MotionBuilder自制插件
可以快速绑定,视频链接地址:
UE4自制开源动画重定向插件_哔哩哔哩_bilibili
# -*- coding: utf-8 -*-
from pyfbsdk import *
from pyfbsdk_additions import *
import xml.etree.ElementTree as ET
import _winreg
from os import walk
import os.path
import os
import glob
import re
#python api https://help.autodesk.com/view/MOBPRO/2019/ENU/?guid=__py_ref_index_html
#获取系统默认路径
def GetWindowsOSDesktopPath():key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')desktopFilepath = _winreg.QueryValueEx(key, 'Desktop')[0] return str(desktopFilepath)class MotionBuilderTool:def __init__(self):self.tool = FBCreateUniqueTool('快速动画重定向插件')self.tool.StartSizeX = 650self.tool.StartSizeY = 650#窗口布局self.PopulateconfigLayout(self.tool)ShowTool(self.tool)#窗口销毁事件回调self.tool.OnUnbind.Add(self.OnToolDestroy)self.LoadConfigHistory()def LoadConfigHistory(self):self.modelFileEdit = 'C:\\Users\\26593\\Desktop\\demo\\SK_Mannequin.FBX'self.skeletonDefinitionTemplateEdit = 'C:\\Users\\26593\\Desktop\\demo\\template.xml'self.TPoseConfigEdit = ''self.animationRepositoryEdit = 'C:\Users\\26593\\Desktop\demo\\animationRepository'self.outputEdit = 'C:\Users\\26593\\Desktop\\demo\\outputEdit'self.MergeEdit = 'C:\\Users\\26593\\Desktop\\demo\\Ying6_Tpos.FBX'#窗口销毁事件回调def OnToolDestroy(self, control, event):FBSystem().Scene.OnChange.Remove(SceneChanged)#窗口布局def PopulateconfigLayout(self, mainLayout):#配置大小区域x = FBAddRegionParam(10, FBAttachType.kFBAttachLeft, '')y = FBAddRegionParam(20, FBAttachType.kFBAttachTop, '')w = FBAddRegionParam(-10, FBAttachType.kFBAttachRight, '')h = FBAddRegionParam(600, FBAttachType.kFBAttachNone, '')mainLayout.AddRegion('Config', '', x, y, w, h)#创建纵向布局configLayout = FBVBoxLayout()mainLayout.SetControl('Config', configLayout)mainLayout.SetBorder('Config', FBBorderStyle.kFBStandardBorder ,True, True,2,2,200,0)#打开路径Button_1 = FBButton()Button_1.Look = FBButtonLook.kFBLookColorChangeButton_1.OnClick.Add(self.OpenModelFile)Button_1.Caption = '打开路径'configLayout.Add(Button_1, 50)#加载模型Button_2 = FBButton()Button_2.Look = FBButtonLook.kFBLookColorChangeButton_2.OnClick.Add(self.LoadModelFile)Button_2.Caption = '加载模型'configLayout.Add(Button_2, 50)#定义骨架Button_3 = FBButton()Button_3.Look = FBButtonLook.kFBLookColorChangeButton_3.OnClick.Add(self.DefineSkeleton)Button_3.Caption = '定义骨架'configLayout.Add(Button_3, 50)#把骨架映射到motion默认的系统上Button_4 = FBButton()Button_4.Look = FBButtonLook.kFBLookColorChangeButton_4.OnClick.Add(self.Characterize)Button_4.Caption = '映射'configLayout.Add(Button_4, 50)"""#跳转到控制面板Button_5 = FBButton()Button_5.Look = FBButtonLook.kFBLookColorChangeButton_5.OnClick.Add(self.PlotToControlRig)Button_5.Caption = '跳转到控制面板'configLayout.Add(Button_5, 50)#加载动画到重定向目标Button_6 = FBButton()Button_6.Look = FBButtonLook.kFBLookColorChangeButton_6.OnClick.Add(self.LoadAnimationForRetargeting)Button_6.Caption = '加载动画到重定向目标'configLayout.Add(Button_6, 50)"""#打开MergeButton_7 = FBButton()Button_7.Look = FBButtonLook.kFBLookColorChangeButton_7.OnClick.Add(self.OpenMerge)Button_7.Caption = '打开Merge'configLayout.Add(Button_7, 50)#选sourceButton_8 = FBButton()Button_8.Look = FBButtonLook.kFBLookColorChangeButton_8.OnClick.Add(self.SetSource)Button_8.Caption = '选Source'configLayout.Add(Button_8, 50)#添加角色动画轨道Button_10 = FBButton()Button_10.Look = FBButtonLook.kFBLookColorChangeButton_10.OnClick.Add(self.AddCharacterAnimationTrack)Button_10.Caption = '添加角色动画轨道'configLayout.Add(Button_10, 50)#烘焙动画到新骨骼Button_9 = FBButton()Button_9.Look = FBButtonLook.kFBLookColorChangeButton_9.OnClick.Add(self.PlotSkeleton)Button_9.Caption = '烘焙动画到新骨骼'configLayout.Add(Button_9, 50)#输出动画Button_11 = FBButton()Button_11.Look = FBButtonLook.kFBLookColorChangeButton_11.OnClick.Add(self.SaveAnimationFile)Button_11.Caption = '输出动画'configLayout.Add(Button_11, 50)#打开模型文件def OpenModelFile(self, contorl, event):# 创建弹出窗口并设置必要的初始值filePopup = pyfbsdk.FBFilePopup()filePopup.Caption = '选择你的原始动画文件'filePopup.Style = pyfbsdk.FBFilePopupStyle.kFBFilePopupOpenfilePopup.Filter = '*.fbx'# 设置默认路径(假设我们使用windows操作系统)filePopup.Path = GetWindowsOSDesktopPath()# 让GUI显示出来bResult = filePopup.Execute()if bResult:self.modelFileEdit = filePopup.FullFilename#打开骨骼定义映射表def OpenSkeletonDefinitionTemplateFile(self, contorl, event):# 创建弹出窗口并设置必要的初始值filePopup = pyfbsdk.FBFilePopup()filePopup.Caption = '选择您的骨骼定义映射表'filePopup.Style = pyfbsdk.FBFilePopupStyle.kFBFilePopupOpenfilePopup.Filter = '*.xml'# 设置默认路径(假设我们使用windows操作系统)filePopup.Path = GetWindowsOSDesktopPath()# 让GUI显示出来bResult = filePopup.Execute()if bResult:self.skeletonDefinitionTemplateEdit= filePopup.FullFilename#打开动画存储文件夹def OpenAimationRepositoryFolder(self, contorl, event):# 创建弹出窗口并设置必要的初始值folderPopup = pyfbsdk.FBFolderPopup()folderPopup.Caption = '选择您的动画存储文件夹'# 设置默认路径(假设我们使用windows操作系统)folderPopup.Path = GetWindowsOSDesktopPath()# 让GUI显示出来result = folderPopup.Execute()if result:self.animationRepositoryEdit = folderPopup.Path#打开输出文件夹def OpenOutputFolder(self, contorl, event):# 创建弹出窗口并设置必要的初始值folderPopup = pyfbsdk.FBFolderPopup()folderPopup.Caption = '选择您的输出文件夹'# 设置默认路径(假设我们使用windows操作系统)folderPopup.Path = GetWindowsOSDesktopPath()# 让GUI显示出来result = folderPopup.Execute()if result:self.outputEdit = folderPopup.Path#加载模型文件def LoadModelFile(self, control, event): targetFilepath = self.modelFileEditif targetFilepath == '':FBMessageBox( 'Config','没有模型文件路径', 'OK', None, None )returnapp = FBApplication()app.FileNew()loadOption = FBFbxOptions(True)loadOption.NamespaceList = 'UE4'app.FileOpen(targetFilepath, True, loadOption)#定义骨架def DefineSkeleton(self, control, event):skeletonDefinitionTemplateFilepath = self.skeletonDefinitionTemplateEditif skeletonDefinitionTemplateFilepath == '':FBMessageBox( 'Config', '无框架定义模板文件路径.', 'OK', None, None )return# 待办事项:在这里需要验证操作currentCharacter = FBApplication().CurrentCharacter# 如果没有角色,就创造一个if currentCharacter == None: currentCharacter = FBCharacter('UE4:Character')FBApplication().CurrentCharacter = currentCharactertree = ET.parse(skeletonDefinitionTemplateFilepath)root = tree.getroot()# 待办事项:现在这里没有匹配操作for elem in tree.iter(tag='item'):jointName = 'UE4:'+elem.attrib['value']targetLinkSlotName = elem.attrib['key'] + 'Link'if jointName == '':continuejoint = FBFindModelByLabelName(jointName)if joint == None:print('骨架定义模板中的意外连接: %s' % (jointName))else:property = currentCharacter.PropertyList.Find(targetLinkSlotName)property.removeAll()property.append (joint)#动画文件是否存在def IsAnimationFileValid(self, animationFileFullFilename):# 获取目标网格文件名targetMeshFullFilename = self.modelFileEdittargetMeshBasename = os.path.basename(targetMeshFullFilename)targetMeshName,_ = os.path.splitext(targetMeshBasename)baseName = os.path.basename(animationFileFullFilename)fileNameWithoutExtention,_ = os.path.splitext(baseName)parttern = targetMeshName + r'_Ani_\w+'match = re.search(parttern, fileNameWithoutExtention ) result = not match == Nonereturn result#在存储库文件夹中找到动画def FindAnimationInRepositoryFolder(self, control, event):self.foundlAnimationFileList.Items.removeAll()animationRepositoryFolder = self.animationRepositoryEditbValidFolderPath = os.path.isdir(animationRepositoryFolder)if not bValidFolderPath:FBMessageBox( 'Config','无效的动画存储库文件夹', 'OK', None, None )returnfoundFbxFiles = glob.glob(animationRepositoryFolder +'/*.fbx')for f in foundFbxFiles:if self.IsAnimationFileValid(f):self.foundlAnimationFileList.Items.append(f)# 如果没有找到动画文件就打印if self.foundlAnimationFileList.Items.len == 0:print('没有发现动画')return#描述-把骨架映射到motion默认的系统上def Characterize(self, control, event):currentCharacter = FBApplication().CurrentCharacterif currentCharacter == None:FBMessageBox( 'Config', '没有定义角色', 'OK', None, None )return # 这里的True指的是两足动物的特征currentCharacter.SetCharacterizeOn(True)FBSystem().Scene.Evaluate()#跳转到控制面板def PlotToControlRig(self, control, event):currentCharacter = FBApplication().CurrentCharacterif currentCharacter == None:FBMessageBox( 'Config', '没有定义角色', 'OK', None, None )return # 禁用并删除控制RigcurrentCharacter.ActiveInput = FalsecontrolRig = currentCharacter.GetCurrentControlSet()# 如果没有控制Rig,就创建一个新的if not controlRig:# 使用“True”参数指定的正运动学和逆运动学创建一个控制RigbCreationResult = currentCharacter.CreateControlRig(True)if not bCreationResult:print('在PlotToControlRig中创建新的控制rig失败,请检查')plotOptions = FBPlotOptions()plotOptions.ConstantKeyReducerKeepOneKey = FalseplotOptions.PlotAllTakes = True plotOptions.PlotOnFrame = TrueplotOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )plotOptions.PlotTranslationOnRootOnly = FalseplotOptions.PreciseTimeDiscontinuities = FalseplotOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnrollplotOptions.UseConstantKeyReducer = FalsecurrentCharacter.PlotAnimation (FBCharacterPlotWhere.kFBCharacterPlotOnControlRig,plotOptions )#加载动画到重定向目标def LoadAnimationForRetargeting(self, control, event):fbxOptions = FBFbxOptions( True )fbxOptions.TransferMethod = FBCharacterLoadAnimationMethod.kFBCharacterLoadRetargetplotOptions = FBPlotOptions()animFile = 'C:\Users\26593\Desktop\demo\Bow_Run_Fwd_45_L.fbx'currentCharacter = FBApplication().CurrentCharacterif currentCharacter == None:FBMessageBox( 'Config', '没有定义角色', 'OK', None, None )return FBApplication().LoadAnimationOnCharacter( animFile, currentCharacter, fbxOptions, plotOptions )#执行测试def ExecuteTest(self, control, event): # 首先,清除场景并打开目标网格文件# 从框架模板定义# 描述# 控制Rig# 指定动画文件# 加载动画self.FindAnimationInRepositoryFolder() #打开Mergedef OpenMerge(self, control, event): # 文件路径nativeFile = self.MergeEditoptions = FBFbxOptions(True, nativeFile)options.SetAll(FBElementAction.kFBElementActionMerge, True)for takeIndex in range( 0, options.GetTakeCount() ):# 取消选择optionsoptions.SetTakeSelect( takeIndex, True )FBApplication().FileMerge( nativeFile, False, options )#选sourcedef SetSource(self, control, event): # 选characterfoundComponents = FBComponentList()# 选characterFBFindObjectsByName('Character', foundComponents, True, False)Character = foundComponents[0]Character.Selected = True# 选sourcefoundComponents = FBComponentList()FBFindObjectsByName('UE4:Character', foundComponents, True, False)OldCharacter = foundComponents[0]Character.InputCharacter = OldCharacterCharacter.InputType = FBCharacterInputType.kFBCharacterInputCharacterCharacter.ActiveInput = True#烘焙动画到新骨骼def PlotSkeleton(self, control, event): myPlotOptions = FBPlotOptions ()myPlotOptions.ConstantKeyReducerKeepOneKey = FalsemyPlotOptions.PlotAllTakes = FalsemyPlotOptions.PlotOnFrame = TruemyPlotOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )myPlotOptions.PlotTranslationOnRootOnly = FalsemyPlotOptions.PreciseTimeDiscontinuities = FalsemyPlotOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterNonemyPlotOptions.UseConstantKeyReducer = FalseTheChar = FBApplication().CurrentCharacterif TheChar.ActiveInput == True:TheChar.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, myPlotOptions)else:TheChar.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, myPlotOptions)#添加角色动画轨道def AddCharacterAnimationTrack(self, control, event): lParentTrack = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter)#把当前角色赋予轨道foundComponents = FBComponentList()FBFindObjectsByName('UE4:Character', foundComponents, True, False)Character = foundComponents[0]lParentTrack.Details.append(Character)#保存当前动画文件def SaveAnimationFile(self, control, event): # 创建所有的类实例lSystem = FBSystem()lApp = FBApplication()lScene = lSystem.Scene#开始保存当前动画lOptions = FBFbxOptions(False)## 保存选项lOptions.SaveCharacter = FalselOptions.SaveControlSet = TruelOptions.SaveCharacterExtension = Falseif len( lScene.Characters ) > 0:lApp.SaveCharacterRigAndAnimation(self.animationRepositoryEdit + '\\Ying6_Bow_Run_Fwd_45_L.fbx', lScene.Characters[0], lOptions)MotionBuilderTool()
MotionBuilder自制插件相关推荐
- chrome自制插件--百度搜索结果去广告1.0
chrome自制插件--百度搜索结果去广告1.0 一.前言 二.效果 三.说明 四.安装 五.下载 一.前言 国内用户用百度的占绝大多数,但是百度搜索结果的广告真烦人,特别是搜索"黄金&qu ...
- chrome自制插件--动易网站后台一键登录v1.4
动易网站后台一键登录v1.4 一.介绍 二.功能 三.安装 四.使用 五.GitHub源码 一.介绍 上篇<chrome自制插件–简单一键登录(附插件开发介绍)>我介绍了chrome插件开 ...
- MotionVenus·MotionBuilder实时插件
MotionVenus·MotionBuilder实时插件 1.1 简介 (1) ...
- chrome自制插件--简单一键登录(附插件开发介绍)
chrome自制插件--简单一键登录(附插件开发介绍) 一.前言 二.需求 三.文件结构及代码 3.1 第一步:建立文件 3.2 第二步:修改manifest.json,配置插件 3.3 第三步:修改 ...
- 【自制插件】B站专栏语音朗读器 v1.0 专栏你太美
这两天下班没事的时候,稍微自制了个简单的B站专栏朗读器插件.什么样的呢? 就这样!2333333333333. (渣渣前端程序员一枚,高科技啥的就不会搞了,只会写点小东西维持生活这样子) (然而该插件 ...
- 【自制插件】将MMD4Mecanim转换的MMD模型导入maya
这个已经废弃了_(:зゝ∠)_,另外做了升级版: http://www.cnblogs.com/marisa/p/5174150.html ============================== ...
- sql server 怎么把视图中的数据存到另外一张表中_承上篇,自制插件优化Kep数据存储问题...
序言:上篇说到Kep数据日志存储是将所有数据存到一张表内,不好筛选,为此抽空做了这个插件对Kep存到SQL的数据表进行优化处理. 一.插件安装及界面功能标注 1.双击安装包弹出安装向导,直接下一步直到 ...
- idea如何自制插件_Lice IntelliJ插件图标制作过程
这是只属于没有Photoshop的人的悲哀. 首先先大吼一声--劳资终于做出了高清无码的Lice图标! 直接进入正题 其实我还是想说一下事情的发展过程的-- 我想照着IntelliJ IDEA的图标风 ...
- idea如何自制插件_Minecraft插件开发教程-开发环境配置 [原创]
Hello 各位小阔爱们好 时隔2个多月 我又回来了 这一期专栏有些特别 让我们一起来制作一个简单的Minecraft插件吧~ 本教程为原创作品 不得随意转载 求硬币 收藏 点赞 关注! 写专栏是贞德 ...
最新文章
- asp.net的定义
- 编写python程序输出图形_python 图形化编程---文本输入框
- python urllib.request 爬虫 数据处理-使用Python3.5写简单网络爬虫
- python学习-序列化对象(pickle)
- 《深入理解Java虚拟机》读书笔记八
- java中怎样上传zip_java服务器如何对zip文件分包上传?
- unity 2d文字跟随主角移动_时间回溯——用Unity实现时空幻境(Braid)中的控制时间效果...
- 汽车诊断协议UDS概述
- linux dstat,dstat 用法详解
- 正切函数半角定理推导
- matlab读取nc\hdf\grd等气象文件 自用
- 机器视觉(四)——打光
- 2019.11.2图论专题(AtCoder Splatter Painting、President and Roads、Shortest Cycle、ISlands II)
- 创新创意springboot计算机毕业设计题目300例,总有你需要用到的!
- 全开源办公开发平台——手机移动端APP功能简介
- ApacheCN 翻译活动进度公告 2019.4.15
- sqlyog修改背景颜色成护眼色
- 【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 新发出品 良心教程)
- Windows 8.1 归档 —— Step 3 软件的选择与安装
- 彻底解决让用户清一下浏览器缓存
热门文章
- 很高兴,今天开了博客
- thinkphp开发app商城项目源码下载(thinkphp)
- 为什么拼团电商APP能成功?
- ClickHouse 在网易的实践
- 赋予角色生命的游戏配音技巧
- TypeScript(七)泛型、声明合并、扩展阅读
- 汽车方向盘电子助力转向器如何接线_相比于液压助力,电子助力有什么优势?...
- 微生物组-宏基因组分析专题研讨会(2022.4,线下)
- 西门子S7-300控制PVC配料注塑机程序 称重仪表通讯,模拟量控制
- Matnote_2_数据的同质性 Data Homogeneity