[小脚本] maya 命令行常用操作

其实这些代码大部分是从 chatgpt 中生成的。

骨骼命名

import maya.cmds as cmds

def rename_bones():
    selected_bones = cmds.ls(type="joint")  # 获取选中的骨骼

    for bone in selected_bones:
        if "_" in bone:
            new_name = bone.split("_")[0]  # 获取下划线前面的部分作为新的骨骼名称
            cmds.rename(bone, new_name)  # 重命名骨骼

rename_bones()

层级 rename

import maya.cmds as cmds

def rename_bones_with_suffix(bone, suffix):
    children = cmds.listRelatives(bone, children=True, type="joint") or []  # 获取骨骼的子骨骼

    for child in children:
        rename_bones_with_suffix(child, suffix)  # 递归调用,处理子骨骼
        
    new_name = bone + suffix  # 添加结尾字符串
    cmds.rename(bone, new_name)  # 重命名骨骼
    print("将骨骼 {} 重命名为 {}".format(bone, new_name))

selected_bones = cmds.ls(selection=True, type="joint")  # 获取选中的骨骼

for bone in selected_bones:
    rename_bones_with_suffix(bone, "_R")

属性赋值

左手旋转复制到右手上

import maya.cmds as cmds

def flip_z_rotation(source_bone, target_bone):
    # 获取源骨骼的旋转值
    source_rotation = cmds.getAttr(source_bone + ".rotate")[0]
    
    # 翻转旋转值的Z轴
    flipped_rotation = [source_rotation[0], source_rotation[1], -source_rotation[2]]
    
    # 将翻转后的旋转值赋值给目标骨骼
    cmds.setAttr(target_bone + ".rotate", flipped_rotation[0], flipped_rotation[1], flipped_rotation[2], type="double3")
    
    print("将骨骼 {} 的旋转值翻转并赋值到骨骼 {}".format(source_bone, target_bone))

all_bones = cmds.ls(type="joint")  # 获取所有骨骼

for bone in all_bones:
    if "_L" in bone:
        # 替换"_L"为"_R"的骨骼
        target_bone = bone.replace("_L", "_R")
        
        # 检查替换后的骨骼是否存在
        if cmds.objExists(target_bone):
            flip_z_rotation(bone, target_bone)

控制台调用批量处理

自己的批量处理框架

# -*- coding: utf-8 -*-

import os
import json
import math
import errno
import numpy as np    

import maya.cmds as cmds
import pymel.core as pm
import pymel.core.nodetypes as nt
import pymel.core.datatypes as dt

from maya import mel 

def SetFPS(fps):
    unit = 'ntscf'
    if fps == 15:
        unit = 'game'
    elif fps == 24:
        unit = 'film'
    elif fps == 25:
        unit = 'pal'
    elif fps == 30:
        unit = 'ntsc'
    elif fps == 48:
        unit = 'show'
    elif fps == 50:
        unit = 'palf'
    elif fps == 60:
        unit = 'ntscf'
    else:
        unit = str(fps)+'fps'

    cmds.currentUnit( time=unit )
    fps = mel.eval('currentTimeUnitToFPS')
    # 等价的
    #mel.eval("currentUnit -time ntsc;")
    return fps

class Cls_get_pure_bone:
    def __init__(self, bones, dstRoot=None, fps=30):
        
        self.use_joints = bones
        self.dstRoot = dstRoot
        self.fps = fps    

    def setup(self):
        cmds.file(new=True, force=True)
        if self.fps == 30:
            mel.eval("currentUnit -time ntsc;")
            self._import_fps = False
        else:
            SetFPS(self.fps)
            self._import_fps = False
            #self._import_fps = True
        

    def run(self, animFbx, outFn, targetOnly=True):
        
        # import source animation
        pm.importFile(
            animFbx, 
            type='FBX',
            importFrameRate=self._import_fps,
            importTimeRange='override'
        )

        startFrame = pm.playbackOptions(animationStartTime=True, q=True)
        endFrame   = pm.playbackOptions(animationEndTime=True, q=True)
    
        def string_array_contains(array, string):
            for item in array:
                if item == string:
                    return True  # 包含指定字符串
            return False  # 不包含指定字符串

        all_joints=cmds.ls(type="joint")
        # 遍历所有骨骼
        for joint in all_joints:
            # 检查当前骨骼是否在给定的骨骼列表中
            if not string_array_contains(self.use_joints, joint):
            # 检查当前骨骼是否在给, joint):
                # 删除不在列表中的骨骼
                if cmds.objExists(joint):
                    print("删除骨骼 " + joint)
                    cmds.delete(joint)
                else:
                    print("骨骼 " + joint + " 不存在")
       
        pm.playbackOptions(animationStartTime=startFrame, e=True)
        pm.playbackOptions(minTime=startFrame, e=True)
        pm.playbackOptions(animationEndTime=endFrame, e=True)
        pm.playbackOptions(maxTime=endFrame, e=True)
        
        # export retargeted anim
        if targetOnly:
            pm.select(self.dstRoot)
            pm.exportSelected(outFn, type='FBX export', force=True)
        else:
            pm.exportAll(outFn, type='FBX export', force=True) 
        return outFn  

 
