diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 53eaf3808d..60bd7df8dc 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -566,7 +566,7 @@ class Actor(DirectObject, NodePath): # and sort them every time somebody asks for the list self.__sortedLODNames = self.__partBundleDict.keys() # Reverse sort the doing a string->int - def sortFunc(x, y): + def sortKey(x): if not str(x).isdigit(): smap = {'h':3, 'm':2, @@ -574,19 +574,16 @@ class Actor(DirectObject, NodePath): 'f':0} """ - sx = smap.get(x[0],None) - sy = smap.get(y[0],None) + sx = smap.get(x[0], None) if sx is None: self.notify.error('Invalid lodName: %s' % x) - if sy is None: - self.notify.error('Invalid lodName: %s' % y) """ - return cmp(smap[y[0]], smap[x[0]]) + return smap[x[0]] else: - return cmp (int(y), int(x)) + return int(x) - self.__sortedLODNames.sort(sortFunc) + self.__sortedLODNames.sort(key=sortKey, reverse=True) def getLODNames(self): """ diff --git a/direct/src/directnotify/DirectNotify.py b/direct/src/directnotify/DirectNotify.py index f2b8e351d1..923de31a44 100644 --- a/direct/src/directnotify/DirectNotify.py +++ b/direct/src/directnotify/DirectNotify.py @@ -64,7 +64,7 @@ class DirectNotify: # we're running before ShowBase has finished initializing; and # we import it directly from libpandaexpress, in case we're # running before libpanda.dll is available. - from libpandaexpress import ConfigVariableString + from panda3d.core import ConfigVariableString dconfigParam = ("notify-level-" + categoryName) cvar = ConfigVariableString(dconfigParam, "") diff --git a/direct/src/directnotify/Notifier.py b/direct/src/directnotify/Notifier.py index 5b1508fa99..eb91d5244e 100644 --- a/direct/src/directnotify/Notifier.py +++ b/direct/src/directnotify/Notifier.py @@ -4,7 +4,7 @@ for the programmer/user """ from LoggerGlobal import defaultLogger from direct.showbase import PythonUtil -from libpandaexpress import ConfigVariableBool +from panda3d.core import ConfigVariableBool import time import types import sys @@ -18,7 +18,7 @@ class Notifier: # with the C++ notify system. streamWriter = None if ConfigVariableBool('notify-integrate', True): - from libpandaexpress import StreamWriter, Notify + from panda3d.core import StreamWriter, Notify streamWriter = StreamWriter(Notify.out(), False) showTime = ConfigVariableBool('notify-timestamp', False) diff --git a/direct/src/directscripts/packpanda.nsi b/direct/src/directscripts/packpanda.nsi index dad5e4beb5..a57514c799 100755 --- a/direct/src/directscripts/packpanda.nsi +++ b/direct/src/directscripts/packpanda.nsi @@ -103,8 +103,6 @@ Section "${SMDIRECTORY}" SecCore File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\filter\*.sha" SetOutPath $INSTDIR\direct File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\*.py" - SetOutPath $INSTDIR - File "${PSOURCE}\panda3d.py" !else File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\src\directscripts\*" SetOutPath $INSTDIR\direct\filter @@ -112,11 +110,15 @@ Section "${SMDIRECTORY}" SecCore SetOutPath $INSTDIR\direct File /r /x CVS /x Opt?-Win32 "${PSOURCE}\direct\src\*.py" File "${PANDA}\tmp\__init__.py" - SetOutPath $INSTDIR - File "${PSOURCE}\direct\src\ffi\panda3d.py" !endif + Delete "$INSTDIR\panda3d.py" + Delete "$INSTDIR\panda3d.pyc" + Delete "$INSTDIR\panda3d.pyo" SetOutPath $INSTDIR\pandac File /r "${PANDA}\pandac\*.py" + SetOutPath $INSTDIR\panda3d + File /r "${PANDA}\panda3d\*.py" + File /r "${PANDA}\panda3d\*.pyd" SetOutPath $INSTDIR\python File /r "${PANDA}\python\*" RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 49bce8268d..8711bd08b6 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -83,7 +83,7 @@ class SelectedNodePaths(DirectObject): break # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # First see if its already in the selected dictionary dnp = self.getSelectedDict(id) # If so, deselect it @@ -104,7 +104,7 @@ class SelectedNodePaths(DirectObject): # Show its bounding box dnp.highlight(fRecompute = 0) # Add it to the selected dictionary - self.selectedDict[dnp.id()] = dnp + self.selectedDict[dnp.get_key()] = dnp self.selectedList.append(dnp) # [gjeon] # And update last @@ -117,7 +117,7 @@ class SelectedNodePaths(DirectObject): def deselect(self, nodePath): """ Deselect the specified node path """ # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # See if it is in the selected dictionary dnp = self.getSelectedDict(id) if dnp: @@ -240,7 +240,7 @@ class SelectedNodePaths(DirectObject): def getDirectNodePath(self, nodePath): # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # First check selected dict dnp = self.getSelectedDict(id) if dnp: diff --git a/direct/src/distributed/AstronDatabaseInterface.py b/direct/src/distributed/AstronDatabaseInterface.py index e5bdbc5626..4b425d05e6 100644 --- a/direct/src/distributed/AstronDatabaseInterface.py +++ b/direct/src/distributed/AstronDatabaseInterface.py @@ -32,7 +32,7 @@ class AstronDatabaseInterface: """ # Save the callback: - ctx = self.air.contextAllocator.allocate() + ctx = self.air.getContext() self._callbacks[ctx] = callback # Pack up/count valid fields. @@ -72,7 +72,6 @@ class AstronDatabaseInterface: self._callbacks[ctx](doId) del self._callbacks[ctx] - self.air.contextAllocator.free(ctx) def queryObject(self, databaseId, doId, callback): """ @@ -84,7 +83,7 @@ class AstronDatabaseInterface: """ # Save the callback: - ctx = self.air.contextAllocator.allocate() + ctx = self.air.getContext() self._callbacks[ctx] = callback # Generate and send the datagram: @@ -138,7 +137,6 @@ class AstronDatabaseInterface: finally: del self._callbacks[ctx] - self.air.contextAllocator.free(ctx) def updateObject(self, databaseId, doId, dclass, newFields, oldFields=None, callback=None): """ @@ -192,7 +190,7 @@ class AstronDatabaseInterface: # Generate and send the datagram: dg = PyDatagram() if oldFields is not None: - ctx = self.air.contextAllocator.allocate() + ctx = self.air.getContext() self._callbacks[ctx] = callback if fieldCount == 1: dg.addServerHeader(databaseId, self.air.ourChannel, @@ -235,6 +233,11 @@ class AstronDatabaseInterface: self._callbacks[ctx](None) return + if not di.getRemainingSize(): + # We failed due to other reasons. + if self._callbacks[ctx]: + return self._callbacks[ctx]({}) + if multi: fieldCount = di.getUint16() else: @@ -260,7 +263,6 @@ class AstronDatabaseInterface: finally: del self._callbacks[ctx] - self.air.contextAllocator.free(ctx) def handleDatagram(self, msgType, di): if msgType == DBSERVER_CREATE_OBJECT_RESP: diff --git a/direct/src/distributed/AstronInternalRepository.py b/direct/src/distributed/AstronInternalRepository.py index f05f12efb0..bf2d27cc9c 100644 --- a/direct/src/distributed/AstronInternalRepository.py +++ b/direct/src/distributed/AstronInternalRepository.py @@ -7,6 +7,80 @@ from ConnectionRepository import ConnectionRepository from PyDatagram import PyDatagram from PyDatagramIterator import PyDatagramIterator from AstronDatabaseInterface import AstronDatabaseInterface +from NetMessenger import NetMessenger +import collections + +# Helper functions for logging output: +def msgpack_length(dg, length, fix, maxfix, tag8, tag16, tag32): + if length < maxfix: + dg.addUint8(fix + length) + elif tag8 is not None and length < 1<<8: + dg.addUint8(tag8) + dg.addUint8(length) + elif tag16 is not None and length < 1<<16: + dg.addUint8(tag16) + dg.addBeUint16(length) + elif tag32 is not None and length < 1<<32: + dg.addUint8(tag32) + dg.addBeUint32(length) + else: + raise ValueError('Value too big for MessagePack') + +def msgpack_encode(dg, element): + if element == None: + dg.addUint8(0xc0) + elif element == False: + dg.addUint8(0xc2) + elif element == True: + dg.addUint8(0xc3) + elif isinstance(element, (int, long)): + if -32 <= element < 128: + dg.addInt8(element) + elif 128 <= element < 256: + dg.addUint8(0xcc) + dg.addUint8(element) + elif 256 <= element < 65536: + dg.addUint8(0xcd) + dg.addBeUint16(element) + elif 65536 <= element < (1<<32): + dg.addUint8(0xce) + dg.addBeUint32(element) + elif (1<<32) <= element < (1<<64): + dg.addUint8(0xcf) + dg.addBeUint64(element) + elif -128 <= element < -32: + dg.addUint8(0xd0) + dg.addInt8(element) + elif -32768 <= element < -128: + dg.addUint8(0xd1) + dg.addBeInt16(element) + elif -1<<31 <= element < -32768: + dg.addUint8(0xd2) + dg.addBeInt32(element) + elif -1<<63 <= element < -1<<31: + dg.addUint8(0xd3) + dg.addBeInt64(element) + else: + raise ValueError('int out of range for msgpack: %d' % element) + elif isinstance(element, dict): + msgpack_length(dg, len(element), 0x80, 0x10, None, 0xde, 0xdf) + for k,v in element.items(): + msgpack_encode(dg, k) + msgpack_encode(dg, v) + elif isinstance(element, list): + msgpack_length(dg, len(element), 0x90, 0x10, None, 0xdc, 0xdd) + for v in element: + msgpack_encode(dg, v) + elif isinstance(element, basestring): + msgpack_length(dg, len(element), 0xa0, 0x20, 0xd9, 0xda, 0xdb) + dg.appendData(element) + elif isinstance(element, float): + # Python does not distinguish between floats and doubles, so we send + # everything as a double in MsgPack: + dg.addUint8(0xcb) + dg.addFloat64(element) + else: + raise TypeError('Encountered non-MsgPack-packable value: %r' % element) class AstronInternalRepository(ConnectionRepository): """ @@ -43,9 +117,12 @@ class AstronInternalRepository(ConnectionRepository): self.channelAllocator = UniqueIdAllocator(baseChannel, baseChannel+maxChannels-1) self._registeredChannels = set() - self.contextAllocator = UniqueIdAllocator(0, 100) + self.__contextCounter = 0 + + self.netMessenger = NetMessenger(self) self.dbInterface = AstronDatabaseInterface(self) + self.__callbacks = {} self.ourChannel = self.allocateChannel() @@ -61,6 +138,10 @@ class AstronInternalRepository(ConnectionRepository): self.readDCFile(dcFileNames) + def getContext(self): + self.__contextCounter = (self.__contextCounter + 1) & 0xFFFFFFFF + return self.__contextCounter + def allocateChannel(self): """ Allocate an unused channel out of this AIR's configured channel space. @@ -153,6 +234,11 @@ class AstronInternalRepository(ConnectionRepository): DBSERVER_OBJECT_SET_FIELD_IF_EQUALS_RESP, DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS_RESP): self.dbInterface.handleDatagram(msgType, di) + elif msgType == DBSS_OBJECT_GET_ACTIVATED_RESP: + self.handleGetActivatedResp(di) + elif msgType >= 20000: + # These messages belong to the NetMessenger: + self.netMessenger.handle(msgType, di) else: self.notify.warning('Received message with unknown MsgType=%d' % msgType) @@ -211,6 +297,30 @@ class AstronInternalRepository(ConnectionRepository): do.delete() do.sendDeleteEvent() + def handleGetActivatedResp(self, di): + ctx = di.getUint32() + doId = di.getUint32() + activated = di.getUint8() + + if ctx not in self.__callbacks: + self.notify.warning('Received unexpected DBSS_OBJECT_GET_ACTIVATED_RESP (ctx: %d)' %ctx) + return + + try: + self.__callbacks[ctx](doId, activated) + finally: + del self.__callbacks[ctx] + + def getActivated(self, doId, callback): + ctx = self.getContext() + self.__callbacks[ctx] = callback + + dg = PyDatagram() + dg.addServerHeader(doId, self.ourChannel, DBSS_OBJECT_GET_ACTIVATED) + dg.addUint32(ctx) + dg.addUint32(doId) + self.send(dg) + def sendUpdate(self, do, fieldName, args): """ Send a field update for the given object. @@ -403,7 +513,7 @@ class AstronInternalRepository(ConnectionRepository): self.eventSocket = SocketUDPOutgoing() self.eventSocket.InitToAddress(address) - def writeServerEvent(self, logtype, *args): + def writeServerEvent(self, logtype, *args, **kwargs): """ Write an event to the central Event Logger, if one is configured. @@ -415,9 +525,16 @@ class AstronInternalRepository(ConnectionRepository): if self.eventSocket is None: return # No event logger configured! + log = collections.OrderedDict() + log['type'] = logtype + log['sender'] = self.eventLogId + + for i,v in enumerate(args): + # +1 because the logtype was _0, so we start at _1 + log['_%d' % (i+1)] = v + + log.update(kwargs) + dg = PyDatagram() - dg.addString(self.eventLogId) - dg.addString(logtype) - for arg in args: - dg.addString(str(arg)) + msgpack_encode(dg, log) self.eventSocket.Send(dg.getMessage()) diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index f42d130363..f839873bcc 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -88,6 +88,8 @@ MsgName2Id = { # DBSS-backed-object messages: 'DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS': 2200, 'DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS_OTHER': 2201, + 'DBSS_OBJECT_GET_ACTIVATED': 2207, + 'DBSS_OBJECT_GET_ACTIVATED_RESP': 2208, 'DBSS_OBJECT_DELETE_FIELD_DISK': 2230, 'DBSS_OBJECT_DELETE_FIELDS_DISK': 2231, 'DBSS_OBJECT_DELETE_DISK': 2232, @@ -137,9 +139,7 @@ MsgName2Id = { MsgId2Names = invertDictLossless(MsgName2Id) # put msg names in module scope, assigned to msg value -for name, value in MsgName2Id.items(): - exec('%s = %s' % (name, value)) -del name, value +globals().update(MsgName2Id) # These messages are ignored when the client is headed to the quiet zone QUIET_ZONE_IGNORED_LIST = [ diff --git a/direct/src/distributed/MsgTypesCMU.py b/direct/src/distributed/MsgTypesCMU.py index 8501866a5b..b91a505453 100644 --- a/direct/src/distributed/MsgTypesCMU.py +++ b/direct/src/distributed/MsgTypesCMU.py @@ -26,6 +26,4 @@ MsgName2Id = { MsgId2Names = invertDictLossless(MsgName2Id) # put msg names in module scope, assigned to msg value -for name, value in MsgName2Id.items(): - exec('%s = %s' % (name, value)) -del name, value +globals().update(MsgName2Id) diff --git a/direct/src/distributed/NetMessenger.py b/direct/src/distributed/NetMessenger.py index 0d24e2a1ff..4994eeb85f 100755 --- a/direct/src/distributed/NetMessenger.py +++ b/direct/src/distributed/NetMessenger.py @@ -6,26 +6,6 @@ from direct.distributed.PyDatagram import PyDatagram from direct.showbase.Messenger import Messenger -# Messages do not need to be in the MESSAGE_TYPES list. -# This is just an optimization. If the message is found -# in this list, it is reduced to an integer index and -# the message string is not sent. Otherwise, the message -# string is sent in the datagram. -MESSAGE_TYPES=( - "avatarOnline", - "avatarOffline", - "create", - "needUberdogCreates", - "transferDo", -) - -# This is the reverse look up for the recipient of the -# datagram: -MESSAGE_STRINGS={} -for i in zip(MESSAGE_TYPES, range(1, len(MESSAGE_TYPES)+1)): - MESSAGE_STRINGS[i[0]]=i[1] - - class NetMessenger(Messenger): """ This works very much like the Messenger class except that messages @@ -34,62 +14,101 @@ class NetMessenger(Messenger): """ notify = DirectNotifyGlobal.directNotify.newCategory('NetMessenger') - def __init__(self, air, channels): + def __init__(self, air, baseChannel=20000, baseMsgType=20000): """ air is the AI Repository. - channels is a list of channel IDs (uint32 values) + baseChannel is the channel that the first message is sent on. + baseMsgType is the MsgType of the same. """ assert self.notify.debugCall() Messenger.__init__(self) self.air=air - self.channels=channels - for i in self.channels: - self.air.registerForChannel(i) + self.baseChannel = baseChannel + self.baseMsgType = baseMsgType + + self.__message2type = {} + self.__type2message = {} + self.__message2channel = {} def clear(self): assert self.notify.debugCall() - for i in self.channels: - self.air.unRegisterChannel(i) - del self.air - del self.channels Messenger.clear(self) - def send(self, message, sentArgs=[]): + def register(self, code, message): + assert self.notify.debugCall() + channel = self.baseChannel + code + msgType = self.baseMsgType + code + + if message in self.__message2type: + self.notify.error('Tried to register message %s twice!' % message) + return + + self.__message2type[message] = msgType + self.__type2message[msgType] = message + self.__message2channel[message] = channel + + def prepare(self, message, sentArgs=[]): """ - Send message to All AI and Uber Dog servers. + Prepare the datagram that would get sent in order to send this message + to its designated channel. """ assert self.notify.debugCall() + + # Make sure the message is registered: + if message not in self.__message2type: + self.notify.error('Tried to send unregistered message %s!' % message) + return + datagram = PyDatagram() # To: datagram.addUint8(1) - datagram.addChannel(self.channels[0]) + datagram.addChannel(self.__message2channel[message]) # From: datagram.addChannel(self.air.ourChannel) - #if 1: # We send this just because the air expects it: - # # Add an 'A' for AI - # datagram.addUint8(ord('A')) - messageType=MESSAGE_STRINGS.get(message, 0) + messageType=self.__message2type[message] datagram.addUint16(messageType) - if messageType: - datagram.addString(str(dumps(sentArgs))) - else: - datagram.addString(str(dumps((message, sentArgs)))) - self.air.send(datagram) + datagram.addString(str(dumps(sentArgs))) - def handle(self, pickleData): + return datagram + + def accept(self, message, *args): + if message not in self.__message2channel: + self.notify.error('Tried to accept unregistered message %s!' % message) + return + + anyAccepting = bool(self.whoAccepts(message)) + if not anyAccepting: + self.air.registerForChannel(self.__message2channel[message]) + + Messenger.accept(self, message, *args) + + def send(self, message, sentArgs=[]): """ - Send pickleData from the net on the local netMessenger. - The internal data in pickleData should have a tuple of - (messageString, sendArgsList). + Send message to anything that's listening for it. """ assert self.notify.debugCall() - messageType=self.air.getMsgType() - if messageType: - message=MESSAGE_TYPES[messageType-1] - sentArgs=loads(pickleData) - else: - (message, sentArgs) = loads(pickleData) + + datagram = self.prepare(message, sentArgs) + self.air.send(datagram) Messenger.send(self, message, sentArgs=sentArgs) + def handle(self, msgType, di): + """ + Send data from the net on the local netMessenger. + """ + assert self.notify.debugCall() + if msgType not in self.__type2message: + self.notify.warning('Received unknown message: %d' % msgType) + return + + message = self.__type2message[msgType] + sentArgs=loads(di.getString()) + + if type(sentArgs) != list: + self.notify.warning('Received non-list item in %s message: %r' % + (message, sentArgs)) + return + + Messenger.send(self, message, sentArgs=sentArgs) diff --git a/direct/src/extensions/EggGroupNode-extensions.py b/direct/src/extensions/EggGroupNode-extensions.py deleted file mode 100644 index 660e556a8f..0000000000 --- a/direct/src/extensions/EggGroupNode-extensions.py +++ /dev/null @@ -1,11 +0,0 @@ - - # For iterating over children - def getChildren(self): - """Returns a Python list of the egg node's children.""" - result = [] - child = self.getFirstChild() - while (child != None): - result.append(child) - child = self.getNextChild() - return result - diff --git a/direct/src/extensions/EggPrimitive-extensions.py b/direct/src/extensions/EggPrimitive-extensions.py deleted file mode 100644 index 60c5bf7392..0000000000 --- a/direct/src/extensions/EggPrimitive-extensions.py +++ /dev/null @@ -1,8 +0,0 @@ - - # For iterating over vertices - def getVertices(self): - """Returns a Python list of the egg primitive's vertices.""" - result = [] - for i in range(self.getNumVertices()): - result.append(self.getVertex(i)) - return result diff --git a/direct/src/extensions/NodePathCollection-extensions.py b/direct/src/extensions/NodePathCollection-extensions.py deleted file mode 100644 index 99a1c7fca6..0000000000 --- a/direct/src/extensions/NodePathCollection-extensions.py +++ /dev/null @@ -1,34 +0,0 @@ - - """ - NodePathCollection-extensions module: contains methods to extend - functionality of the NodePathCollection class - """ - - # For iterating over children - def asList(self): - """Converts a NodePathCollection into a list""" - if self.isEmpty(): - return [] - else: - npList = [] - for nodePathIndex in range(self.getNumPaths()): - npList.append(self.getPath(nodePathIndex)) - return npList - - def getTightBounds(self): - from pandac import Point3 - - if self.getNumPaths() == 0: - return (Point3.Point3(0), Point3.Point3(0)) - - v1, v2 = self.getPath(0).getTightBounds() - for i in range(1, self.getNumPaths()): - v1x, v2x = self.getPath(i).getTightBounds() - v1 = Point3.Point3(min(v1[0], v1x[0]), - min(v1[1], v1x[1]), - min(v1[2], v1x[2])) - v2 = Point3.Point3(max(v2[0], v2x[0]), - max(v2[1], v2x[1]), - max(v2[2], v2x[2])) - - return v1, v2 diff --git a/direct/src/extensions/OdeBody-extensions.py b/direct/src/extensions/OdeBody-extensions.py deleted file mode 100755 index 6b0f60a633..0000000000 --- a/direct/src/extensions/OdeBody-extensions.py +++ /dev/null @@ -1,6 +0,0 @@ - -def getConvertedJoint(self, index): - """ - Return a downcast joint on this body. - """ - return self.getJoint(index).convert() diff --git a/direct/src/extensions/OdeGeom-extensions.py b/direct/src/extensions/OdeGeom-extensions.py deleted file mode 100755 index 0796dc5cf7..0000000000 --- a/direct/src/extensions/OdeGeom-extensions.py +++ /dev/null @@ -1,44 +0,0 @@ - -def convert(self): - """ - Do a sort of pseudo-downcast on this geom in - order to expose its specialized functions. - """ - if self.getGeomClass() == OdeGeom.GCSphere: - return self.convertToSphere() - elif self.getGeomClass() == OdeGeom.GCBox: - return self.convertToBox() - elif self.getGeomClass() == OdeGeom.GCCappedCylinder: - return self.convertToCappedCylinder() - elif self.getGeomClass() == OdeGeom.GCPlane: - return self.convertToPlane() - elif self.getGeomClass() == OdeGeom.GCRay: - return self.convertToRay() - # elif self.getGeomClass() == OdeGeom.GCConvex: - # return self.convertToConvex() - # elif self.getGeomClass() == OdeGeom.GCGeomTransform: - # return self.convertToGeomTransform() - elif self.getGeomClass() == OdeGeom.GCTriMesh: - return self.convertToTriMesh() - # elif self.getGeomClass() == OdeGeom.GCHeightfield: - # return self.convertToHeightfield() - elif self.getGeomClass() == OdeGeom.GCSimpleSpace: - return self.convertToSimpleSpace() - elif self.getGeomClass() == OdeGeom.GCHashSpace: - return self.convertToHashSpace() - elif self.getGeomClass() == OdeGeom.GCQuadTreeSpace: - return self.convertToQuadTreeSpace() - -def getConvertedSpace(self): - """ - """ - return self.getSpace().convert() - -def getAABounds(self): - """ - A more Pythonic way of calling getAABB(). - """ - min = Point3() - max = Point3() - self.getAABB(min,max) - return min,max \ No newline at end of file diff --git a/direct/src/extensions/OdeJoint-extensions.py b/direct/src/extensions/OdeJoint-extensions.py deleted file mode 100755 index 3e3eeccfc8..0000000000 --- a/direct/src/extensions/OdeJoint-extensions.py +++ /dev/null @@ -1,39 +0,0 @@ -def attach(self, body1, body2): - """ - Attach two bodies together. - If either body is None, the other will be attached to the environment. - """ - if body1 and body2: - self.attachBodies(body1, body2) - elif body1 and not body2: - self.attachBody(body1, 0) - elif not body1 and body2: - self.attachBody(body2, 1) - -def convert(self): - """ - Do a sort of pseudo-downcast on this joint in - order to expose its specialized functions. - """ - if self.getJointType() == OdeJoint.JTBall: - return self.convertToBall() - elif self.getJointType() == OdeJoint.JTHinge: - return self.convertToHinge() - elif self.getJointType() == OdeJoint.JTSlider: - return self.convertToSlider() - elif self.getJointType() == OdeJoint.JTContact: - return self.convertToContact() - elif self.getJointType() == OdeJoint.JTUniversal: - return self.convertToUniversal() - elif self.getJointType() == OdeJoint.JTHinge2: - return self.convertToHinge2() - elif self.getJointType() == OdeJoint.JTFixed: - return self.convertToFixed() - elif self.getJointType() == OdeJoint.JTNull: - return self.convertToNull() - elif self.getJointType() == OdeJoint.JTAMotor: - return self.convertToAMotor() - elif self.getJointType() == OdeJoint.JTLMotor: - return self.convertToLMotor() - elif self.getJointType() == OdeJoint.JTPlane2d: - return self.convertToPlane2d() diff --git a/direct/src/extensions/OdeSpace-extensions.py b/direct/src/extensions/OdeSpace-extensions.py deleted file mode 100755 index f110615831..0000000000 --- a/direct/src/extensions/OdeSpace-extensions.py +++ /dev/null @@ -1,32 +0,0 @@ - -def convert(self): - """ - Do a sort of pseudo-downcast on this space in - order to expose its specialized functions. - """ - if self.getClass() == OdeGeom.GCSimpleSpace: - return self.convertToSimpleSpace() - elif self.getClass() == OdeGeom.GCHashSpace: - return self.convertToHashSpace() - elif self.getClass() == OdeGeom.GCQuadTreeSpace: - return self.convertToQuadTreeSpace() - -def getConvertedGeom(self, index): - """ - Return a downcast geom on this body. - """ - return self.getGeom(index).convert() - -def getConvertedSpace(self): - """ - """ - return self.getSpace().convert() - -def getAABounds(self): - """ - A more Pythonic way of calling getAABB() - """ - min = Point3() - max = Point3() - self.getAABB(min,max) - return min,max \ No newline at end of file diff --git a/direct/src/extensions/Ramfile-extensions.py b/direct/src/extensions/Ramfile-extensions.py deleted file mode 100644 index a05a666a24..0000000000 --- a/direct/src/extensions/Ramfile-extensions.py +++ /dev/null @@ -1,15 +0,0 @@ - - """ - Ramfile-extensions module: contains methods to extend functionality - of the Ramfile class - """ - - def readlines(self): - """Reads all the lines at once and returns a list.""" - lines = [] - line = self.readline() - while line: - lines.append(line) - line = self.readline() - return lines - diff --git a/direct/src/extensions/StreamReader-extensions.py b/direct/src/extensions/StreamReader-extensions.py deleted file mode 100644 index 792abde3a6..0000000000 --- a/direct/src/extensions/StreamReader-extensions.py +++ /dev/null @@ -1,15 +0,0 @@ - - """ - StreamReader-extensions module: contains methods to extend functionality - of the StreamReader class - """ - - def readlines(self): - """Reads all the lines at once and returns a list.""" - lines = [] - line = self.readline() - while line: - lines.append(line) - line = self.readline() - return lines - diff --git a/direct/src/extensions_native/EggGroupNode_extensions.py b/direct/src/extensions_native/EggGroupNode_extensions.py deleted file mode 100644 index 6c6173e66f..0000000000 --- a/direct/src/extensions_native/EggGroupNode_extensions.py +++ /dev/null @@ -1,16 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - # For iterating over children -def getChildren(self): - """Returns a Python list of the egg node's children.""" - result = [] - child = self.getFirstChild() - while (child != None): - result.append(child) - child = self.getNextChild() - return result - -Dtool_funcToMethod(getChildren, EggGroupNode) -del getChildren diff --git a/direct/src/extensions_native/EggPrimitive_extensions.py b/direct/src/extensions_native/EggPrimitive_extensions.py deleted file mode 100644 index 657f99a132..0000000000 --- a/direct/src/extensions_native/EggPrimitive_extensions.py +++ /dev/null @@ -1,13 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - # For iterating over vertices -def getVertices(self): - """Returns a Python list of the egg primitive's vertices.""" - result = [] - for i in range(self.getNumVertices()): - result.append(self.getVertex(i)) - return result -Dtool_funcToMethod(getVertices, EggPrimitive) -del getVertices diff --git a/direct/src/extensions_native/NodePathCollection_extensions.py b/direct/src/extensions_native/NodePathCollection_extensions.py deleted file mode 100644 index f7f379ab32..0000000000 --- a/direct/src/extensions_native/NodePathCollection_extensions.py +++ /dev/null @@ -1,31 +0,0 @@ -##################################################################### - -# For iterating over children -def asList(self): - """Converts a NodePathCollection into a list""" - print "Warning: NodePathCollection.asList() is no longer needed and deprecated. Iterate on the collection directly instead." - return list(self) - -Dtool_funcToMethod(asList, NodePathCollection) -del asList -#####################################################################3333 - -def getTightBounds(self): - from pandac.PandaModules import Point3 - - if self.getNumPaths() == 0: - return (Point3(0), Point3(0)) - v1, v2 = self.getPath(0).getTightBounds() - for i in range(1, self.getNumPaths()): - v1x, v2x = self.getPath(i).getTightBounds() - v1 = Point3(min(v1[0], v1x[0]), - min(v1[1], v1x[1]), - min(v1[2], v1x[2])) - v2 = Point3(max(v2[0], v2x[0]), - max(v2[1], v2x[1]), - max(v2[2], v2x[2])) - return v1, v2 - -Dtool_funcToMethod(getTightBounds, NodePathCollection) -del getTightBounds -#####################################################################3333 diff --git a/direct/src/extensions_native/NodePath_extensions.py b/direct/src/extensions_native/NodePath_extensions.py index c1a19f3784..7b17dc34f6 100644 --- a/direct/src/extensions_native/NodePath_extensions.py +++ b/direct/src/extensions_native/NodePath_extensions.py @@ -154,15 +154,6 @@ def getAncestry(self): Dtool_funcToMethod(getAncestry, NodePath) del getAncestry ##################################################################### -def getTightBounds(self): - from pandac.PandaModules import Point3 - v1 = Point3(0) - v2 = Point3(0) - self.calcTightBounds(v1, v2) - return v1, v2 -Dtool_funcToMethod(getTightBounds, NodePath) -del getTightBounds -##################################################################### def pPrintString(self, other = None): """ diff --git a/direct/src/extensions_native/OdeBody_extensions.py b/direct/src/extensions_native/OdeBody_extensions.py deleted file mode 100755 index 78b71cb638..0000000000 --- a/direct/src/extensions_native/OdeBody_extensions.py +++ /dev/null @@ -1,18 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - -""" -OdeBody-extensions module: contains methods to extend functionality -of the OdeBody classe -""" - -def getConvertedJoint(self, index): - """ - Return a downcast joint on this body. - """ - return self.getJoint(index).convert() -Dtool_funcToMethod(getConvertedJoint, OdeBody) -del getConvertedJoint - diff --git a/direct/src/extensions_native/OdeGeom_extensions.py b/direct/src/extensions_native/OdeGeom_extensions.py deleted file mode 100755 index e154e05e55..0000000000 --- a/direct/src/extensions_native/OdeGeom_extensions.py +++ /dev/null @@ -1,60 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - -""" -OdeGeom-extensions module: contains methods to extend functionality -of the OdeGeom class -""" - -def convert(self): - """ - Do a sort of pseudo-downcast on this geom in - order to expose its specialized functions. - """ - if self.getClass() == OdeGeom.GCSphere: - return self.convertToSphere() - elif self.getClass() == OdeGeom.GCBox: - return self.convertToBox() - elif self.getClass() == OdeGeom.GCCappedCylinder: - return self.convertToCappedCylinder() - elif self.getClass() == OdeGeom.GCPlane: - return self.convertToPlane() - elif self.getClass() == OdeGeom.GCRay: - return self.convertToRay() - # elif self.getClass() == OdeGeom.GCConvex: - # return self.convertToConvex() - # elif self.getClass() == OdeGeom.GCGeomTransform: - # return self.convertToGeomTransform() - elif self.getClass() == OdeGeom.GCTriMesh: - return self.convertToTriMesh() - # elif self.getClass() == OdeGeom.GCHeightfield: - # return self.convertToHeightfield() - elif self.getClass() == OdeGeom.GCSimpleSpace: - return self.convertToSimpleSpace() - elif self.getClass() == OdeGeom.GCHashSpace: - return self.convertToHashSpace() - elif self.getClass() == OdeGeom.GCQuadTreeSpace: - return self.convertToQuadTreeSpace() -Dtool_funcToMethod(convert, OdeGeom) -del convert - -def getConvertedSpace(self): - """ - """ - return self.getSpace().convert() -Dtool_funcToMethod(getConvertedSpace, OdeGeom) -del getConvertedSpace - -def getAABounds(self): - """ - A more Pythonic way of calling getAABB() - """ - min = Point3() - max = Point3() - self.getAABB(min,max) - return min,max -Dtool_funcToMethod(getAABounds, OdeGeom) -del getAABounds - diff --git a/direct/src/extensions_native/OdeJoint_extensions.py b/direct/src/extensions_native/OdeJoint_extensions.py deleted file mode 100755 index e113e6fdfa..0000000000 --- a/direct/src/extensions_native/OdeJoint_extensions.py +++ /dev/null @@ -1,54 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - -""" -OdeJoint-extensions module: contains methods to extend functionality -of the OdeJoint class -""" - -def attach(self, body1, body2): - """ - Attach two bodies together. - If either body is None, the other will be attached to the environment. - """ - if body1 and body2: - self.attachBodies(body1, body2) - elif body1 and not body2: - self.attachBody(body1, 0) - elif not body1 and body2: - self.attachBody(body2, 1) -Dtool_funcToMethod(attach, OdeJoint) -del attach - -def convert(self): - """ - Do a sort of pseudo-downcast on this joint in - order to expose its specialized functions. - """ - if self.getJointType() == OdeJoint.JTBall: - return self.convertToBall() - elif self.getJointType() == OdeJoint.JTHinge: - return self.convertToHinge() - elif self.getJointType() == OdeJoint.JTSlider: - return self.convertToSlider() - elif self.getJointType() == OdeJoint.JTContact: - return self.convertToContact() - elif self.getJointType() == OdeJoint.JTUniversal: - return self.convertToUniversal() - elif self.getJointType() == OdeJoint.JTHinge2: - return self.convertToHinge2() - elif self.getJointType() == OdeJoint.JTFixed: - return self.convertToFixed() - elif self.getJointType() == OdeJoint.JTNull: - return self.convertToNull() - elif self.getJointType() == OdeJoint.JTAMotor: - return self.convertToAMotor() - elif self.getJointType() == OdeJoint.JTLMotor: - return self.convertToLMotor() - elif self.getJointType() == OdeJoint.JTPlane2d: - return self.convertToPlane2d() -Dtool_funcToMethod(convert, OdeJoint) -del convert - diff --git a/direct/src/extensions_native/OdeSpace_extensions.py b/direct/src/extensions_native/OdeSpace_extensions.py deleted file mode 100755 index 14b3c1e618..0000000000 --- a/direct/src/extensions_native/OdeSpace_extensions.py +++ /dev/null @@ -1,50 +0,0 @@ -#################################################################### -#Dtool_funcToMethod(func, class) -#del func -##################################################################### - -""" -OdeSpace-extensions module: contains methods to extend functionality -of the OdeSpace classe -""" - -def convert(self): - """ - Do a sort of pseudo-downcast on this space in - order to expose its specialized functions. - """ - if self.getClass() == OdeGeom.GCSimpleSpace: - return self.convertToSimpleSpace() - elif self.getClass() == OdeGeom.GCHashSpace: - return self.convertToHashSpace() - elif self.getClass() == OdeGeom.GCQuadTreeSpace: - return self.convertToQuadTreeSpace() -Dtool_funcToMethod(convert, OdeSpace) -del convert - -def getConvertedGeom(self, index): - """ - Return a downcast geom on this space. - """ - return self.getGeom(index).convert() -Dtool_funcToMethod(getConvertedGeom, OdeSpace) -del getConvertedGeom - -def getConvertedSpace(self): - """ - """ - return self.getSpace().convert() -Dtool_funcToMethod(getConvertedSpace, OdeSpace) -del getConvertedSpace - -def getAABounds(self): - """ - A more Pythonic way of calling getAABB() - """ - min = Point3() - max = Point3() - self.getAABB(min,max) - return min,max -Dtool_funcToMethod(getAABounds, OdeSpace) -del getAABounds - diff --git a/direct/src/extensions_native/Ramfile_extensions.py b/direct/src/extensions_native/Ramfile_extensions.py deleted file mode 100644 index c05040c73e..0000000000 --- a/direct/src/extensions_native/Ramfile_extensions.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Ramfile_extensions module: contains methods to extend functionality -of the Ramfile class -""" - -def readlines(self): - """Reads all the lines at once and returns a list.""" - lines = [] - line = self.readline() - while line: - lines.append(line) - line = self.readline() - return lines - -Dtool_funcToMethod(readlines, Ramfile) -del readlines diff --git a/direct/src/extensions_native/StreamReader_extensions.py b/direct/src/extensions_native/StreamReader_extensions.py deleted file mode 100755 index b4111cc965..0000000000 --- a/direct/src/extensions_native/StreamReader_extensions.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -StreamReader_extensions module: contains methods to extend functionality -of the StreamReader class -""" - -def readlines(self): - """Reads all the lines at once and returns a list.""" - lines = [] - line = self.readline() - while line: - lines.append(line) - line = self.readline() - return lines - -Dtool_funcToMethod(readlines, StreamReader) -del readlines diff --git a/direct/src/fsm/FSM.py b/direct/src/fsm/FSM.py index 593581f758..db85ad4b00 100644 --- a/direct/src/fsm/FSM.py +++ b/direct/src/fsm/FSM.py @@ -10,7 +10,6 @@ from direct.directnotify import DirectNotifyGlobal from direct.showbase import PythonUtil from direct.stdpy.threading import RLock import types -import string class FSMException(Exception): pass @@ -364,7 +363,7 @@ class FSM(DirectObject): # If self.defaultTransitions is None, it means to accept # all requests whose name begins with a capital letter. # These are direct requests to a particular state. - if request[0] in string.uppercase: + if request[0].isupper(): return (request,) + args else: # If self.defaultTransitions is not None, it is a map of @@ -381,7 +380,7 @@ class FSM(DirectObject): # to request a direct state transition (capital letter # request) not listed in defaultTransitions and not # handled by an earlier filter. - if request[0] in string.uppercase: + if request[0].isupper(): raise RequestDenied, "%s (from state: %s)" % (request, self.state) # In either case, we quietly ignore unhandled command @@ -392,7 +391,7 @@ class FSM(DirectObject): def filterOff(self, request, args): """From the off state, we can always go directly to any other state.""" - if request[0] in string.uppercase: + if request[0].isupper(): return (request,) + args return self.defaultFilter(request, args) diff --git a/direct/src/fsm/FourState.py b/direct/src/fsm/FourState.py index 6f42046cef..e29e494ff9 100755 --- a/direct/src/fsm/FourState.py +++ b/direct/src/fsm/FourState.py @@ -91,6 +91,7 @@ class FourState: off (and so is state 2 which is oposite of 4 and therefore oposite of 'on'). """ + self.stateIndex = 0 assert self.debugPrint("FourState(names=%s)"%(names)) self.track = None self.stateTime = 0.0 @@ -121,7 +122,6 @@ class FourState: self.exitState4, [names[1]]), } - self.stateIndex = 0 self.fsm = ClassicFSM.ClassicFSM('FourState', self.states.values(), # Initial State diff --git a/direct/src/fsm/FourStateAI.py b/direct/src/fsm/FourStateAI.py index d81d2bcf47..1c491aaecf 100755 --- a/direct/src/fsm/FourStateAI.py +++ b/direct/src/fsm/FourStateAI.py @@ -93,11 +93,11 @@ class FourStateAI: off (and so is state 2 which is oposite of state 4 and therefore oposite of 'on'). """ + self.stateIndex = 0 assert self.debugPrint( "FourStateAI(names=%s, durations=%s)" %(names, durations)) self.doLaterTask = None - self.stateIndex = 0 assert len(names) == 5 assert len(names) == len(durations) self.names = names diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 3d9d66292d..2d8c8241e7 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -14,7 +14,7 @@ from direct.task import Task from direct.showbase import ShowBase from direct.showbase.PythonUtil import recordCreationStackStr from pandac.PandaModules import PStatCollector -import string, types +import types guiObjectCollector = PStatCollector("Client::GuiObjects") @@ -192,9 +192,9 @@ class DirectGuiBase(DirectObject.DirectObject): # optimisations: optionInfo = self._optionInfo - optionInfo_has_key = optionInfo.has_key + optionInfo_has_key = optionInfo.__contains__ keywords = self._constructorKeywords - keywords_has_key = keywords.has_key + keywords_has_key = keywords.__contains__ FUNCTION = DGG._OPT_FUNCTION for name, default, function in optionDefs: @@ -251,7 +251,7 @@ class DirectGuiBase(DirectObject.DirectObject): # This keyword argument has not been used. If it # does not refer to a dynamic group, mark it as # unused. - index = string.find(name, '_') + index = name.find('_') if index < 0 or name[:index] not in self._dynamicGroups: unusedOptions.append(name) self._constructorKeywords = {} @@ -260,7 +260,7 @@ class DirectGuiBase(DirectObject.DirectObject): text = 'Unknown option "' else: text = 'Unknown options "' - raise KeyError, text + string.join(unusedOptions, ', ') + \ + raise KeyError, text + ', '.join(unusedOptions) + \ '" for ' + myClass.__name__ # Can now call post init func self.postInitialiseFunc() @@ -326,11 +326,11 @@ class DirectGuiBase(DirectObject.DirectObject): # optimizations: optionInfo = self._optionInfo - optionInfo_has_key = optionInfo.has_key + optionInfo_has_key = optionInfo.__contains__ componentInfo = self.__componentInfo - componentInfo_has_key = componentInfo.has_key + componentInfo_has_key = componentInfo.__contains__ componentAliases = self.__componentAliases - componentAliases_has_key = componentAliases.has_key + componentAliases_has_key = componentAliases.__contains__ VALUE = DGG._OPT_VALUE FUNCTION = DGG._OPT_FUNCTION @@ -345,7 +345,7 @@ class DirectGuiBase(DirectObject.DirectObject): # component and whose values are a dictionary of options and # values for the component. indirectOptions = {} - indirectOptions_has_key = indirectOptions.has_key + indirectOptions_has_key = indirectOptions.__contains__ for option, value in kw.items(): if optionInfo_has_key(option): @@ -361,7 +361,7 @@ class DirectGuiBase(DirectObject.DirectObject): optionInfo[option][VALUE] = value directOptions.append(option) else: - index = string.find(option, '_') + index = option.find('_') if index >= 0: # This option may be of the form _