added parentMgr for more flexible distributed reparentTo's
This commit is contained in:
parent
9d18ee6aff
commit
b64887d146
|
|
@ -8,6 +8,7 @@ import ClientDistClass
|
|||
import CRCache
|
||||
import ConnectionRepository
|
||||
import PythonUtil
|
||||
import ParentMgr
|
||||
import time
|
||||
|
||||
class ClientRepository(ConnectionRepository.ConnectionRepository):
|
||||
|
|
@ -27,6 +28,10 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||
self.bootedIndex = None
|
||||
self.bootedText = None
|
||||
|
||||
# create a parentMgr to handle distributed reparents
|
||||
# this used to be 'token2nodePath'
|
||||
self.parentMgr = ParentMgr.ParentMgr()
|
||||
|
||||
def setServerDelta(self, delta):
|
||||
"""
|
||||
Indicates the approximate difference in seconds between the
|
||||
|
|
|
|||
|
|
@ -48,15 +48,14 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath):
|
|||
|
||||
def b_setParent(self, parentToken):
|
||||
self.setParent(parentToken)
|
||||
# it's important to call the local setParent first.
|
||||
self.d_setParent(parentToken)
|
||||
return None
|
||||
|
||||
def d_setParent(self, parentToken):
|
||||
self.sendUpdate("setParent", [parentToken])
|
||||
return None
|
||||
|
||||
def setParent(self, parentToken):
|
||||
return self.do_setParent(parentToken)
|
||||
self.do_setParent(parentToken)
|
||||
|
||||
def do_setParent(self, parentToken):
|
||||
"""do_setParent(self, int parentToken)
|
||||
|
|
@ -66,10 +65,7 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath):
|
|||
desired.
|
||||
"""
|
||||
if not self.isDisabled():
|
||||
assert(self.cr.token2nodePath.has_key(parentToken))
|
||||
parent = self.cr.token2nodePath[parentToken]
|
||||
self.wrtReparentTo(parent)
|
||||
return None
|
||||
self.cr.parentMgr.requestReparent(self, parentToken)
|
||||
|
||||
###### set pos and hpr functions #######
|
||||
|
||||
|
|
|
|||
|
|
@ -319,6 +319,18 @@ class DistributedSmoothNode(DistributedNode.DistributedNode):
|
|||
else:
|
||||
NodePath.wrtReparentTo(self, parent)
|
||||
|
||||
def d_setParent(self, parentToken):
|
||||
# We override this DistributedNode method to force a full position
|
||||
# update immediately after the distributed setParent is sent.
|
||||
# See ParentMgr.py for an explanation.
|
||||
DistributedNode.DistributedNode.d_setParent(self, parentToken)
|
||||
|
||||
self.forceToTruePosition()
|
||||
xyz = self.getPos()
|
||||
hpr = self.getHpr()
|
||||
x=xyz[0]; y=xyz[1]; z=xyz[2]
|
||||
h=hpr[0]; p=hpr[1]; r=hpr[2]
|
||||
self.d_setSmPosHpr(x,y,z,h,p,r)
|
||||
|
||||
### Monitor clock sync ###
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
"""ParentMgr module: contains the ParentMgr class"""
|
||||
|
||||
from ShowBaseGlobal import *
|
||||
from ToontownGlobals import *
|
||||
import DirectNotifyGlobal
|
||||
|
||||
class ParentMgr:
|
||||
"""ParentMgr holds a table of nodes that avatars may be parented to
|
||||
in a distributed manner. All clients within a particular zone maintain
|
||||
identical tables of these nodes, and the nodes are referenced by 'tokens'
|
||||
which the clients can pass to each other to communicate distributed
|
||||
reparenting information.
|
||||
|
||||
The functionality of ParentMgr used to be implemented with a simple
|
||||
token->node dictionary. As distributed 'parent' objects were manifested,
|
||||
they would add themselves to the dictionary. Problems occured when
|
||||
distributed avatars were manifested before the objects to which they
|
||||
were parented to.
|
||||
|
||||
Since the order of object manifestation depends on the order of the
|
||||
classes in the DC file, we could maintain an ordering of DC definitions
|
||||
that ensures that the necessary objects are manifested before avatars.
|
||||
However, it's easy enough to keep a list of pending reparents and thus
|
||||
support the general case without requiring any strict ordering in the DC.
|
||||
"""
|
||||
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('ParentMgr')
|
||||
|
||||
def __init__(self):
|
||||
self.token2nodepath = {}
|
||||
# these are nodepaths that have requested to be parented to
|
||||
# a node that has not yet been registered
|
||||
self.pendingChildren = {}
|
||||
|
||||
def destroy(self):
|
||||
del self.token2nodepath
|
||||
del self.pendingChildren
|
||||
|
||||
def requestReparent(self, child, parentToken):
|
||||
if parentToken in self.token2nodepath.keys():
|
||||
# this parent has registered
|
||||
self.notify.debug('performing wrtReparent of %s to %s' %
|
||||
(child, parentToken))
|
||||
child.wrtReparentTo(self.token2nodepath[parentToken])
|
||||
else:
|
||||
self.notify.warning(
|
||||
"child %s requested reparent to '%s', not in list" %
|
||||
(child, parentToken))
|
||||
if not self.pendingChildren.has_key(parentToken):
|
||||
self.pendingChildren[parentToken] = []
|
||||
self.pendingChildren[parentToken].append(child)
|
||||
|
||||
def registerParent(self, token, parent):
|
||||
if token in self.token2nodepath.keys():
|
||||
self.notify.error(
|
||||
'token %s already in the table, referencing %s' %
|
||||
(token, self.token2nodepath[token]))
|
||||
|
||||
self.notify.debug('registering %s as %s' % (parent, token))
|
||||
self.token2nodepath[token] = parent
|
||||
|
||||
# if we have any pending children, add them
|
||||
if token in self.pendingChildren.keys():
|
||||
children = self.pendingChildren[token]
|
||||
for child in children:
|
||||
# NOTE: We do a plain-old reparentTo here (non-wrt)
|
||||
# under the assumption that the node has been
|
||||
# positioned as if it is already under the new parent.
|
||||
#
|
||||
# The only case that I can think of where the parent
|
||||
# node would not have been registered at the time of
|
||||
# the reparent request is when we're entering a new
|
||||
# zone and manifesting remote toons along with
|
||||
# other distributed objects, and a remote toon is
|
||||
# requesting to be parented to geometry owned by a
|
||||
# distributed object that has not yet been manifested.
|
||||
#
|
||||
# It is therefore important for that remote toon to
|
||||
# have his position set as a required field, relative
|
||||
# to the parent node, after the reparent request.
|
||||
# If the node has already been registered, the toon will
|
||||
# be in the correct position. Otherwise, the toon will
|
||||
# have the correct position but the wrong parent node,
|
||||
# until this code runs and corrects the toon's parent
|
||||
# node. Since we don't start rendering until all objects
|
||||
# in a new zone have been generated, all of that action
|
||||
# will happen in a single frame, and the net result will
|
||||
# be that the toon will be in the right place when
|
||||
# rendering starts.
|
||||
self.notify.debug('performing reparent of %s to %s' %
|
||||
(child, token))
|
||||
child.reparentTo(self.token2nodepath[token])
|
||||
del self.pendingChildren[token]
|
||||
|
||||
def unregisterParent(self, token):
|
||||
if token not in self.token2nodepath.keys():
|
||||
self.notify.warning('unknown token %s' % token)
|
||||
return
|
||||
self.notify.debug("unregistering parent '%s'" % (token))
|
||||
del self.token2nodepath[token]
|
||||
Loading…
Reference in New Issue