if __name__ == '__main__':
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--inputAnimFile', type=str, default=None, help='Input Anim Fbx')
    
    parser.add_argument('--inputFolder', type=str, default=None, help='Input Fbx Directory, batch mode')
    parser.add_argument('--outputFolder', type=str, default=None, help='Output Fbx Directory')
    parser.add_argument('--resume', action='store_true', help='skip exist or redo')
    parser.add_argument('--targetOnly', action='store_true', help='only keep target char')
 
    parser.add_argument('--dstRoot', type=str, default='')
    parser.add_argument('--fps', type=int, default=30)

    args = parser.parse_args()
    
    file_path = "scripts/data/coco_bone.txt"

    # 打开文件
    with open(file_path, "r") as file:
        # 按行读取文件内容
        bones = [ e.strip() for e in file.readlines() ]
    
    # list input files
    if args.inputFolder is None:
        inputFiles = [args.inputAnimFile]
        inputFolder = os.path.dirname(args.inputAnimFile)
    else:
        from pathlib import Path
        if not os.path.isdir(args.inputFolder):
            # regex pattern in arg
            pattern = os.path.basename(args.inputFolder)
            inputFolder = os.path.dirname(args.inputFolder)
        else:
            # directory
            inputFolder = args.inputFolder
            # pattern = r'**/*_anim.fbx'
            pattern = r'**/*.fbx'
            
        inputFiles = sorted([str(f) for f in Path(r'{0}'.format(inputFolder)).glob(pattern)])
        
    
    if args.outputFolder is None:
        outputFolder = inputFolder
    else:
        outputFolder = args.outputFolder
    
    cls = Cls_get_pure_bone(
        bones,
        dstRoot=args.dstRoot,
        fps=args.fps
    )
    
    cls.setup()

    for inputFile in inputFiles:
        relpath  = os.path.relpath(os.path.dirname(inputFile), inputFolder)        
        
        fout  = os.path.join(outputFolder, relpath) + f"/{os.path.basename(inputFile)}"
        
        ddir=fout.rsplit("/",1)[0]
        if not os.path.exists(ddir):
            os.makedirs(ddir)
        
        print('-- work on file: {0}'.format(inputFile))
        if args.resume and os.path.exists(fout):
            print('-- skip {0}'.format(inputFile))
            continue
        
        cls.run(inputFile, fout)
        

调用方式

@echo off
setlocal

rem 

"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" /path/get_pure_bone.py ^
    --inputFolder  \path\fbx_org ^
    --dstRoot DeformationSystem ^
    --outputFolder \path\fbx_org_clear ^
    --targetOnly --fps 30

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/350689.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue day06

