Files
gtav-src/tools_ng/techart/dcc/motionbuilder2014/python/RS/Utils/Creation.py
T
2025-09-29 00:52:08 +02:00

358 lines
14 KiB
Python
Executable File

"""
## Written And Maintained By: David Bailey
## Contributors: Kristine Middlemiss
## Description: A list of commonly used functions to create scene objects and to simplify and speed
## up tool production. This also signifies a turning point to minimise the duplication
## of code in new tools.
##
## Rules: Definitions: Prefixed with "rs_"
## Global Variables: Prefixed with "g"
## Local Variables: Prefixed with "l"
## Iteration Variables: Prefixed with "i"
## Arguments: Prefixed with "p"
##
"""
from pyfbsdk import *
import os
import re
import sys
import webbrowser
import RS.Globals as glo
import RS.Config
from RS.Utils.Scene.Component import SetProperties
from RS.Utils.Scene import Constraint
###############################################################################################################
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
##
## Description: The yellow Rockstar Banner that should be used at the top of EVERY tool
##
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
###############################################################################################################
def rs_OnEmailClickCallback(pControl, pEvent):
if gCc == None:
os.startfile("mailto:" + gEmailTo + "&Subject= "+ gToolName+ "&Body=" +gToolPath)
else:
os.startfile("mailto:" + gEmailTo + "?CC=" + gCc + "&Subject= "+ gToolName+ "&Body=" +gToolPath)
def rs_OnInfoClickCallback(pControl, pEvent):
if gWikiLink == None:
FBMessageBox("Information", "Sorry, there is no Wiki page for this UI...YET :)", "Ok")
else:
lNew = 2
webbrowser.open(gWikiLink)
def rs_CreateBanner( parentLyt, lToolName, lEmailTo, lToolPath, lCc=None, lWikiLink=None):
# HouseKeeping
global gToolName
gToolName = lToolName
global gEmailTo
gEmailTo = lEmailTo
global gToolPath
gToolPath = lToolPath
global gCc
gCc = lCc
global gWikiLink
gWikiLink = lWikiLink
# Rockstar Logo
titlex = FBAddRegionParam(0,FBAttachType.kFBAttachLeft,"")
titley = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
titlew = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
titleh = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
parentLyt.AddRegion("Title","Title", titlex,titley,titlew,titleh)
titleImg = FBImageContainer()
titleImg.Filename = "{0}\\YellowRockstarLogo_30x30.jpg".format( RS.Config.Script.Path.ToolImages )
parentLyt.SetControl("Title",titleImg)
# Spacer
spacerx = FBAddRegionParam(30,FBAttachType.kFBAttachLeft,"")
spacery = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
spacerw = FBAddRegionParam(-60,FBAttachType.kFBAttachRight,"")
spacerh = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
parentLyt.AddRegion("Spacer","Spacer", spacerx,spacery,spacerw,spacerh)
spacerImg = FBImageContainer()
spacerImg.Filename = "{0}\\YellowSpacerBanner.jpg".format( RS.Config.Script.Path.ToolImages )
parentLyt.SetControl("Spacer",spacerImg)
# Send an email about the tool logo
lEmailX = FBAddRegionParam(-60,FBAttachType.kFBAttachRight,"")
lEmailY = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
lEmailW = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
lEmailH = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
parentLyt.AddRegion( "lEmail","lEmail", lEmailX, lEmailY, lEmailW, lEmailH )
lEmailContainer = FBVisualContainer()
parentLyt.SetControl( "lEmail", lEmailContainer)
lEmailContainer.OnChange.Add(rs_OnEmailClickCallback)
lEmailImage = "{0}\\email_icon_yellow.tif".format( RS.Config.Script.Path.ToolImages )
lEmailContainer.Items.append("")
lEmailContainer.ItemIconSet(0, lEmailImage)
lEmailContainer.ItemWidth = 27
lEmailContainer.ItemHeight = 44
lEmailContainer.ItemWrap = True
# Find more information on the wiki about the tool logo
lInfoX = FBAddRegionParam(-30,FBAttachType.kFBAttachRight,"")
lInfoY = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
lInfoW = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
lInfoH = FBAddRegionParam(30,FBAttachType.kFBAttachNone,None)
parentLyt.AddRegion( "lInfo","lInfo", lInfoX, lInfoY, lInfoW, lInfoH )
lInfoContainer = FBVisualContainer()
parentLyt.SetControl( "lInfo", lInfoContainer)
lInfoContainer.OnChange.Add(rs_OnInfoClickCallback)
lInfoImage = "{0}\\information_icon_yellow.tif".format( RS.Config.Script.Path.ToolImages )
lInfoContainer.Items.append("")
lInfoContainer.ItemIconSet(0, lInfoImage)
lInfoContainer.ItemWidth = 27
lInfoContainer.ItemHeight = 44
lInfoContainer.ItemWrap = True
return parentLyt
def rs_CreateFolder(pName, pLocation):
"""
Creates a folder with a specific name under the given location
Arguments:
pName (string): name for the folder
pLocation (string or FBComponent): location to put folder under, accepts strings and pyfbsdk classes that
inherit FBComponent
Return:
FBFolder
"""
FBMethodDictionary = {
"Actor Faces" : "FBActorFace",
"Actors" : "FBActor",
"Audio Clips" : "FBAudioClip",
"Cameras" : "FBCamera",
"Character Extensions": "FBCharacterExtension",
"Character Faces": "FBCharacterFace",
"Character Poses": "FBCharacterPose",
"Characters" : "FBCharacter",
"Constraints 1" : "FBConstraintSolver",
"Constraints" : "FBConstraintSolver",
"Control Rigs" : "FBControlSet",
"Lights" : "FBLight",
"Materials" : "FBMaterial",
"Notes" : "FBNote",
"Poses" : "FBPose",
"Sets" : "FBSet",
"Shaders" : ["FBShaderManager", "CreateShader(ZShader)"],
"Takes" : ["FBTake", "CopyTake"],
"Textures" : "FBTexture",
"VideoClips" : "FBVideoClipImage",
"Videos" : "FBVideoClipImage",
"FBShader" : ["FBShaderManager", "CreateShader(ZShader)"],
"FBTake" : ["FBTake", "CopyTake"],
"FBConstraint" : "FBConstraintSolver",
"FBConstraintRelation": "FBConstraintSolver"
}
fbtype = None
# Check if the location passed is a class from the pyfbsdk and if it is to
# get the name of that class
if hasattr(pLocation, "__module__") and pLocation.__module__ == "pyfbsdk":
fbtype = FBMethodDictionary.get(pLocation.__name__, pLocation.__name__)
if FBMethodDictionary.get(pLocation, None) is None and fbtype is None:
return
methodList = FBMethodDictionary.get(pLocation, None) or fbtype
if not isinstance(methodList, list):
methodList = [methodList]
method = sys.modules["pyfbsdk"]
for eachMethod in methodList:
# Regular Expression to extract arguments from methods
# It returns a list of all strings between
arguments = re.findall("(?<=\()[0-9a-z._ ]+(?=\))", eachMethod, re.I)
eachMethod = eachMethod.split("(")[0]
method = getattr(method, eachMethod)
if eachMethod == methodList[-1] and not arguments:
arguments = ["ToBeDeleted"]
method = method(*arguments)
temporaryModel = method
folder = FBFolder(pName, temporaryModel)
temporaryModel.FBDelete()
return folder
###############################################################################################################
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
##
## Description: Create Folders and Add Component(s) in, if they exist
##
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
###############################################################################################################
def rs_CreateFolderAddComponents(pComponent, pComponentStr, name="", excludeByTypes=[]):
if not name:
name = pComponentStr
lFolder = None
for folder in RS.Globals.Folders:
if folder.Name == name:
lFolder = folder
break
if lFolder == None:
lFolder = rs_CreateFolder(name, pComponentStr)
for iComp in filter(None, pComponent):
if not IsPyfbsdkType(iComp, *excludeByTypes):
lFolder.ConnectSrc(iComp)
return lFolder
###############################################################################################################
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
##
## Description: Create Constraint Folder and Add Component(s) in, if they exist. Exclude FBCharacter &
## FBCharacterSolver url:bugstar:1264071
##
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
###############################################################################################################
def rs_CreateConstraintFolderAddComponents(pComponent, pComponentStr):
lFolder = rs_CreateFolderAddComponents(pComponent, "Constraints", name=pComponentStr,
excludeByTypes=[FBCharacterSolver, FBCharacter])
FBSystem().Scene.Evaluate()
def IsPyfbsdkType(pComponent, *pyfbsdkTypes):
"""
Checks if a model/component from motion builder is of a certain type
:param pComponent: FBComponent() or any object that inherits FBComponent; object to check type
:param pyfbsdkTypes:
:return:
"""
pyfbsdk = sys.modules["pyfbsdk"]
result_list = []
for eachType in pyfbsdkTypes:
if isinstance(eachType, basestring):
eachType = getattr(pyfbsdk, eachType)
result_list.append(isinstance(pComponent, eachType))
return True in result_list
def CreatePath(name, *points, **kwargs):
"""
Creates a Path3D object in the scene with keys at the given points
:param name:
:param points:
:return:
"""
curve = FBModelPath3D(name)
curve.Show = True
EditPath(curve, *points, **kwargs)
return curve
def EditPath(curve, *points, **kwargs):
plot = kwargs.get("Plot", False)
frame = kwargs.get("Frame", FBSystem().LocalTime.GetFrame())
for index, point in enumerate(points):
position = FBVector4d(*point)
try:
# We call PathKeyGet to check if a key already exists
# it will error out if it doesn't
if curve.PathKeyGet(index):
curve.PathKeySet(index, position)
except IndexError:
curve.Segment_PathKeyAdd(index, position)
# Sometimes the first point isn't set
# So we set it again
if not index:
curve.PathKeySet(index, position)
if plot:
property = curve.PropertyList.Find("Point_{}".format(index))
property.SetAnimated(True)
animationNode = curve.PropertyList.Find("Point_{}".format(index)).GetAnimationNode()
animationNode.KeyAdd(FBTime(0, 0, 0, frame), [each for each in position])
return curve
def CreateConstraint(type, name="", *references, **properties):
"""
DEPRECATED FUCNTION! Use:
from RS.Utils.Scene import Constraint
Constraint.CreateConstraint
"""
constraintTypes = {
"Aim" : Constraint.AIM,
"Expression" : Constraint.EXPRESSION,
"Multi Referential" : Constraint.MULTI_REFERENTIAL,
"Parent/Child" : Constraint.PARENT_CHILD,
"Path" : Constraint.PATH,
"Path Constraint" : Constraint.PATH,
"Position" : Constraint.POSITION,
"Range" : Constraint.RANGE,
"Relation" : Constraint.RELATION,
"Rigid Body" : Constraint.RIGID_BODY,
"3 Points" : Constraint.THREE_POINT,
"Rotation" : Constraint.ROTATION,
"Scale" : Constraint.SCALE,
"Mapping" : Constraint.MAPPING,
"Chain IK" : Constraint.CHAIN_IK}
constraint = Constraint.CreateConstraint(constraintTypes[type])
if name:
constraint.Name = name
[constraint.ReferenceAdd(index, component) for index, component in enumerate(references) if component != None]
SetProperties(constraint, **properties)
return constraint
""" Legacy Code"""
###############################################################################################################
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
##
## Description: Create Null Object and name it. This Null object was introduced to the character asset setup
## to keep the scenes clean.
## Requested by Animation
##
##* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
###############################################################################################################
def rs_CreateNullElement(pName, pXpos, pYpos, pZpos):
lNull = FBModelNull(pName)
lNull.Show = False
lNull.Translation = FBVector3d(pXpos, pYpos, pZpos)
return lNull