|
@@ -3,6 +3,7 @@
|
|
|
from direct.showbase.DirectObject import *
|
|
from direct.showbase.DirectObject import *
|
|
|
from pandac.PandaModules import LODNode
|
|
from pandac.PandaModules import LODNode
|
|
|
import types
|
|
import types
|
|
|
|
|
+import copy as copy_module
|
|
|
|
|
|
|
|
class Actor(DirectObject, NodePath):
|
|
class Actor(DirectObject, NodePath):
|
|
|
"""
|
|
"""
|
|
@@ -89,6 +90,7 @@ class Actor(DirectObject, NodePath):
|
|
|
|
|
|
|
|
# create data structures
|
|
# create data structures
|
|
|
self.__partBundleDict = {}
|
|
self.__partBundleDict = {}
|
|
|
|
|
+ self.__subpartDict = {}
|
|
|
self.__sortedLODNames = []
|
|
self.__sortedLODNames = []
|
|
|
self.__animControlDict = {}
|
|
self.__animControlDict = {}
|
|
|
self.__controlJoints = {}
|
|
self.__controlJoints = {}
|
|
@@ -199,6 +201,7 @@ class Actor(DirectObject, NodePath):
|
|
|
|
|
|
|
|
# copy the part dictionary from other
|
|
# copy the part dictionary from other
|
|
|
self.__copyPartBundles(other)
|
|
self.__copyPartBundles(other)
|
|
|
|
|
+ self.__subpartDict = copy_module.deepcopy(other.__subpartDict)
|
|
|
|
|
|
|
|
# copy the anim dictionary from other
|
|
# copy the anim dictionary from other
|
|
|
self.__copyAnimControls(other)
|
|
self.__copyAnimControls(other)
|
|
@@ -245,6 +248,48 @@ class Actor(DirectObject, NodePath):
|
|
|
return "Actor: partBundleDict = %s,\n animControlDict = %s" % \
|
|
return "Actor: partBundleDict = %s,\n animControlDict = %s" % \
|
|
|
(self.__partBundleDict, self.__animControlDict)
|
|
(self.__partBundleDict, self.__animControlDict)
|
|
|
|
|
|
|
|
|
|
+ def listJoints(self, partName="modelRoot", lodName="lodRoot"):
|
|
|
|
|
+ """Handy utility function to list the joint hierarchy of the
|
|
|
|
|
+ actor. """
|
|
|
|
|
+
|
|
|
|
|
+ partBundleDict = self.__partBundleDict.get(lodName)
|
|
|
|
|
+ if not partBundleDict:
|
|
|
|
|
+ Actor.notify.error("no lod named: %s" % (lodName))
|
|
|
|
|
+
|
|
|
|
|
+ truePartName = partName
|
|
|
|
|
+ subset = PartSubset()
|
|
|
|
|
+ subpartDef = self.__subpartDict.get(partName)
|
|
|
|
|
+ if subpartDef:
|
|
|
|
|
+ truePartName, subset = subpartDef
|
|
|
|
|
+
|
|
|
|
|
+ bundle = partBundleDict.get(truePartName)
|
|
|
|
|
+ if bundle == None:
|
|
|
|
|
+ Actor.notify.error("no part named: %s" % (partName))
|
|
|
|
|
+
|
|
|
|
|
+ self.__doListJoints(0, bundle.node().getBundle(),
|
|
|
|
|
+ subset.isEmpty(), subset)
|
|
|
|
|
+
|
|
|
|
|
+ def __doListJoints(self, indentLevel, part, isIncluded, subset):
|
|
|
|
|
+ name = part.getName()
|
|
|
|
|
+ if subset.matchesInclude(name):
|
|
|
|
|
+ isIncluded = True
|
|
|
|
|
+ elif subset.matchesExclude(name):
|
|
|
|
|
+ isIncluded = False
|
|
|
|
|
+
|
|
|
|
|
+ if isIncluded:
|
|
|
|
|
+ value = ''
|
|
|
|
|
+ if hasattr(part, 'outputValue'):
|
|
|
|
|
+ lineStream = LineStream.LineStream()
|
|
|
|
|
+ part.outputValue(lineStream)
|
|
|
|
|
+ value = lineStream.getLine()
|
|
|
|
|
+
|
|
|
|
|
+ print ' ' * indentLevel, part.getName(), value
|
|
|
|
|
+
|
|
|
|
|
+ for i in range(part.getNumChildren()):
|
|
|
|
|
+ self.__doListJoints(indentLevel + 2, part.getChild(i),
|
|
|
|
|
+ isIncluded, subset)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def getActorInfo(self):
|
|
def getActorInfo(self):
|
|
|
"""
|
|
"""
|
|
|
Utility function to create a list of information about an actor.
|
|
Utility function to create a list of information about an actor.
|
|
@@ -255,7 +300,8 @@ class Actor(DirectObject, NodePath):
|
|
|
partDict = self.__animControlDict[lodName]
|
|
partDict = self.__animControlDict[lodName]
|
|
|
partInfo = []
|
|
partInfo = []
|
|
|
for partName in partDict.keys():
|
|
for partName in partDict.keys():
|
|
|
- partBundle = self.__partBundleDict[lodName][partName]
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ partBundle = self.__partBundleDict[lodName][truePartName]
|
|
|
animDict = partDict[partName]
|
|
animDict = partDict[partName]
|
|
|
animInfo = []
|
|
animInfo = []
|
|
|
for animName in animDict.keys():
|
|
for animName in animDict.keys():
|
|
@@ -301,6 +347,7 @@ class Actor(DirectObject, NodePath):
|
|
|
self.stop()
|
|
self.stop()
|
|
|
|
|
|
|
|
self.__partBundleDict = {}
|
|
self.__partBundleDict = {}
|
|
|
|
|
+ self.__subpartDict = {}
|
|
|
self.__sortedLODNames = []
|
|
self.__sortedLODNames = []
|
|
|
self.__animControlDict = {}
|
|
self.__animControlDict = {}
|
|
|
self.__controlJoints = {}
|
|
self.__controlJoints = {}
|
|
@@ -353,7 +400,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Return list of Actor part names. If not an multipart actor,
|
|
Return list of Actor part names. If not an multipart actor,
|
|
|
returns 'modelRoot' NOTE: returns parts of arbitrary LOD
|
|
returns 'modelRoot' NOTE: returns parts of arbitrary LOD
|
|
|
"""
|
|
"""
|
|
|
- return self.__partBundleDict.values()[0].keys()
|
|
|
|
|
|
|
+ return self.__partBundleDict.values()[0].keys() + self.__subpartDict.keys()
|
|
|
|
|
+
|
|
|
|
|
|
|
|
def getGeomNode(self):
|
|
def getGeomNode(self):
|
|
|
"""
|
|
"""
|
|
@@ -626,7 +674,8 @@ class Actor(DirectObject, NodePath):
|
|
|
if not partBundleDict:
|
|
if not partBundleDict:
|
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
|
return None
|
|
return None
|
|
|
- return partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ return partBundleDict.get(truePartName)
|
|
|
|
|
|
|
|
def removePart(self, partName, lodName="lodRoot"):
|
|
def removePart(self, partName, lodName="lodRoot"):
|
|
|
"""
|
|
"""
|
|
@@ -646,14 +695,14 @@ class Actor(DirectObject, NodePath):
|
|
|
del(partBundleDict[partName])
|
|
del(partBundleDict[partName])
|
|
|
|
|
|
|
|
# find the corresponding anim control dict
|
|
# find the corresponding anim control dict
|
|
|
- animControlDict = self.__animControlDict.get(lodName)
|
|
|
|
|
- if not animControlDict:
|
|
|
|
|
|
|
+ partDict = self.__animControlDict.get(lodName)
|
|
|
|
|
+ if not partDict:
|
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
# remove the animations
|
|
# remove the animations
|
|
|
- if (animControlDict.has_key(partName)):
|
|
|
|
|
- del(animControlDict[partName])
|
|
|
|
|
|
|
+ if (partDict.has_key(partName)):
|
|
|
|
|
+ del(partDict[partName])
|
|
|
|
|
|
|
|
def hidePart(self, partName, lodName="lodRoot"):
|
|
def hidePart(self, partName, lodName="lodRoot"):
|
|
|
"""
|
|
"""
|
|
@@ -716,7 +765,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
|
return None
|
|
return None
|
|
|
|
|
|
|
|
- part = partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ part = partBundleDict.get(truePartName)
|
|
|
if part:
|
|
if part:
|
|
|
bundle = part.node().getBundle()
|
|
bundle = part.node().getBundle()
|
|
|
else:
|
|
else:
|
|
@@ -749,7 +799,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
|
return None
|
|
return None
|
|
|
|
|
|
|
|
- part = partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ part = partBundleDict.get(truePartName)
|
|
|
if part:
|
|
if part:
|
|
|
bundle = part.node().getBundle()
|
|
bundle = part.node().getBundle()
|
|
|
else:
|
|
else:
|
|
@@ -782,7 +833,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
|
|
return None
|
|
return None
|
|
|
|
|
|
|
|
- part = partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ part = partBundleDict.get(truePartName)
|
|
|
if part:
|
|
if part:
|
|
|
bundle = part.node().getBundle()
|
|
bundle = part.node().getBundle()
|
|
|
else:
|
|
else:
|
|
@@ -814,7 +866,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Instance a nodePath to an actor part at a joint called jointName"""
|
|
Instance a nodePath to an actor part at a joint called jointName"""
|
|
|
partBundleDict = self.__partBundleDict.get(lodName)
|
|
partBundleDict = self.__partBundleDict.get(lodName)
|
|
|
if partBundleDict:
|
|
if partBundleDict:
|
|
|
- part = partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ part = partBundleDict.get(truePartName)
|
|
|
if part:
|
|
if part:
|
|
|
joint = part.find("**/" + jointName)
|
|
joint = part.find("**/" + jointName)
|
|
|
if (joint.isEmpty()):
|
|
if (joint.isEmpty()):
|
|
@@ -831,7 +884,8 @@ class Actor(DirectObject, NodePath):
|
|
|
Attach one actor part to another at a joint called jointName"""
|
|
Attach one actor part to another at a joint called jointName"""
|
|
|
partBundleDict = self.__partBundleDict.get(lodName)
|
|
partBundleDict = self.__partBundleDict.get(lodName)
|
|
|
if partBundleDict:
|
|
if partBundleDict:
|
|
|
- part = partBundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ part = partBundleDict.get(truePartName)
|
|
|
if part:
|
|
if part:
|
|
|
anotherPart = partBundleDict.get(anotherPartName)
|
|
anotherPart = partBundleDict.get(anotherPartName)
|
|
|
if anotherPart:
|
|
if anotherPart:
|
|
@@ -1069,7 +1123,8 @@ class Actor(DirectObject, NodePath):
|
|
|
for partBundle in bundleDict.values():
|
|
for partBundle in bundleDict.values():
|
|
|
partBundle.node().getBundle().setBlendType(blendType)
|
|
partBundle.node().getBundle().setBlendType(blendType)
|
|
|
else:
|
|
else:
|
|
|
- partBundle = bundleDict.get(partName)
|
|
|
|
|
|
|
+ truePartName = self.__subpartDict.get(partName, [partName])[0]
|
|
|
|
|
+ partBundle = bundleDict.get(truePartName)
|
|
|
if partBundle != None:
|
|
if partBundle != None:
|
|
|
partBundle.node().getBundle().setBlendType(blendType)
|
|
partBundle.node().getBundle().setBlendType(blendType)
|
|
|
else:
|
|
else:
|
|
@@ -1099,11 +1154,11 @@ class Actor(DirectObject, NodePath):
|
|
|
a given anim and part. Return the animControl if present,
|
|
a given anim and part. Return the animControl if present,
|
|
|
or None otherwise
|
|
or None otherwise
|
|
|
"""
|
|
"""
|
|
|
- animControlDict = self.__animControlDict.get(lodName)
|
|
|
|
|
|
|
+ partDict = self.__animControlDict.get(lodName)
|
|
|
# if this assertion fails, named lod was not present
|
|
# if this assertion fails, named lod was not present
|
|
|
- assert animControlDict != None
|
|
|
|
|
|
|
+ assert partDict != None
|
|
|
|
|
|
|
|
- animDict = animControlDict.get(partName)
|
|
|
|
|
|
|
+ animDict = partDict.get(partName)
|
|
|
if animDict == None:
|
|
if animDict == None:
|
|
|
# part was not present
|
|
# part was not present
|
|
|
Actor.notify.warning("couldn't find part: %s" % (partName))
|
|
Actor.notify.warning("couldn't find part: %s" % (partName))
|
|
@@ -1138,28 +1193,39 @@ class Actor(DirectObject, NodePath):
|
|
|
# Get all LOD's
|
|
# Get all LOD's
|
|
|
animControlDictItems = self.__animControlDict.items()
|
|
animControlDictItems = self.__animControlDict.items()
|
|
|
else:
|
|
else:
|
|
|
- animControlDict = self.__animControlDict.get(lodName)
|
|
|
|
|
- if animControlDict == None:
|
|
|
|
|
|
|
+ partDict = self.__animControlDict.get(lodName)
|
|
|
|
|
+ if partDict == None:
|
|
|
Actor.notify.warning("couldn't find lod: %s" % (lodName))
|
|
Actor.notify.warning("couldn't find lod: %s" % (lodName))
|
|
|
animControlDictItems = []
|
|
animControlDictItems = []
|
|
|
else:
|
|
else:
|
|
|
- animControlDictItems = [(lodName, animControlDict)]
|
|
|
|
|
|
|
+ animControlDictItems = [(lodName, partDict)]
|
|
|
|
|
|
|
|
- for lodName, animControlDict in animControlDictItems:
|
|
|
|
|
|
|
+ for lodName, partDict in animControlDictItems:
|
|
|
# Now, build the list of partNames and the corresponding
|
|
# Now, build the list of partNames and the corresponding
|
|
|
# animDicts.
|
|
# animDicts.
|
|
|
if partName == None:
|
|
if partName == None:
|
|
|
# Get all parts
|
|
# Get all parts
|
|
|
- animDictItems = animControlDict.items()
|
|
|
|
|
|
|
+ animDictItems = partDict.items()
|
|
|
else:
|
|
else:
|
|
|
- if isinstance(partName, types.StringType):
|
|
|
|
|
|
|
+ if isinstance(partName, types.StringTypes):
|
|
|
partNameList = [partName]
|
|
partNameList = [partName]
|
|
|
else:
|
|
else:
|
|
|
partNameList = partName
|
|
partNameList = partName
|
|
|
|
|
|
|
|
animDictItems = []
|
|
animDictItems = []
|
|
|
for partName in partNameList:
|
|
for partName in partNameList:
|
|
|
- animDict = animControlDict.get(partName)
|
|
|
|
|
|
|
+ animDict = partDict.get(partName)
|
|
|
|
|
+ if animDict == None:
|
|
|
|
|
+ # Maybe it's a subpart that hasn't been bound yet.
|
|
|
|
|
+ subpartDef = self.__subpartDict.get(partName)
|
|
|
|
|
+ if subpartDef:
|
|
|
|
|
+ truePartName = subpartDef[0]
|
|
|
|
|
+ dupAnimDict = partDict.get(truePartName)
|
|
|
|
|
+ animDict = {}
|
|
|
|
|
+ for name, anim in dupAnimDict.items():
|
|
|
|
|
+ animDict[name] = [anim[0], None]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
if animDict == None:
|
|
if animDict == None:
|
|
|
# part was not present
|
|
# part was not present
|
|
|
Actor.notify.warning("couldn't find part: %s" % (partName))
|
|
Actor.notify.warning("couldn't find part: %s" % (partName))
|
|
@@ -1181,11 +1247,11 @@ class Actor(DirectObject, NodePath):
|
|
|
Actor.notify.debug("couldn't find anim: %s" % (animName))
|
|
Actor.notify.debug("couldn't find anim: %s" % (animName))
|
|
|
else:
|
|
else:
|
|
|
# bind the animation first if we need to
|
|
# bind the animation first if we need to
|
|
|
- if not isinstance(anim[1], AnimControl):
|
|
|
|
|
- if self.__bindAnimToPart(animName, thisPart, lodName):
|
|
|
|
|
- controls.append(anim[1])
|
|
|
|
|
- else:
|
|
|
|
|
- controls.append(anim[1])
|
|
|
|
|
|
|
+ animControl = anim[1]
|
|
|
|
|
+ if animControl == None:
|
|
|
|
|
+ animControl = self.__bindAnimToPart(animName, thisPart, lodName)
|
|
|
|
|
+ if animControl:
|
|
|
|
|
+ controls.append(animControl)
|
|
|
|
|
|
|
|
return controls
|
|
return controls
|
|
|
|
|
|
|
@@ -1194,8 +1260,10 @@ class Actor(DirectObject, NodePath):
|
|
|
bool = 0)
|
|
bool = 0)
|
|
|
Actor model loader. Takes a model name (ie file path), a part
|
|
Actor model loader. Takes a model name (ie file path), a part
|
|
|
name(defaults to "modelRoot") and an lod name(defaults to "lodRoot").
|
|
name(defaults to "modelRoot") and an lod name(defaults to "lodRoot").
|
|
|
- If copy is set to 0, do a lodModelOnce instead of a loadModelCopy.
|
|
|
|
|
|
|
+ If copy is set to 0, do a loadModel instead of a loadModelCopy.
|
|
|
"""
|
|
"""
|
|
|
|
|
+ assert partName not in self.__subpartDict
|
|
|
|
|
+
|
|
|
Actor.notify.debug("in loadModel: %s , part: %s, lod: %s, copy: %s" % \
|
|
Actor.notify.debug("in loadModel: %s , part: %s, lod: %s, copy: %s" % \
|
|
|
(modelPath, partName, lodName, copy))
|
|
(modelPath, partName, lodName, copy))
|
|
|
|
|
|
|
@@ -1260,9 +1328,11 @@ class Actor(DirectObject, NodePath):
|
|
|
model.removeNode()
|
|
model.removeNode()
|
|
|
|
|
|
|
|
def prepareBundle(self, bundle, partName="modelRoot", lodName="lodRoot"):
|
|
def prepareBundle(self, bundle, partName="modelRoot", lodName="lodRoot"):
|
|
|
|
|
+ assert partName not in self.__subpartDict
|
|
|
|
|
+
|
|
|
# Rename the node at the top of the hierarchy, if we
|
|
# Rename the node at the top of the hierarchy, if we
|
|
|
# haven't already, to make it easier to identify this
|
|
# haven't already, to make it easier to identify this
|
|
|
- # actor in the scene graph.
|
|
|
|
|
|
|
+ # actor in the scene graph.
|
|
|
if not self.gotName:
|
|
if not self.gotName:
|
|
|
self.node().setName(bundle.node().getName())
|
|
self.node().setName(bundle.node().getName())
|
|
|
self.gotName = 1
|
|
self.gotName = 1
|
|
@@ -1293,6 +1363,49 @@ class Actor(DirectObject, NodePath):
|
|
|
else:
|
|
else:
|
|
|
self.__partBundleDict[lodName][partName] = bundle
|
|
self.__partBundleDict[lodName][partName] = bundle
|
|
|
|
|
|
|
|
|
|
+ def makeSubpart(self, partName, includeJoints, excludeJoints = [],
|
|
|
|
|
+ parent="modelRoot"):
|
|
|
|
|
+
|
|
|
|
|
+ """Defines a new "part" of the Actor that corresponds to the
|
|
|
|
|
+ same geometry as the named parent part, but animates only a
|
|
|
|
|
+ certain subset of the joints. This can be used for
|
|
|
|
|
+ partial-body animations, for instance to animate a hand waving
|
|
|
|
|
+ while the rest of the body continues to play its walking
|
|
|
|
|
+ animation.
|
|
|
|
|
+
|
|
|
|
|
+ includeJoints is a list of joint names that are to be animated
|
|
|
|
|
+ by the subpart. Each name can include globbing characters
|
|
|
|
|
+ like '?' or '*', which will match one or any number of
|
|
|
|
|
+ characters, respectively. Including a joint by naming it in
|
|
|
|
|
+ includeJoints implicitly includes all of the descendents of
|
|
|
|
|
+ that joint as well, except for excludeJoints, below.
|
|
|
|
|
+
|
|
|
|
|
+ excludeJoints is a list of joint names that are *not* to be
|
|
|
|
|
+ animated by the subpart. As in includeJoints, each name can
|
|
|
|
|
+ include globbing characters. If a joint is named by
|
|
|
|
|
+ excludeJoints, it will not be included (and neither will any
|
|
|
|
|
+ of its descendents), even if a parent joint was named by
|
|
|
|
|
+ includeJoints.
|
|
|
|
|
+
|
|
|
|
|
+ parent is the actual partName that this subpart is based
|
|
|
|
|
+ on."""
|
|
|
|
|
+
|
|
|
|
|
+ assert partName not in self.__subpartDict
|
|
|
|
|
+
|
|
|
|
|
+ truePartName = partName
|
|
|
|
|
+ prevSubset = PartSubset()
|
|
|
|
|
+ subpartDef = self.__subpartDict.get(partName)
|
|
|
|
|
+ if subpartDef:
|
|
|
|
|
+ truePartName, subset = subpartDef
|
|
|
|
|
+
|
|
|
|
|
+ subset = PartSubset(prevSubset)
|
|
|
|
|
+ for name in includeJoints:
|
|
|
|
|
+ subset.addIncludeJoint(GlobPattern(name))
|
|
|
|
|
+ for name in excludeJoints:
|
|
|
|
|
+ subset.addExcludeJoint(GlobPattern(name))
|
|
|
|
|
+
|
|
|
|
|
+ self.__subpartDict[partName] = (parent, subset)
|
|
|
|
|
+
|
|
|
def loadAnims(self, anims, partName="modelRoot", lodName="lodRoot"):
|
|
def loadAnims(self, anims, partName="modelRoot", lodName="lodRoot"):
|
|
|
"""loadAnims(self, string:string{}, string='modelRoot',
|
|
"""loadAnims(self, string:string{}, string='modelRoot',
|
|
|
string='lodRoot')
|
|
string='lodRoot')
|
|
@@ -1370,7 +1483,7 @@ class Actor(DirectObject, NodePath):
|
|
|
# loop over all lods
|
|
# loop over all lods
|
|
|
for thisLod in lodNames:
|
|
for thisLod in lodNames:
|
|
|
if partName == None:
|
|
if partName == None:
|
|
|
- partNames = animControlDict[lodName].keys()
|
|
|
|
|
|
|
+ partNames = self.__partBundleDict[thisLod].keys()
|
|
|
else:
|
|
else:
|
|
|
partNames = [partName]
|
|
partNames = [partName]
|
|
|
# loop over all parts
|
|
# loop over all parts
|
|
@@ -1383,26 +1496,49 @@ class Actor(DirectObject, NodePath):
|
|
|
for internal use only!
|
|
for internal use only!
|
|
|
"""
|
|
"""
|
|
|
# make sure this anim is in the dict
|
|
# make sure this anim is in the dict
|
|
|
- if not self.__animControlDict[lodName][partName].has_key(animName):
|
|
|
|
|
- Actor.notify.debug("actor has no animation %s", animName)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ subpartDef = self.__subpartDict.get(partName)
|
|
|
|
|
+ truePartName = partName
|
|
|
|
|
+ subset = PartSubset()
|
|
|
|
|
+ if subpartDef:
|
|
|
|
|
+ truePartName, subset = subpartDef
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ partDict = self.__animControlDict[lodName]
|
|
|
|
|
+ animDict = partDict.get(partName)
|
|
|
|
|
+ if animDict == None:
|
|
|
|
|
+ # It must be a subpart that hasn't been bound yet.
|
|
|
|
|
+ animDict = {}
|
|
|
|
|
+ partDict[partName] = animDict
|
|
|
|
|
+
|
|
|
|
|
+ anim = animDict.get(animName)
|
|
|
|
|
+ if anim == None:
|
|
|
|
|
+ # It must be a subpart that hasn't been bound yet.
|
|
|
|
|
+ if subpartDef != None:
|
|
|
|
|
+ anim = partDict[truePartName].get(animName)
|
|
|
|
|
+ anim = [anim[0], None]
|
|
|
|
|
+ animDict[animName] = anim
|
|
|
|
|
+
|
|
|
|
|
+ if anim == None:
|
|
|
|
|
+ Actor.notify.error("actor has no animation %s", animName)
|
|
|
|
|
|
|
|
# only bind if not already bound!
|
|
# only bind if not already bound!
|
|
|
- if isinstance(self.__animControlDict[lodName][partName][animName][1],
|
|
|
|
|
- AnimControl):
|
|
|
|
|
- return None
|
|
|
|
|
|
|
+ if anim[1]:
|
|
|
|
|
+ return anim[1]
|
|
|
|
|
|
|
|
# fetch a copy from the modelPool, or if we weren't careful
|
|
# fetch a copy from the modelPool, or if we weren't careful
|
|
|
# enough to preload, fetch from disk :(
|
|
# enough to preload, fetch from disk :(
|
|
|
- animPath = self.__animControlDict[lodName][partName][animName][0]
|
|
|
|
|
|
|
+ animPath = anim[0]
|
|
|
if self.__autoCopy:
|
|
if self.__autoCopy:
|
|
|
- anim = loader.loadModelOnce(animPath)
|
|
|
|
|
|
|
+ animNode = loader.loadModelOnce(animPath)
|
|
|
else:
|
|
else:
|
|
|
- anim = loader.loadModel(animPath,
|
|
|
|
|
- loaderOptions = self.animLoaderOptions)
|
|
|
|
|
- if anim == None:
|
|
|
|
|
|
|
+ animNode = loader.loadModel(animPath,
|
|
|
|
|
+ loaderOptions = self.animLoaderOptions)
|
|
|
|
|
+ if animNode == None:
|
|
|
return None
|
|
return None
|
|
|
- animBundle = (anim.find("**/+AnimBundleNode").node()).getBundle()
|
|
|
|
|
- bundle = self.__partBundleDict[lodName][partName].node().getBundle()
|
|
|
|
|
|
|
+ animBundle = (animNode.find("**/+AnimBundleNode").node()).getBundle()
|
|
|
|
|
+
|
|
|
|
|
+ bundle = self.__partBundleDict[lodName][truePartName].node().getBundle()
|
|
|
|
|
|
|
|
# Are there any controls requested for joints in this bundle?
|
|
# Are there any controls requested for joints in this bundle?
|
|
|
# If so, apply them.
|
|
# If so, apply them.
|
|
@@ -1417,16 +1553,15 @@ class Actor(DirectObject, NodePath):
|
|
|
Actor.notify.error("controlled joint %s is not present" % jointName)
|
|
Actor.notify.error("controlled joint %s is not present" % jointName)
|
|
|
|
|
|
|
|
# bind anim
|
|
# bind anim
|
|
|
- animControl = bundle.bindAnim(animBundle, -1)
|
|
|
|
|
|
|
+ animControl = bundle.bindAnim(animBundle, -1, subset)
|
|
|
|
|
|
|
|
if (animControl == None):
|
|
if (animControl == None):
|
|
|
Actor.notify.error("Null AnimControl: %s" % (animName))
|
|
Actor.notify.error("Null AnimControl: %s" % (animName))
|
|
|
else:
|
|
else:
|
|
|
# store the animControl
|
|
# store the animControl
|
|
|
- self.__animControlDict[lodName][partName][animName][1] = \
|
|
|
|
|
- animControl
|
|
|
|
|
|
|
+ anim[1] = animControl
|
|
|
Actor.notify.debug("binding anim: %s to part: %s, lod: %s" %
|
|
Actor.notify.debug("binding anim: %s to part: %s, lod: %s" %
|
|
|
- (animName, partName, lodName))
|
|
|
|
|
|
|
+ (animName, partName, lodName))
|
|
|
return animControl
|
|
return animControl
|
|
|
|
|
|
|
|
def __copyPartBundles(self, other):
|
|
def __copyPartBundles(self, other):
|