1、路由模块封装 2、声明式导航 实现导航高亮效果 直接通过这两个类名对相应标签设置样式 点击a链接进入my页面时,a链接 我的音乐高亮,同时my下的a、b页面中的 我的音乐也有router-link-active类,但没有精确匹配的类(只有my页…

HTTP连接池在Java中的应用:轻松应对网络拥堵

网络拥堵是现代生活中无法避免的问题,尤其是在我们这个“点点点”时代,网页加载速度直接影响到我们的心情。此时,我们需要一位“救世主”——HTTP连接池。今天,就让我们一起探讨一下,这位“救世主”如何在Java中大显神…

12个强大的 JavaScript 动画库,可帮助你提升用户体验

文章目录 12个强大的 JavaScript 动画库,可帮助你提升用户体验1.Anime.js2.Lottie3. Velocity4.Rough Notation5.Popmotion6. Vivus7.GSAP:Green Stocking Animation Platform8. Three.js9.ScrollReveal10.Barba.js11.Mo.js12.Typed.js总结 12个强大的 J…

【Python】01快速上手爬虫案例一:搞定豆瓣读书

文章目录 前言一、VSCodePython环境搭建二、爬虫案例一1、爬取第一页数据2、爬取所有页数据3、格式化html数据4、导出excel文件 前言 实战是最好的老师,直接案例操作,快速上手。 案例一,爬取数据,最终效果图: 一、VS…

降维(Dimensionality Reduction)

1.动机一:数据可视化 将数据可视化,我们便能寻找到一个更好的解决方案,降维可以帮助我们。 假使我们有有关于许多不同国家的数据,每一个特征向量都有 50 个特征(如 GDP,人均 GDP,平均寿命等&a…

python深度学习—第6章(波斯美女)

第6章 深度学习用于文本和序列 6.1 处理文本数据 与其他所有神经网络一样,深度学习模型不会接收原始文本作为输入,它只能处理数值张量。 文本向量化(vectorize)是指将文本转换为数值张量的过程。它有多种实现方法。 将文本分割…

力扣80、删除有序数组中的重复项Ⅱ(中等)

1 题目描述 图1 题目描述 2 题目解读 对于有序数组nums,要求在不使用额外数组空间的条件下,删除数组nums中重复出现的元素,使得nums中出现次数超过两次的元素只出现两次。返回删除后数组的新长度。 3 解法一:双指针 双指针法可以…

【代码随想录-数组】二分查找

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

学习笔记-李沐动手学深度学习(四)(12-13,权重衰退、L2正则化、Dropout)

总结 【trick】过拟合及正则化项参数的理解 实际数据都有噪音,一般有噪音后,模型实际学习到的权重w就会比 理论上w的最优解(即没有噪音时)大。(QA中讲的) 【好问题】 (1)不使用正…

Jupyter Notebook安装以及简单使用教程

Jupyter Notebook安装以及简单使用教程 本文章将,简要的讲解在已经拥有Python环境下如何进行Jupyter Notebook的安装。并且简短的介绍Jupyter Notebook的使用方法。 Jupyter Notebook是什么 Jupyter Notebook是一个基于Web的交互式计算环境,它支持多种…

101.乐理基础-五线谱-五线谱的构造、谱号是什么

内容参考于:三分钟音乐社 上一个内容:100.乐理基础-五线谱-是否需要学习五线谱-CSDN博客 首先简谱的构造,如下图:真正影响音乐的是左上角的三部分,调号、拍号、情绪与速度,如图1 然后不管用什么谱&#xf…

代码随想录第十七天| ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和

文章目录 110.平衡二叉树思路-递归:代码: 思路二-迭代 257. 二叉树的所有路径思路一:普通递归 思路二:递归优化思路三:迭代法(没细看) 404.左叶子之和思路-递归 110.平衡二叉树 思路-递归&#…

解决WinForms跨线程操作控件的问题

解决WinForms跨线程操作控件的问题 介绍 在构建Windows窗体应用程序时,我们通常会遇到需要从非UI线程更新UI元素的场景。由于WinForms控件并不是线程安全的,直接这样做会抛出一个异常:“控件’control name’是从其他线程创建的,…

Oracle DG环境下的秘钥管理

今天有朋友问到1)DG环境下的秘钥管理需要注意什么,2)秘钥管理对DG的日志同步有影响吗? 对于2)的回答是明确的,没有影响。秘钥的管理和DG的redo log shipping完全是两套机制。在最新版的Oracle Key Vault常…

基于YOLOv7算法的高精度实时五类动物目标检测系统(PyTorch+Pyside6+YOLOv7)

摘要:基于YOLOv7算法的高精度实时五类动物目标检测系统可用于日常生活中检测与定位狼、鹿、猪、兔和浣熊,此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别,同时本系统还支持检测结果可视化与导出。本系统采用YOLOv7目标…

多数据源 dynamic-datasource 模块使用

在项目中引入dynamic-datasource该modul 在application.yml中添加 dynamic:datasource:slave1: driver-class-name: oracle.jdbc.OracleDriverurl: jdbc:oracle:thin:XXX:orcl_tjhusername: XXpassword: XXvalidation-query: SELECT 1 FROM DUALslave2: driver-class-name: co…

广东建筑模板厂家批发-建筑木模板市场供应

近年来,随着建筑行业的快速发展,建筑模板作为一种不可或缺的建筑材料,备受关注。广东作为中国建筑业的重要发展地区之一,其建筑模板市场也日渐繁荣。在这个市场中,建筑模板厂家能强优品木业成为了备受青睐的选择&#…

操作符详解(上)

目录 操作符的分类 二进制和进制转换 2进制转10进制 10进制转2进制数字 2进制转8进制 2进制转16进制 原码、反码、补码 移位操作符 左移操作符 右移操作符 位操作符:&、|、^、~ 单目操作符 逗号表达式 操作符的分类 • 算术操作符: …

大数据学习之Flink,了解Flink的多种部署模式

目录 一、部署模式 1. 部署模式分类: 1.1 会话模式(Session Mode): 优点: 缺点: 1.2 单作业模式(Per-Job Mode): 优点: ​ 缺点: ​ 1.3…

Kubernetes/k8s之安全机制:

k8s当中的安全机制 核心是分布式集群管理工具,容器编排,安全机制核心是:API SERVER作为整个集群内部通信的中介,也是外部控制的入口,所有的安全机制都是围绕api server开设计的。 请求api资源 1、认证 2、鉴权 3、准入机制 三…
最新文章