mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
reorganize Actor dictionaries a bit; keep around ModelRoot node for proper ModelPool reference counting
This commit is contained in:
parent
79d14e2fc8
commit
1373705582
@ -22,6 +22,66 @@ class Actor(DirectObject, NodePath):
|
|||||||
LoaderOptions.LFReportErrors |
|
LoaderOptions.LFReportErrors |
|
||||||
LoaderOptions.LFConvertAnim)
|
LoaderOptions.LFConvertAnim)
|
||||||
|
|
||||||
|
class PartDef:
|
||||||
|
|
||||||
|
"""Instances of this class are stored within the
|
||||||
|
PartBundleDict to track all of the individual PartBundles
|
||||||
|
associated with the Actor. In general, each separately loaded
|
||||||
|
model file is a different PartBundle. This can include the
|
||||||
|
multiple different LOD's, as well as the multiple different
|
||||||
|
pieces of a multipart Actor. """
|
||||||
|
|
||||||
|
def __init__(self, partBundle, partModel):
|
||||||
|
# We also save the ModelRoot node along with the
|
||||||
|
# PartBundle, so that the reference count in the ModelPool
|
||||||
|
# will be accurate.
|
||||||
|
self.partBundle = partBundle
|
||||||
|
self.partModel = partModel
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'Actor.PartDef(%s, %s)' % (repr(self.partBundle), repr(self.partModel))
|
||||||
|
|
||||||
|
class AnimDef:
|
||||||
|
|
||||||
|
"""Instances of this class are stored within the
|
||||||
|
AnimControlDict to track all of the animations associated with
|
||||||
|
the Actor. This includes animations that have already been
|
||||||
|
bound (these have a valid AnimControl) as well as those that
|
||||||
|
have not yet been bound (for these, self.animControl is None).
|
||||||
|
|
||||||
|
There is a different AnimDef for each different part or
|
||||||
|
sub-part, times each different animation in the AnimDict. """
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.filename = filename
|
||||||
|
self.animModel = None
|
||||||
|
self.animControl = None
|
||||||
|
|
||||||
|
def makeCopy(self):
|
||||||
|
return Actor.AnimDef(self.filename)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'Actor.AnimDef(%s)' % (repr(self.filename))
|
||||||
|
|
||||||
|
class SubpartDef:
|
||||||
|
|
||||||
|
"""Instances of this class are stored within the SubpartDict
|
||||||
|
to track the existance of arbitrary sub-parts. These are
|
||||||
|
designed to appear to the user to be identical to true "part"
|
||||||
|
of a multi-part Actor, but in fact each subpart represents a
|
||||||
|
subset of the joints of an existing part (which is accessible
|
||||||
|
via a different name). """
|
||||||
|
|
||||||
|
def __init__(self, truePartName, subset = PartSubset()):
|
||||||
|
self.truePartName = truePartName
|
||||||
|
self.subset = subset
|
||||||
|
|
||||||
|
def makeCopy(self):
|
||||||
|
return Actor.SubpartDef(self.truePartName, PartSubset(self.subset))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'Actor.SubpartDef(%s, %s)' % (repr(self.truePartName), repr(self.subset))
|
||||||
|
|
||||||
def __init__(self, models=None, anims=None, other=None, copy=1,
|
def __init__(self, models=None, anims=None, other=None, copy=1,
|
||||||
lodNode = None):
|
lodNode = None):
|
||||||
"""__init__(self, string | string:string{}, string:string{} |
|
"""__init__(self, string | string:string{}, string:string{} |
|
||||||
@ -226,7 +286,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
# copy the scene graph elements of other
|
# copy the scene graph elements of other
|
||||||
if (overwrite):
|
if (overwrite):
|
||||||
otherCopy = other.copyTo(hidden)
|
otherCopy = other.copyTo(NodePath())
|
||||||
otherCopy.detachNode()
|
otherCopy.detachNode()
|
||||||
# assign these elements to ourselve (overwrite)
|
# assign these elements to ourselve (overwrite)
|
||||||
self.assign(otherCopy)
|
self.assign(otherCopy)
|
||||||
@ -266,8 +326,8 @@ class Actor(DirectObject, NodePath):
|
|||||||
"""
|
"""
|
||||||
Actor print function
|
Actor print function
|
||||||
"""
|
"""
|
||||||
return "Actor: partBundleDict = %s,\n animControlDict = %s" % \
|
return "Actor %s, parts = %s, LODs = %s, anims = %s" % \
|
||||||
(self.__partBundleDict, self.__animControlDict)
|
(self.getName(), self.getPartNames(), self.getLODNames(), self.getAnimNames())
|
||||||
|
|
||||||
def listJoints(self, partName="modelRoot", lodName="lodRoot"):
|
def listJoints(self, partName="modelRoot", lodName="lodRoot"):
|
||||||
"""Handy utility function to list the joint hierarchy of the
|
"""Handy utility function to list the joint hierarchy of the
|
||||||
@ -277,18 +337,14 @@ class Actor(DirectObject, NodePath):
|
|||||||
if not partBundleDict:
|
if not partBundleDict:
|
||||||
Actor.notify.error("no lod named: %s" % (lodName))
|
Actor.notify.error("no lod named: %s" % (lodName))
|
||||||
|
|
||||||
truePartName = partName
|
subpartDef = self.__subpartDict.get(partName, Actor.SubpartDef(partName))
|
||||||
subset = PartSubset()
|
|
||||||
subpartDef = self.__subpartDict.get(partName)
|
|
||||||
if subpartDef:
|
|
||||||
truePartName, subset = subpartDef
|
|
||||||
|
|
||||||
bundle = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(subpartDef.truePartName)
|
||||||
if bundle == None:
|
if partDef == None:
|
||||||
Actor.notify.error("no part named: %s" % (partName))
|
Actor.notify.error("no part named: %s" % (partName))
|
||||||
|
|
||||||
self.__doListJoints(0, bundle.node().getBundle(),
|
self.__doListJoints(0, partDef.partBundle.node().getBundle(),
|
||||||
subset.isIncludeEmpty(), subset)
|
subset.isIncludeEmpty(), subpartDef.subset)
|
||||||
|
|
||||||
def __doListJoints(self, indentLevel, part, isIncluded, subset):
|
def __doListJoints(self, indentLevel, part, isIncluded, subset):
|
||||||
name = part.getName()
|
name = part.getName()
|
||||||
@ -322,12 +378,12 @@ class Actor(DirectObject, NodePath):
|
|||||||
partInfo = []
|
partInfo = []
|
||||||
for partName in partDict.keys():
|
for partName in partDict.keys():
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
partBundle = self.__partBundleDict[lodName][truePartName]
|
partBundle = self.__partBundleDict[lodName][truePartName].partBundle
|
||||||
animDict = partDict[partName]
|
animDict = partDict[partName]
|
||||||
animInfo = []
|
animInfo = []
|
||||||
for animName in animDict.keys():
|
for animName in animDict.keys():
|
||||||
file = animDict[animName][0]
|
file = animDict[animName].filename
|
||||||
animControl = animDict[animName][1]
|
animControl = animDict[animName].animControl
|
||||||
animInfo.append([animName, file, animControl])
|
animInfo.append([animName, file, animControl])
|
||||||
partInfo.append([partName, partBundle, animInfo])
|
partInfo.append([partName, partBundle, animInfo])
|
||||||
lodInfo.append([lodName, partInfo])
|
lodInfo.append([lodName, partInfo])
|
||||||
@ -563,10 +619,10 @@ class Actor(DirectObject, NodePath):
|
|||||||
def update(self, lod=0):
|
def update(self, lod=0):
|
||||||
lodnames = self.getLODNames()
|
lodnames = self.getLODNames()
|
||||||
if (lod < len(lodnames)):
|
if (lod < len(lodnames)):
|
||||||
partBundles = self.__partBundleDict[lodnames[lod]].values()
|
partDefs = self.__partBundleDict[lodnames[lod]].values()
|
||||||
for partBundle in partBundles:
|
for partDef in partDefs:
|
||||||
# print "updating: %s" % (partBundle.node())
|
# print "updating: %s" % (partBundle.node())
|
||||||
partBundle.node().updateToNow()
|
partDef.partBundle.node().updateToNow()
|
||||||
else:
|
else:
|
||||||
self.notify.warning('update() - no lod: %d' % lod)
|
self.notify.warning('update() - no lod: %d' % lod)
|
||||||
|
|
||||||
@ -675,7 +731,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
# loop through all anims for named part and find if any are playing
|
# loop through all anims for named part and find if any are playing
|
||||||
for animName, anim in animDict.items():
|
for animName, anim in animDict.items():
|
||||||
if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
|
if isinstance(anim.animControl, AnimControl) and anim.animControl.isPlaying():
|
||||||
return animName
|
return animName
|
||||||
|
|
||||||
# we must have found none, or gotten an error
|
# we must have found none, or gotten an error
|
||||||
@ -700,8 +756,8 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
# loop through all anims for named part and find if any are playing
|
# loop through all anims for named part and find if any are playing
|
||||||
for animName, anim in animDict.items():
|
for animName, anim in animDict.items():
|
||||||
if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
|
if isinstance(anim.animControl, AnimControl) and anim.animControl.isPlaying():
|
||||||
return anim[1].getFrame()
|
return anim.animControl.getFrame()
|
||||||
|
|
||||||
# we must have found none, or gotten an error
|
# we must have found none, or gotten an error
|
||||||
return None
|
return None
|
||||||
@ -719,7 +775,10 @@ class Actor(DirectObject, NodePath):
|
|||||||
Actor.notify.warning("no lod named: %s" % (lodName))
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
||||||
return None
|
return None
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
return partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
|
if partDef != None:
|
||||||
|
return partDef.partBundle
|
||||||
|
return None
|
||||||
|
|
||||||
def removePart(self, partName, lodName="lodRoot"):
|
def removePart(self, partName, lodName="lodRoot"):
|
||||||
"""
|
"""
|
||||||
@ -735,7 +794,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
# remove the part
|
# remove the part
|
||||||
if (partBundleDict.has_key(partName)):
|
if (partBundleDict.has_key(partName)):
|
||||||
partBundleDict[partName].removeNode()
|
partBundleDict[partName].partBundle.removeNode()
|
||||||
del(partBundleDict[partName])
|
del(partBundleDict[partName])
|
||||||
|
|
||||||
# find the corresponding anim control dict
|
# find the corresponding anim control dict
|
||||||
@ -758,9 +817,9 @@ 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
|
return
|
||||||
part = partBundleDict.get(partName)
|
partDef = partBundleDict.get(partName)
|
||||||
if part:
|
if partDef:
|
||||||
part.hide()
|
partDef.partBundle.hide()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
|
|
||||||
@ -773,9 +832,9 @@ 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
|
return
|
||||||
part = partBundleDict.get(partName)
|
partDef = partBundleDict.get(partName)
|
||||||
if part:
|
if partDef:
|
||||||
part.show()
|
partDef.partBundle.show()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
|
|
||||||
@ -788,10 +847,10 @@ 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
|
return
|
||||||
part = partBundleDict.get(partName)
|
partDef = partBundleDict.get(partName)
|
||||||
if part:
|
if partDef:
|
||||||
part.show()
|
partDef.partBundle.show()
|
||||||
part.getChildren().show()
|
partDef.partBundle.getChildren().show()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
|
|
||||||
@ -810,9 +869,9 @@ class Actor(DirectObject, NodePath):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
part = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
if part:
|
if partDef:
|
||||||
bundle = part.node().getBundle()
|
bundle = partDef.partBundle.node().getBundle()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
return None
|
return None
|
||||||
@ -844,9 +903,9 @@ class Actor(DirectObject, NodePath):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
part = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
if part:
|
if partDef:
|
||||||
bundle = part.node().getBundle()
|
bundle = partDef.partBundle.node().getBundle()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
return None
|
return None
|
||||||
@ -878,9 +937,9 @@ class Actor(DirectObject, NodePath):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
part = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
if part:
|
if part:
|
||||||
bundle = part.node().getBundle()
|
bundle = partDef.partBundle.node().getBundle()
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (partName))
|
Actor.notify.warning("no part named %s!" % (partName))
|
||||||
return None
|
return None
|
||||||
@ -911,9 +970,9 @@ class Actor(DirectObject, NodePath):
|
|||||||
partBundleDict = self.__partBundleDict.get(lodName)
|
partBundleDict = self.__partBundleDict.get(lodName)
|
||||||
if partBundleDict:
|
if partBundleDict:
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
part = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
if part:
|
if partDef:
|
||||||
joint = part.find("**/" + jointName)
|
joint = partDef.partBundle.find("**/" + jointName)
|
||||||
if (joint.isEmpty()):
|
if (joint.isEmpty()):
|
||||||
Actor.notify.warning("%s not found!" % (jointName))
|
Actor.notify.warning("%s not found!" % (jointName))
|
||||||
else:
|
else:
|
||||||
@ -929,15 +988,15 @@ class Actor(DirectObject, NodePath):
|
|||||||
partBundleDict = self.__partBundleDict.get(lodName)
|
partBundleDict = self.__partBundleDict.get(lodName)
|
||||||
if partBundleDict:
|
if partBundleDict:
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
part = partBundleDict.get(truePartName)
|
partDef = partBundleDict.get(truePartName)
|
||||||
if part:
|
if partDef:
|
||||||
anotherPart = partBundleDict.get(anotherPartName)
|
anotherPartDef = partBundleDict.get(anotherPartName)
|
||||||
if anotherPart:
|
if anotherPartDef:
|
||||||
joint = anotherPart.find("**/" + jointName)
|
joint = anotherPartDef.partBundle.find("**/" + jointName)
|
||||||
if (joint.isEmpty()):
|
if (joint.isEmpty()):
|
||||||
Actor.notify.warning("%s not found!" % (jointName))
|
Actor.notify.warning("%s not found!" % (jointName))
|
||||||
else:
|
else:
|
||||||
part.reparentTo(joint)
|
partDef.partBundle.reparentTo(joint)
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("no part named %s!" % (anotherPartName))
|
Actor.notify.warning("no part named %s!" % (anotherPartName))
|
||||||
else:
|
else:
|
||||||
@ -1191,14 +1250,14 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
for lodName, bundleDict in self.__partBundleDict.items():
|
for lodName, bundleDict in self.__partBundleDict.items():
|
||||||
if partName == None:
|
if partName == None:
|
||||||
for partBundle in bundleDict.values():
|
for partDef in bundleDict.values():
|
||||||
bundles.append(partBundle.node().getBundle())
|
bundles.append(partDef.partBundle.node().getBundle())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
truePartName = self.__subpartDict.get(partName, [partName])[0]
|
||||||
partBundle = bundleDict.get(truePartName)
|
partDef = bundleDict.get(truePartName)
|
||||||
if partBundle != None:
|
if partDef != None:
|
||||||
bundles.append(partBundle.node().getBundle())
|
bundles.append(partDef.partBundle.node().getBundle())
|
||||||
else:
|
else:
|
||||||
Actor.notify.warning("Couldn't find part: %s" % (partName))
|
Actor.notify.warning("Couldn't find part: %s" % (partName))
|
||||||
|
|
||||||
@ -1269,9 +1328,9 @@ class Actor(DirectObject, NodePath):
|
|||||||
pass
|
pass
|
||||||
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 not isinstance(anim.animControl, AnimControl):
|
||||||
self.__bindAnimToPart(animName, partName, lodName)
|
self.__bindAnimToPart(animName, partName, lodName)
|
||||||
return anim[1]
|
return anim.animControl
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -1345,8 +1404,8 @@ class Actor(DirectObject, NodePath):
|
|||||||
# get all playing animations
|
# get all playing animations
|
||||||
for thisPart, animDict in animDictItems:
|
for thisPart, animDict in animDictItems:
|
||||||
for anim in animDict.values():
|
for anim in animDict.values():
|
||||||
if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
|
if isinstance(anim.animControl, AnimControl) and anim.animControl.isPlaying():
|
||||||
controls.append(anim[1])
|
controls.append(anim.animControl)
|
||||||
else:
|
else:
|
||||||
# get the named animation only.
|
# get the named animation only.
|
||||||
for thisPart, animDict in animDictItems:
|
for thisPart, animDict in animDictItems:
|
||||||
@ -1356,10 +1415,10 @@ class Actor(DirectObject, NodePath):
|
|||||||
# Maybe it's a subpart that hasn't been bound yet.
|
# Maybe it's a subpart that hasn't been bound yet.
|
||||||
subpartDef = self.__subpartDict.get(pName)
|
subpartDef = self.__subpartDict.get(pName)
|
||||||
if subpartDef:
|
if subpartDef:
|
||||||
truePartName = subpartDef[0]
|
truePartName = subpartDef.truePartName
|
||||||
anim = partDict[truePartName].get(animName)
|
anim = partDict[truePartName].get(animName)
|
||||||
if anim:
|
if anim:
|
||||||
anim = [anim[0], None]
|
anim = anim.makeCopy()
|
||||||
animDict[animName] = anim
|
animDict[animName] = anim
|
||||||
|
|
||||||
if anim == None:
|
if anim == None:
|
||||||
@ -1368,7 +1427,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# bind the animation first if we need to
|
# bind the animation first if we need to
|
||||||
animControl = anim[1]
|
animControl = anim.animControl
|
||||||
if animControl == None:
|
if animControl == None:
|
||||||
animControl = self.__bindAnimToPart(animName, thisPart, lodName)
|
animControl = self.__bindAnimToPart(animName, thisPart, lodName)
|
||||||
if animControl:
|
if animControl:
|
||||||
@ -1392,27 +1451,31 @@ class Actor(DirectObject, NodePath):
|
|||||||
# If we got a NodePath instead of a string, use *that* as
|
# If we got a NodePath instead of a string, use *that* as
|
||||||
# the model directly.
|
# the model directly.
|
||||||
if (copy):
|
if (copy):
|
||||||
model = modelPath.copyTo(hidden)
|
model = modelPath.copyTo(NodePath())
|
||||||
else:
|
else:
|
||||||
model = modelPath
|
model = modelPath
|
||||||
else:
|
else:
|
||||||
# otherwise, we got the name of the model to load.
|
# otherwise, we got the name of the model to load.
|
||||||
if (copy):
|
loaderOptions = self.modelLoaderOptions
|
||||||
# We can't pass loaderOptions to loadModelCopy.
|
if not copy:
|
||||||
model = loader.loadModelCopy(modelPath)
|
# If copy = 0, then we should always hit the disk.
|
||||||
else:
|
loaderOptions = LoaderOptions(loaderOptions)
|
||||||
# But if we're loading our own copy of the model, we
|
loaderOptions.setFlags(loaderOptions.getFlags() & ~LoaderOptions.LFNoRamCache)
|
||||||
# can pass loaderOptions to specify that we want to
|
|
||||||
|
# Pass loaderOptions to specify that we want to
|
||||||
# get the skeleton model. This only matters to model
|
# get the skeleton model. This only matters to model
|
||||||
# files (like .mb) for which we can choose to extract
|
# files (like .mb) for which we can choose to extract
|
||||||
# either the skeleton or animation, or neither.
|
# either the skeleton or animation, or neither.
|
||||||
model = loader.loadModel(modelPath,
|
model = loader.loadModel(modelPath, loaderOptions = loaderOptions)
|
||||||
loaderOptions = self.modelLoaderOptions)
|
|
||||||
|
|
||||||
if (model == None):
|
if (model == None):
|
||||||
raise StandardError, "Could not load Actor model %s" % (modelPath)
|
raise StandardError, "Could not load Actor model %s" % (modelPath)
|
||||||
|
|
||||||
|
if (model.node().isOfType(PartBundleNode.getClassType())):
|
||||||
|
bundle = model
|
||||||
|
else:
|
||||||
bundle = model.find("**/+PartBundleNode")
|
bundle = model.find("**/+PartBundleNode")
|
||||||
|
|
||||||
if (bundle.isEmpty()):
|
if (bundle.isEmpty()):
|
||||||
Actor.notify.warning("%s is not a character!" % (modelPath))
|
Actor.notify.warning("%s is not a character!" % (modelPath))
|
||||||
model.reparentTo(self.__geomNode)
|
model.reparentTo(self.__geomNode)
|
||||||
@ -1426,7 +1489,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
# Now extract out the PartBundleNode and integrate it with
|
# Now extract out the PartBundleNode and integrate it with
|
||||||
# the Actor.
|
# the Actor.
|
||||||
self.prepareBundle(bundle, partName, lodName)
|
self.__prepareBundle(bundle, model, partName, lodName)
|
||||||
|
|
||||||
if numAnims != 0:
|
if numAnims != 0:
|
||||||
# If the model had some animations, store them in the
|
# If the model had some animations, store them in the
|
||||||
@ -1446,9 +1509,8 @@ class Actor(DirectObject, NodePath):
|
|||||||
# animControl, but put None in for the filename.
|
# animControl, but put None in for the filename.
|
||||||
self.__animControlDict[lodName][partName][animName] = [None, animControl]
|
self.__animControlDict[lodName][partName][animName] = [None, animControl]
|
||||||
|
|
||||||
model.removeNode()
|
def __prepareBundle(self, bundle, model,
|
||||||
|
partName="modelRoot", lodName="lodRoot"):
|
||||||
def prepareBundle(self, bundle, partName="modelRoot", lodName="lodRoot"):
|
|
||||||
assert partName not in self.__subpartDict
|
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
|
||||||
@ -1469,20 +1531,17 @@ class Actor(DirectObject, NodePath):
|
|||||||
needsDict = 0
|
needsDict = 0
|
||||||
|
|
||||||
if (lodName!="lodRoot"):
|
if (lodName!="lodRoot"):
|
||||||
# instance to appropriate node under LOD switch
|
# parent to appropriate node under LOD switch
|
||||||
#bundle = bundle.instanceTo(
|
|
||||||
# self.__LODNode.find("**/" + str(lodName)))
|
|
||||||
bundle.reparentTo(self.__LODNode.find("**/" + str(lodName)))
|
bundle.reparentTo(self.__LODNode.find("**/" + str(lodName)))
|
||||||
else:
|
else:
|
||||||
#bundle = bundle.instanceTo(self.__geomNode)
|
|
||||||
bundle.reparentTo(self.__geomNode)
|
bundle.reparentTo(self.__geomNode)
|
||||||
|
|
||||||
if (needsDict):
|
if (needsDict):
|
||||||
bundleDict[partName] = bundle
|
bundleDict[partName] = Actor.PartDef(bundle, model.node())
|
||||||
self.__partBundleDict[lodName] = bundleDict
|
self.__partBundleDict[lodName] = bundleDict
|
||||||
self.__updateSortedLODNames()
|
self.__updateSortedLODNames()
|
||||||
else:
|
else:
|
||||||
self.__partBundleDict[lodName][partName] = bundle
|
self.__partBundleDict[lodName][partName] = Actor.PartDef(bundle, model.node())
|
||||||
|
|
||||||
def makeSubpart(self, partName, includeJoints, excludeJoints = [],
|
def makeSubpart(self, partName, includeJoints, excludeJoints = [],
|
||||||
parent="modelRoot"):
|
parent="modelRoot"):
|
||||||
@ -1513,19 +1572,15 @@ class Actor(DirectObject, NodePath):
|
|||||||
|
|
||||||
assert partName not in self.__subpartDict
|
assert partName not in self.__subpartDict
|
||||||
|
|
||||||
truePartName = partName
|
subpartDef = self.__subpartDict.get(parent, Actor.SubpartDef(''))
|
||||||
prevSubset = PartSubset()
|
|
||||||
subpartDef = self.__subpartDict.get(partName)
|
|
||||||
if subpartDef:
|
|
||||||
truePartName, subset = subpartDef
|
|
||||||
|
|
||||||
subset = PartSubset(prevSubset)
|
subset = PartSubset(subpartDef.subset)
|
||||||
for name in includeJoints:
|
for name in includeJoints:
|
||||||
subset.addIncludeJoint(GlobPattern(name))
|
subset.addIncludeJoint(GlobPattern(name))
|
||||||
for name in excludeJoints:
|
for name in excludeJoints:
|
||||||
subset.addExcludeJoint(GlobPattern(name))
|
subset.addExcludeJoint(GlobPattern(name))
|
||||||
|
|
||||||
self.__subpartDict[partName] = (parent, subset)
|
self.__subpartDict[partName] = Actor.SubpartDef(parent, subset)
|
||||||
|
|
||||||
def setSubpartsComplete(self, flag):
|
def setSubpartsComplete(self, flag):
|
||||||
|
|
||||||
@ -1567,13 +1622,14 @@ class Actor(DirectObject, NodePath):
|
|||||||
assert Actor.notify.debug("in loadAnims: %s, part: %s, lod: %s" %
|
assert Actor.notify.debug("in loadAnims: %s, part: %s, lod: %s" %
|
||||||
(anims, partName, lodName))
|
(anims, partName, lodName))
|
||||||
|
|
||||||
for animName in anims.keys():
|
for animName, filename in anims.items():
|
||||||
# make sure this lod is in anim control dict
|
# make sure this lod is in anim control dict
|
||||||
self.__animControlDict.setdefault(lodName, {})
|
self.__animControlDict.setdefault(lodName, {})
|
||||||
self.__animControlDict[lodName].setdefault(partName, {})
|
self.__animControlDict[lodName].setdefault(partName, {})
|
||||||
# store the file path and None in place of the animControl.
|
|
||||||
# we will bind it only when played
|
# store the file path only; we will bind it (and produce
|
||||||
self.__animControlDict[lodName][partName][animName] = [anims[animName], None]
|
# an AnimControl) when it is played
|
||||||
|
self.__animControlDict[lodName][partName][animName] = Actor.AnimDef(filename)
|
||||||
|
|
||||||
|
|
||||||
def unloadAnims(self, anims, partName="modelRoot", lodName="lodRoot"):
|
def unloadAnims(self, anims, partName="modelRoot", lodName="lodRoot"):
|
||||||
@ -1612,15 +1668,14 @@ class Actor(DirectObject, NodePath):
|
|||||||
for animName in anims:
|
for animName in anims:
|
||||||
# delete the anim control
|
# delete the anim control
|
||||||
try:
|
try:
|
||||||
animControlPair = self.__animControlDict[lodName][partName][animName]
|
animDef = self.__animControlDict[lodName][partName][animName]
|
||||||
if animControlPair[1] != None:
|
if animDef.animControl != None:
|
||||||
# Try to clear any control effects before we let
|
# Try to clear any control effects before we let
|
||||||
# our handle on them go. This is especially
|
# our handle on them go. This is especially
|
||||||
# important if the anim control was blending
|
# important if the anim control was blending
|
||||||
# animations.
|
# animations.
|
||||||
animControlPair[1].getPart().clearControlEffects()
|
animDef.animControl.getPart().clearControlEffects()
|
||||||
del(animControlPair[1])
|
animDef.animControl = None
|
||||||
animControlPair.append(None)
|
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1649,12 +1704,7 @@ 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
|
||||||
subpartDef = self.__subpartDict.get(partName)
|
subpartDef = self.__subpartDict.get(partName, Actor.SubpartDef(partName))
|
||||||
truePartName = partName
|
|
||||||
subset = PartSubset()
|
|
||||||
if subpartDef:
|
|
||||||
truePartName, subset = subpartDef
|
|
||||||
|
|
||||||
|
|
||||||
partDict = self.__animControlDict[lodName]
|
partDict = self.__animControlDict[lodName]
|
||||||
animDict = partDict.get(partName)
|
animDict = partDict.get(partName)
|
||||||
@ -1666,31 +1716,32 @@ class Actor(DirectObject, NodePath):
|
|||||||
anim = animDict.get(animName)
|
anim = animDict.get(animName)
|
||||||
if anim == None:
|
if anim == None:
|
||||||
# It must be a subpart that hasn't been bound yet.
|
# It must be a subpart that hasn't been bound yet.
|
||||||
if subpartDef != None:
|
anim = partDict[subpartDef.truePartName].get(animName)
|
||||||
anim = partDict[truePartName].get(animName)
|
anim = anim.makeCopy()
|
||||||
anim = [anim[0], None]
|
|
||||||
animDict[animName] = anim
|
animDict[animName] = anim
|
||||||
|
|
||||||
if anim == None:
|
if anim == None:
|
||||||
Actor.notify.error("actor has no animation %s", animName)
|
Actor.notify.error("actor has no animation %s", animName)
|
||||||
|
|
||||||
# only bind if not already bound!
|
# only bind if not already bound!
|
||||||
if anim[1]:
|
if anim.animControl:
|
||||||
return anim[1]
|
return anim.animControl
|
||||||
|
|
||||||
# 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 = anim[0]
|
animPath = anim.filename
|
||||||
if self.__autoCopy:
|
loaderOptions = self.animLoaderOptions
|
||||||
animNode = loader.loadModelOnce(animPath)
|
if not self.__autoCopy:
|
||||||
else:
|
# If copy = 0, then we should always hit the disk.
|
||||||
animNode = loader.loadModel(animPath,
|
loaderOptions = LoaderOptions(loaderOptions)
|
||||||
loaderOptions = self.animLoaderOptions)
|
loaderOptions.setFlags(loaderOptions.getFlags() & ~LoaderOptions.LFNoRamCache)
|
||||||
|
|
||||||
|
animNode = loader.loadModel(animPath, loaderOptions = loaderOptions)
|
||||||
if animNode == None:
|
if animNode == None:
|
||||||
return None
|
return None
|
||||||
animBundle = (animNode.find("**/+AnimBundleNode").node()).getBundle()
|
animBundle = (animNode.find("**/+AnimBundleNode").node()).getBundle()
|
||||||
|
|
||||||
bundle = self.__partBundleDict[lodName][truePartName].node().getBundle()
|
bundle = self.__partBundleDict[lodName][subpartDef.truePartName].partBundle.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.
|
||||||
@ -1706,13 +1757,13 @@ 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, subset)
|
animControl = bundle.bindAnim(animBundle, -1, subpartDef.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
|
||||||
anim[1] = animControl
|
anim.animControl = animControl
|
||||||
assert Actor.notify.debug("binding anim: %s to part: %s, lod: %s" %
|
assert Actor.notify.debug("binding anim: %s to part: %s, lod: %s" %
|
||||||
(animName, partName, lodName))
|
(animName, partName, lodName))
|
||||||
return animControl
|
return animControl
|
||||||
@ -1733,14 +1784,14 @@ class Actor(DirectObject, NodePath):
|
|||||||
if partLod.isEmpty():
|
if partLod.isEmpty():
|
||||||
Actor.notify.warning("no lod named: %s" % (lodName))
|
Actor.notify.warning("no lod named: %s" % (lodName))
|
||||||
return None
|
return None
|
||||||
for partName in other.__partBundleDict[lodName].keys():
|
for partName, partDef in other.__partBundleDict[lodName].items():
|
||||||
|
model = partDef.partModel.copySubgraph()
|
||||||
|
|
||||||
# find the part in our tree
|
# find the part in our tree
|
||||||
#partBundle = self.find("**/" + Actor.partPrefix + partName)
|
|
||||||
# Asad: changed above line to below
|
|
||||||
partBundle = partLod.find("**/" + Actor.partPrefix + partName)
|
partBundle = partLod.find("**/" + Actor.partPrefix + partName)
|
||||||
if (partBundle != None):
|
if (partBundle != None):
|
||||||
# store the part bundle
|
# store the part bundle
|
||||||
self.__partBundleDict[lodName][partName] = partBundle
|
self.__partBundleDict[lodName][partName] = Actor.PartDef(partBundle, model)
|
||||||
else:
|
else:
|
||||||
Actor.notify.error("lod: %s has no matching part: %s" %
|
Actor.notify.error("lod: %s has no matching part: %s" %
|
||||||
(lodName, partName))
|
(lodName, partName))
|
||||||
@ -1755,8 +1806,7 @@ class Actor(DirectObject, NodePath):
|
|||||||
for partName, subpartDef in other.__subpartDict.items():
|
for partName, subpartDef in other.__subpartDict.items():
|
||||||
subpartDefCopy = subpartDef
|
subpartDefCopy = subpartDef
|
||||||
if subpartDef:
|
if subpartDef:
|
||||||
truePartName, subset = subpartDef
|
subpartDef = subpartDef.makeCopy()
|
||||||
subpartDefCopy = (truePartName, PartSubset(subset))
|
|
||||||
self.__subpartDict[partName] = subpartDef
|
self.__subpartDict[partName] = subpartDef
|
||||||
|
|
||||||
def __copyAnimControls(self, other):
|
def __copyAnimControls(self, other):
|
||||||
@ -1770,9 +1820,10 @@ class Actor(DirectObject, NodePath):
|
|||||||
for partName in other.__animControlDict[lodName].keys():
|
for partName in other.__animControlDict[lodName].keys():
|
||||||
self.__animControlDict[lodName][partName] = {}
|
self.__animControlDict[lodName][partName] = {}
|
||||||
for animName in other.__animControlDict[lodName][partName].keys():
|
for animName in other.__animControlDict[lodName][partName].keys():
|
||||||
# else just copy what's there
|
anim = other.__animControlDict[lodName][partName][animName]
|
||||||
self.__animControlDict[lodName][partName][animName] = \
|
anim = anim.makeCopy()
|
||||||
[other.__animControlDict[lodName][partName][animName][0], None]
|
self.__animControlDict[lodName][partName][animName] = anim
|
||||||
|
|
||||||
|
|
||||||
def actorInterval(self, *args, **kw):
|
def actorInterval(self, *args, **kw):
|
||||||
from direct.interval import ActorInterval
|
from direct.interval import ActorInterval
|
||||||
|
Loading…
x
Reference in New Issue
Block a user