Bläddra i källkod

integrate latest changes from CMU

David Rose 21 år sedan
förälder
incheckning
ee66668ab1
76 ändrade filer med 1592 tillägg och 617 borttagningar
  1. 12 4
      direct/src/actor/DistributedActor.py
  2. 76 1
      direct/src/dcparser/dcClass.cxx
  3. 2 0
      direct/src/dcparser/dcClass.h
  4. 2 0
      direct/src/dcparser/dcmsgtypes.h
  5. 159 5
      direct/src/distributed/ClientRepository.py
  6. 19 16
      direct/src/distributed/DistributedObject.py
  7. 9 0
      direct/src/distributed/MsgTypes.py
  8. 23 0
      direct/src/distributed/SampleObject.py
  9. 417 0
      direct/src/distributed/ServerRepository.py
  10. 0 2
      direct/src/distributed/cConnectionRepository.cxx
  11. 1 1
      direct/src/ffi/DoGenPyCode.py
  12. 3 0
      direct/src/interval/SoundInterval.py
  13. 86 53
      direct/src/showbase/ShowBase.py
  14. 1 0
      direct/src/showbase/pandaSqueezer.py
  15. 10 6
      doc/Config.prc
  16. 2 2
      doc/SceneEditor/AlignTool.py
  17. 4 4
      doc/SceneEditor/MetadataPanel.py
  18. 8 8
      doc/SceneEditor/SeSession.py
  19. 5 5
      doc/SceneEditor/SideWindow.py
  20. 5 5
      doc/SceneEditor/collisionWindow.py
  21. 4 4
      doc/SceneEditor/controllerWindow.py
  22. 11 11
      doc/SceneEditor/dataHolder.py
  23. 2 2
      doc/SceneEditor/duplicateWindow.py
  24. 5 5
      doc/SceneEditor/lightingPanel.py
  25. 7 7
      doc/SceneEditor/propertyWindow.py
  26. 31 31
      doc/SceneEditor/quad.py
  27. 3 3
      doc/SceneEditor/seAnimPanel.py
  28. 3 3
      doc/SceneEditor/seBlendAnimPanel.py
  29. 6 6
      doc/SceneEditor/seCameraControl.py
  30. 5 5
      doc/SceneEditor/seColorEntry.py
  31. 66 67
      doc/SceneEditor/seFileSaver.py
  32. 5 5
      doc/SceneEditor/seForceGroup.py
  33. 4 4
      doc/SceneEditor/seGeometry.py
  34. 2 2
      doc/SceneEditor/seGrid.py
  35. 8 8
      doc/SceneEditor/seLights.py
  36. 7 7
      doc/SceneEditor/seManipulation.py
  37. 13 12
      doc/SceneEditor/seMopathRecorder.py
  38. 2 2
      doc/SceneEditor/seParticleEffect.py
  39. 9 9
      doc/SceneEditor/seParticlePanel.py
  40. 25 25
      doc/SceneEditor/seParticles.py
  41. 6 6
      doc/SceneEditor/sePlacer.py
  42. 2 2
      doc/SceneEditor/seSceneGraphExplorer.py
  43. 12 9
      doc/SceneEditor/seSelection.py
  44. 2 2
      doc/SceneEditor/seTree.py
  45. 8 8
      dtool/Config.pp
  46. 18 0
      dtool/pptempl/Global.nmake.pp
  47. 2 0
      dtool/pptempl/Template.nmake.pp
  48. 1 3
      dtool/src/parser-inc/Sources.pp
  49. 14 0
      panda/metalibs/panda/Sources.pp
  50. 5 4
      panda/src/audio/audioManager.h
  51. 1 0
      panda/src/audio/audioSound.h
  52. 3 0
      panda/src/audio/nullAudioManager.cxx
  53. 1 0
      panda/src/audio/nullAudioManager.h
  54. 9 2
      panda/src/audiotraits/fmodAudioManager.cxx
  55. 3 2
      panda/src/audiotraits/fmodAudioSound.cxx
  56. 5 0
      panda/src/audiotraits/fmodAudioSound.h
  57. 1 1
      panda/src/dxgsg9/dxgsg9base.h
  58. 1 0
      panda/src/glstuff/Sources.pp
  59. 5 4
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  60. 6 1
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  61. 138 138
      panda/src/helix/HelixClient.cxx
  62. 1 1
      panda/src/helix/HelixClient.h
  63. 2 2
      panda/src/helix/HxAdviseSink.cxx
  64. 1 1
      panda/src/helix/HxAuthenticationManager.cxx
  65. 11 11
      panda/src/helix/HxErrorSink.cxx
  66. 2 2
      panda/src/helix/HxErrorSink.h
  67. 1 1
      panda/src/helix/HxSiteSupplier.cxx
  68. 36 36
      panda/src/helix/fivemmap.cxx
  69. 10 10
      panda/src/helix/fivemmap.h
  70. 0 16
      panda/src/helix/main.cpp
  71. 2 0
      panda/src/testbed/Sources.pp
  72. 213 23
      panda/src/windisplay/winGraphicsWindow.cxx
  73. 4 1
      panda/src/windisplay/winGraphicsWindow.h
  74. 2 0
      pandatool/src/bam/Sources.pp
  75. 1 0
      pandatool/src/dxfprogs/Sources.pp
  76. 1 1
      pandatool/src/mayaprogs/mayaSavePview.h

+ 12 - 4
direct/src/actor/DistributedActor.py

@@ -1,33 +1,41 @@
 """DistributedActor module: contains the DistributedActor class"""
 
 from direct.distributed import DistributedNode
+
 import Actor
 
 class DistributedActor(DistributedNode.DistributedNode, Actor.Actor):
     """Distributed Actor class:"""
 
+# Constructor for DistributedActor
+
     def __init__(self, cr):
         try:
             self.DistributedActor_initialized
         except:
-            self.DistributedActor_initialized = 1
+            self.DistributedActor_initialized = 1   
+            Actor.Actor.__init__(self)     
             DistributedNode.DistributedNode.__init__(self, cr)
-
             # Since actors are probably fairly heavyweight, we'd
-            # rather cache them than delete them if possible.
+            # rather cache them than delete them if possible.       
             self.setCacheable(1)
 
+# Disable the DistributedActor
+
     def disable(self):
         # remove all anims, on all parts and all lods
         if (not self.isEmpty()):
             Actor.Actor.unloadAnims(self, None, None, None)
         DistributedNode.DistributedNode.disable(self)
 
+# Delete the DistributedActor
+
     def delete(self):
         try:
             self.DistributedActor_deleted
         except:
-            self.DistributedActor_deleted = 1
+            self.DistributedActor_deleted = 1       
             DistributedNode.DistributedNode.delete(self)
             Actor.Actor.delete(self)
 
+

+ 76 - 1
direct/src/dcparser/dcClass.cxx

@@ -694,7 +694,7 @@ client_format_update(const string &field_name, int do_id,
 
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
-//     Function: DCClass::al_format_update
+//     Function: DCClass::ai_format_update
 //       Access: Published
 //  Description: Generates a datagram containing the message necessary
 //               to send an update for the indicated distributed
@@ -716,6 +716,81 @@ ai_format_update(const string &field_name, int do_id,
 }
 #endif  // HAVE_PYTHON
 
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::client_format_generate
+//       Access: Published
+//  Description: Generates a datagram containing the message necessary
+//               to generate a new distributed object from the client.
+//               This requires querying the object for the initial
+//               value of its required fields.
+//
+//               optional_fields is a list of fieldNames to generate
+//               in addition to the normal required fields.
+////////////////////////////////////////////////////////////////////
+Datagram DCClass::
+client_format_generate(PyObject *distobj, int do_id, 
+                   int zone_id, PyObject *optional_fields) const {
+  DCPacker packer;
+
+  //packer.raw_pack_uint8('A');
+
+  bool has_optional_fields = (PyObject_IsTrue(optional_fields) != 0);
+
+  if (has_optional_fields) {
+    packer.raw_pack_uint16(CLIENT_CREATE_OBJECT_REQUIRED_OTHER);
+  } else {
+    packer.raw_pack_uint16(CLIENT_CREATE_OBJECT_REQUIRED);
+  }
+
+  packer.raw_pack_uint32(zone_id);
+  packer.raw_pack_uint16(_number);
+  packer.raw_pack_uint32(do_id);
+
+  // Specify all of the required fields.
+  int num_fields = get_num_inherited_fields();
+  for (int i = 0; i < num_fields; i++) {
+    DCField *field = get_inherited_field(i);
+    if (field->is_required() && field->as_molecular_field() == NULL) {
+      packer.begin_pack(field);
+      if (!pack_required_field(packer, distobj, field)) {
+        return Datagram();
+      }
+      packer.end_pack();
+    }
+  }
+
+  // Also specify the optional fields.
+  if (has_optional_fields) {
+    int num_optional_fields = PySequence_Size(optional_fields);
+    packer.raw_pack_uint16(num_optional_fields);
+
+    for (int i = 0; i < num_optional_fields; i++) {
+      PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
+      string field_name = PyString_AsString(py_field_name);
+      Py_XDECREF(py_field_name);
+
+      DCField *field = get_field_by_name(field_name);
+      if (field == (DCField *)NULL) {
+        ostringstream strm;
+        strm << "No field named " << field_name << " in class " << get_name()
+             << "\n";
+        nassert_raise(strm.str());
+        return Datagram();
+      }
+      packer.raw_pack_uint16(field->get_number());
+      packer.begin_pack(field);
+      if (!pack_required_field(packer, distobj, field)) {
+        return Datagram();
+      }
+      packer.end_pack();
+    }
+  }
+
+  return Datagram(packer.get_data(), packer.get_length());
+}
+#endif  // HAVE_PYTHON
+
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::ai_format_generate

+ 2 - 0
direct/src/dcparser/dcClass.h

@@ -97,6 +97,8 @@ PUBLISHED:
   Datagram ai_format_generate(PyObject *distobj, int do_id, int parent_id, int zone_id,
                               CHANNEL_TYPE district_channel_id, CHANNEL_TYPE from_channel_id,
                               PyObject *optional_fields) const;
+  Datagram client_format_generate(PyObject *distobj, int do_id, int zone_id,                              
+                                  PyObject *optional_fields) const;
 #endif 
 
 public:

+ 2 - 0
direct/src/dcparser/dcmsgtypes.h

@@ -24,6 +24,8 @@
 // AIMsgTypes.py.
 
 #define CLIENT_OBJECT_UPDATE_FIELD                        24
+#define CLIENT_CREATE_OBJECT_REQUIRED                     34
+#define CLIENT_CREATE_OBJECT_REQUIRED_OTHER               35
 
 #define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED         2001
 #define STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER   2003

+ 159 - 5
direct/src/distributed/ClientRepository.py

@@ -15,6 +15,13 @@ from PyDatagram import PyDatagram
 from PyDatagramIterator import PyDatagramIterator
 
 class ClientRepository(ConnectionRepository.ConnectionRepository):
+
+    """ This maintains a client-side connection with a Panda server.
+    It currently supports several different versions of the server:
+    within the VR Studio, we are currently in transition from the
+    Toontown server to the OTP server; people outside the VR studio
+    will use the Panda LAN server provided by CMU."""
+    
     notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository")
 
     def __init__(self):
@@ -52,12 +59,26 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
         self.heartbeatInterval = base.config.GetDouble('heartbeat-interval', 10)
         self.heartbeatStarted = 0
         self.lastHeartbeat = 0
+        
         if wantOtpServer:
             # Top level Interest Manager
             self._interestIdAssign = 1
             self._interests = {}
-        
-    
+
+        # By default, the ClientRepository is set up to respond to
+        # datagrams from the CMU Panda LAN server.  You can
+        # reassign this member to change the response behavior
+        # according to game context.
+        self.handler = self.publicServerDatagramHandler
+
+        # The DOID allocator.  The CMU LAN server may choose to
+        # send us a block of DOIDs.  If it chooses to do so, then we
+        # may create objects, using those DOIDs.  These structures are
+        # only used in conjunction with the CMU LAN server.
+        self.DOIDbase = 0
+        self.DOIDnext = 0
+        self.DOIDlast = 0
+
     def abruptCleanup(self):
         """
         Call this method to clean up any pending hooks or tasks on
@@ -509,7 +530,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
         doId = di.getUint32()
         #print("Updating " + str(doId))
         # Find the DO
-            
+        
         do = self.doId2do.get(doId)
         if (do != None):
             # Let the dclass finish the job
@@ -544,6 +565,31 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
         self.notify.info('Message from server: %s' % (message))
         return message
 
+    def handleSetDOIDrange(self, di):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+        
+        self.DOIDbase = di.getUint32()
+        self.DOIDlast = self.DOIDbase + di.getUint32()
+        self.DOIDnext = self.DOIDbase
+        return None
+
+    def handleRequestGenerates(self, di):
+        # When new clients join the zone of an object, they need to hear
+        # about it, so we send out all of our information about objects in
+        # that particular zone.
+
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+        
+        assert(self.DOIDnext < self.DOIDlast);
+        zone = di.getUint32()
+        for obj in self.doId2do.values():
+            if obj.zone == zone:
+                id = obj.doId
+                if (self.isLocalId(id)):
+                    self.send(obj.dclass.clientFormatGenerate(obj, id, zone, []))
+
     def handleUnexpectedMsgType(self, msgType, di):        
         if msgType == CLIENT_CREATE_OBJECT_REQUIRED:
             self.handleGenerateWithRequired(di)
@@ -588,6 +634,69 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
                 " game state: " +
                 currentGameStateName)
 
+
+    def createWithRequired(self, className, zoneId = 0, optionalFields=None):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+
+        if (self.DOIDnext >= self.DOIDlast):
+            self.notify.error("Cannot allocate a distributed object ID: all IDs used up.")
+            return None
+        id = self.DOIDnext
+        self.DOIDnext = self.DOIDnext + 1
+        dclass = self.dclassesByName[className]
+        classDef = dclass.getClassDef()
+        if classDef == None:
+            self.notify.error("Could not create an undefined %s object." % (dclass.getName()))
+        obj = classDef(self)
+        obj.dclass = dclass
+        obj.zone = zoneId
+        obj.doId = id
+        self.doId2do[id] = obj
+        obj.generateInit()
+        obj.generate()
+        obj.announceGenerate()
+        datagram = dclass.clientFormatGenerate(obj, id, zoneId, optionalFields)
+        self.send(datagram)
+        return obj
+
+    def sendDisableMsg(self, doId):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+
+        datagram = PyDatagram()
+        datagram.addUint16(CLIENT_OBJECT_DISABLE)
+        datagram.addUint32(doId)
+        self.send(datagram)
+
+    def sendDeleteMsg(self, doId):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+
+        datagram = PyDatagram()
+        datagram.addUint16(CLIENT_OBJECT_DELETE)
+        datagram.addUint32(doId)
+        self.send(datagram)
+
+    def sendRemoveZoneMsg(self, zoneId, visibleZoneList=None):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+
+        datagram = PyDatagram()
+        datagram.addUint16(CLIENT_REMOVE_ZONE)
+        datagram.addUint32(zoneId)
+
+        # if we have an explicit list of visible zones, add them
+        if visibleZoneList is not None:
+            vzl = list(visibleZoneList)
+            vzl.sort()
+            assert PythonUtil.uniqueElements(vzl)
+            for zone in vzl:
+                datagram.addUint32(zone)
+
+        # send the message
+        self.send(datagram)
+
     def sendSetShardMsg(self, shardId):
         datagram = PyDatagram()
         # Add message type
@@ -656,6 +765,29 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
         # If we're processing a lot of datagrams within one frame, we
         # may forget to send heartbeats.  Keep them coming!
         self.considerHeartbeat()
+
+    def publicServerDatagramHandler(self, msgType, di):
+
+        # These are the sort of messages we may expect from the public
+        # Panda server.
+        
+        if msgType == CLIENT_SET_DOID_RANGE:
+            self.handleSetDOIDrange(di)
+        elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_RESP:
+            self.handleGenerateWithRequired(di)
+        elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_OTHER_RESP:
+            self.handleGenerateWithRequiredOther(di)
+        elif msgType == CLIENT_OBJECT_UPDATE_FIELD_RESP:
+            self.handleUpdateField(di)
+        elif msgType == CLIENT_OBJECT_DELETE_RESP:
+            self.handleDelete(di)
+        elif msgType == CLIENT_OBJECT_DISABLE_RESP:
+            self.handleDisable(di)
+        elif msgType == CLIENT_REQUEST_GENERATES:
+            self.handleRequestGenerates(di)
+        else:
+            self.handleUnexpectedMsgType(msgType, di)
+
     
     if wantOtpServer:
         # interest managment 
@@ -756,7 +888,6 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
             self.send(datagram)
 
 
-
     def sendHeartbeat(self):
         datagram = PyDatagram()
         # Add message type
@@ -799,11 +930,21 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
     def waitForNextHeartBeat(self):
         taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
                               "heartBeat")        
-        
+
     def sendUpdate(self, do, fieldName, args, sendToId = None):
         dg = do.dclass.clientFormatUpdate(fieldName, sendToId or do.doId, args)
         self.send(dg)
 
+    def sendUpdateZone(self, obj, zoneId):
+        # This method is only used in conjunction with the CMU LAN
+        # server.
+        
+        id = obj.doId
+        assert(self.isLocalId(id))
+        self.sendDeleteMsg(id, 1)
+        obj.zone = zoneId
+        self.send(obj.dclass.clientFormatGenerate(obj, id, zoneId, []))
+
     def replaceMethod(self, oldMethod, newFunction):
         return 0
 
@@ -815,3 +956,16 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
             if isinstance(obj, type):
                 result.append(obj)
         return result
+
+    def findAnyOfType(self, type):
+        # Searches the repository for any object of the given type.
+        for obj in self.doId2do.values():
+            if isinstance(obj, type):
+                return obj
+        return None
+
+    def isLocalId(self,id):
+        return ((id >= self.DOIDbase) and (id < self.DOIDlast))
+
+    def haveCreateAuthority(self):
+        return (self.DOIDlast > self.DOIDnext)

+ 19 - 16
direct/src/distributed/DistributedObject.py

@@ -62,12 +62,8 @@ class DistributedObject(PandaObject):
             # This is used by doneBarrier().
             self.__barrierContext = None
 
-    #def __del__(self):
-    #    """
-    #    For debugging purposes, this just prints out what got deleted
-    #    """
-    #    print ("Destructing: " + self.__class__.__name__ + " id: " + str(self.doId))
-    #    PandaObject.__del__(self)
+            #zone of the distributed object, default to 0
+            self.zone = 0
 
     def setNeverDisable(self, bool):
         assert((bool == 1) or (bool == 0))
@@ -228,21 +224,18 @@ class DistributedObject(PandaObject):
         if self.cr:
             self.cr.sendUpdate(self, fieldName, args, sendToId)
 
+    def sendDisableMsg(self):
+        self.cr.sendDisableMsg(self.doId)
+
+    def sendDeleteMsg(self):
+        self.cr.sendDeleteMsg(self.doId)
+
     def taskName(self, taskString):
         return (taskString + "-" + str(self.getDoId()))
     
     def uniqueName(self, idString):
         return (idString + "-" + str(self.getDoId()))
 
-    def isLocal(self):
-        # This returns true if the distributed object is "local,"
-        # which means the client created it instead of the AI, and it
-        # gets some other special handling.  Normally, only the local
-        # avatar class overrides this to return true.
-        return 0
-    
-
-
     def getCallbackContext(self, callback, extraArgs = []):
         # Some objects implement a back-and-forth handshake operation
         # with the AI via an arbitrary context number.  This method
@@ -334,7 +327,7 @@ class DistributedObject(PandaObject):
         if self.__barrierContext != None:
             self.sendUpdate("setBarrierReady", [self.__barrierContext])
             self.__barrierContext = None
-
+    
     if wantOtpServer:
         def addInterest(self, zoneId, note=""):
             self.cr.addInterest(self.getDoId(), zoneId, note)
@@ -347,3 +340,13 @@ class DistributedObject(PandaObject):
         def getLocation(self):
             return self.__location
 
+    def isLocal(self):
+        # This returns true if the distributed object is "local,"
+        # which means the client created it instead of the AI, and it
+        # gets some other special handling.  Normally, only the local
+        # avatar class overrides this to return true.
+        return (self.cr.isLocalId(self.doId))
+
+    def updateZone(self, zoneId):
+        self.cr.sendUpdateZone(self, zoneId)
+

+ 9 - 0
direct/src/distributed/MsgTypes.py

@@ -23,13 +23,20 @@ CLIENT_LOGIN_2_RESP =                        17
 
 CLIENT_OBJECT_UPDATE_FIELD =                 24
 CLIENT_OBJECT_UPDATE_FIELD_RESP =            24
+CLIENT_OBJECT_DISABLE =                      25
 CLIENT_OBJECT_DISABLE_RESP =                 25
+CLIENT_OBJECT_DELETE =                       27
 CLIENT_OBJECT_DELETE_RESP =                  27
 CLIENT_SET_ZONE =                            29
+CLIENT_REMOVE_ZONE =                         30
 CLIENT_SET_SHARD =                           31
 CLIENT_SET_AVATAR =                          32
 CLIENT_CREATE_OBJECT_REQUIRED =              34
+CLIENT_CREATE_OBJECT_REQUIRED_RESP =         34
 CLIENT_CREATE_OBJECT_REQUIRED_OTHER =        35
+CLIENT_CREATE_OBJECT_REQUIRED_OTHER_RESP =   35
+
+CLIENT_REQUEST_GENERATES =                   36
 
 CLIENT_DISCONNECT =                          37
 
@@ -61,6 +68,8 @@ CLIENT_SET_WISHNAME_RESP =                   71
 CLIENT_SET_WISHNAME_CLEAR =                  72
 CLIENT_SET_SECURITY =                        73
 
+CLIENT_SET_DOID_RANGE =                      74
+
 CLIENT_GET_AVATARS_RESP2 =                   75
 CLIENT_CREATE_AVATAR2 =                      76
 CLIENT_SYSTEM_MESSAGE =                      78

+ 23 - 0
direct/src/distributed/SampleObject.py

@@ -0,0 +1,23 @@
+"""SampleObject module: contains the SampleObject class"""
+
+from direct.directnotify.DirectNotifyGlobal import *
+from direct.distributed.DistributedObject import *
+
+class SampleObject(DistributedObject):
+
+    notify = directNotify.newCategory("SampleObject")
+
+    def __init__(self, cr):
+        self.cr = cr
+#        self.red = 0
+#        self.green = 0
+#        self.blue = 0
+
+    def setColor(self, red = 0, green = 0, blue = 0):
+        self.red = red                 
+        self.green = green
+        self.blue = blue
+        self.announceGenerate()
+
+    def getColor(self):
+        return (self.red, self.green, self.blue)

+ 417 - 0
direct/src/distributed/ServerRepository.py

@@ -0,0 +1,417 @@
+"""ServerRepository module: contains the ServerRepository class"""
+
+from pandac.PandaModules import *
+#from TaskManagerGlobal import *
+from direct.distributed.MsgTypes import *
+from direct.task import Task
+from direct.directnotify import DirectNotifyGlobal
+#from NetDatagram import NetDatagram
+#from Datagram import Datagram
+#from Datagram import *
+from pandac import Datagram
+from pandac import DatagramIterator
+from direct.distributed.PyDatagram import PyDatagram
+from direct.distributed.PyDatagramIterator import PyDatagramIterator
+#from PointerToConnection import PointerToConnection
+import time
+
+class ServerRepository:
+
+    """ This maintains the server-side connection with a Panda server.
+    It is only for use with the Panda LAN server provided by CMU."""
+
+    notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository")
+
+    def __init__(self, tcpPort, udpPort):
+        self.qcm = QueuedConnectionManager()
+        self.qcl = QueuedConnectionListener(self.qcm, 0)
+        self.qcr = QueuedConnectionReader(self.qcm, 0)
+        self.cw = ConnectionWriter(self.qcm,0)
+        self.tcpRendezvous = self.qcm.openTCPServerRendezvous(tcpPort, 10)
+        print self.tcpRendezvous
+        self.qcl.addConnection(self.tcpRendezvous)
+        taskMgr.add(self.listenerPoll, "serverListenerPollTask")
+        taskMgr.add(self.readerPollUntilEmpty, "serverReaderPollTask")
+	taskMgr.add(self.clientHardDisconnectTask, "clientHardDisconnect")
+	self.ClientIP = {}
+	self.ClientZones = {}
+	self.ClientDOIDbase = {}
+	self.ClientObjects = {}
+	self.DOIDnext = 1
+	self.DOIDrange = 1000000
+	self.DOIDtoClients = {}
+	self.DOIDtoZones = {}
+	self.DOIDtoDClass = {}
+	self.ZonesToClients = {}
+	self.ZonetoDOIDs = {}
+	self.RemovedDOIDs = []
+	self.dcFile = DCFile()
+	self.dcSuffix = ''
+	self.readDCFile()
+
+    def importModule(self, dcImports, moduleName, importSymbols):
+        """ Imports the indicated moduleName and all of its symbols
+        into the current namespace.  This more-or-less reimplements
+        the Python import command. """
+
+        module = __import__(moduleName, globals(), locals(), importSymbols)
+
+        if importSymbols:
+            # "from moduleName import symbolName, symbolName, ..."
+            # Copy just the named symbols into the dictionary.
+            if importSymbols == ['*']:
+                # "from moduleName import *"
+                if hasattr(module, "__all__"):
+                    importSymbols = module.__all__
+                else:
+                    importSymbols = module.__dict__.keys()
+            
+            for symbolName in importSymbols:
+                if hasattr(module, symbolName):
+                    dcImports[symbolName] = getattr(module, symbolName)
+
+                else:
+                    raise StandardError, 'Symbol %s not defined in module %s.' % (symbolName, moduleName)
+
+        else:
+            # "import moduleName"
+
+            # Copy the root module name into the dictionary.
+
+            # Follow the dotted chain down to the actual module.
+            components = moduleName.split('.')
+            dcImports[components[0]] = module
+
+    def readDCFile(self, dcFileNames = None):
+        """
+        Reads in the dc files listed in dcFileNames, or if
+        dcFileNames is None, reads in all of the dc files listed in
+        the Configrc file.
+        """
+        dcFile = self.dcFile
+        dcFile.clear()
+        self.dclassesByName = {}
+        self.dclassesByNumber = {}
+        self.hashVal = 0
+        
+        dcImports = {}
+        if dcFileNames == None:
+            readResult = dcFile.readAll()
+            if not readResult:
+                self.notify.error("Could not read dc file.")
+        else:
+            for dcFileName in dcFileNames:
+                readResult = dcFile.read(Filename(dcFileName))
+                if not readResult:
+                    self.notify.error("Could not read dc file: %s" % (dcFileName))
+
+        self.hashVal = dcFile.getHash()
+
+        # Now import all of the modules required by the DC file.
+        for n in range(dcFile.getNumImportModules()):
+            moduleName = dcFile.getImportModule(n)
+
+            # Maybe the module name is represented as "moduleName/AI".
+            suffix = moduleName.split('/')
+            moduleName = suffix[0]
+            if self.dcSuffix and self.dcSuffix in suffix[1:]:
+                moduleName += self.dcSuffix
+
+            importSymbols = []
+            for i in range(dcFile.getNumImportSymbols(n)):
+                symbolName = dcFile.getImportSymbol(n, i)
+
+                # Maybe the symbol name is represented as "symbolName/AI".
+                suffix = symbolName.split('/')
+                symbolName = suffix[0]
+                if self.dcSuffix and self.dcSuffix in suffix[1:]:
+                    symbolName += self.dcSuffix
+
+                importSymbols.append(symbolName)
+                
+            self.importModule(dcImports, moduleName, importSymbols)
+
+        # Now get the class definition for the classes named in the DC
+        # file.
+        for i in range(dcFile.getNumClasses()):
+            dclass = dcFile.getClass(i)
+            number = dclass.getNumber()
+            className = dclass.getName() + self.dcSuffix
+
+            # Does the class have a definition defined in the newly
+            # imported namespace?
+            classDef = dcImports.get(className)
+            if classDef == None:
+                self.notify.info("No class definition for %s." % (className))
+            else:
+                if type(classDef) == types.ModuleType:
+                    if not hasattr(classDef, className):
+                        self.notify.error("Module %s does not define class %s." % (className, className))
+                    classDef = getattr(classDef, className)
+                    
+                if type(classDef) != types.ClassType:
+                    self.notify.error("Symbol %s is not a class name." % (className))
+                else:
+                    dclass.setClassDef(classDef)
+
+            self.dclassesByName[className] = dclass
+            if number >= 0:
+                self.dclassesByNumber[number] = dclass
+
+
+# listens for new clients
+
+    def listenerPoll(self, task):
+        if self.qcl.newConnectionAvailable():
+            rendezvous = PointerToConnection()
+            netAddress = NetAddress()
+            newConnection = PointerToConnection()
+            retVal = self.qcl.getNewConnection(rendezvous, netAddress,
+                                               newConnection)
+            if retVal:
+                # Crazy dereferencing
+                newConnection=newConnection.p()
+                self.qcr.addConnection(newConnection)
+		#  Add clients infomation to dictionary
+		self.ClientIP[newConnection] = netAddress.getIpString()
+		self.ClientZones[newConnection] = []
+		self.ClientObjects[newConnection] = []
+                self.lastConnection = newConnection
+		self.sendDOIDrange(self.lastConnection)
+            else:
+                self.notify.warning(
+                    "getNewConnection returned false")
+        return Task.cont
+
+# continuously polls for new messages on the server
+
+    def readerPollUntilEmpty(self, task):
+        while self.readerPollOnce():
+	    pass
+        return Task.cont
+
+# checks for available messages to the server
+
+    def readerPollOnce(self):
+        availGetVal = self.qcr.dataAvailable()
+        if availGetVal:
+            datagram = NetDatagram() 
+            readRetVal = self.qcr.getData(datagram) 
+            if readRetVal:
+		# need to send to message processing unit
+                self.handleDatagram(datagram)
+            else:
+                self.notify.warning("getData returned false")
+        return availGetVal
+
+# switching station for messages
+
+    def handleDatagram(self, datagram):
+	dgi = DatagramIterator.DatagramIterator(datagram)
+	type = dgi.getUint16()
+
+	if type == CLIENT_DISCONNECT:
+		self.handleClientDisconnect(datagram.getConnection())
+	elif type == CLIENT_SET_ZONE:
+		self.handleSetZone(dgi, datagram.getConnection())
+	elif type == CLIENT_REMOVE_ZONE:
+		self.handleRemoveZone(dgi, datagram.getConnection())
+	elif type == CLIENT_CREATE_OBJECT_REQUIRED:
+		self.handleClientCreateObjectRequired(datagram, dgi)
+	elif type == CLIENT_OBJECT_UPDATE_FIELD:
+		self.handleClientUpdateField(datagram, dgi)
+	elif type == CLIENT_OBJECT_DELETE:
+		self.handleClientDeleteObject(datagram, dgi.getUint32())
+	elif type == CLIENT_OBJECT_DISABLE:
+		self.handleClientDisable(datagram, dgi.getUint32())
+	else:
+                self.notify.error("unrecognized message")
+
+# client wants to create an object, so we store appropriate data,
+# and then pass message along to corresponding zones
+
+    def handleClientCreateObjectRequired(self, datagram, dgi):
+	connection = datagram.getConnection()
+        # no need to create a new message, just forward the received
+	# message as it has the same msg type number
+	zone    = dgi.getUint32()
+	classid = dgi.getUint16()
+	doid    = dgi.getUint32()
+	rest    = dgi.getRemainingBytes()
+	datagram = NetDatagram()
+	datagram.addUint16(CLIENT_CREATE_OBJECT_REQUIRED)
+	datagram.addUint16(classid)
+	datagram.addUint32(doid)
+	datagram.appendData(rest)
+	dclass = self.dclassesByNumber[classid]
+	if self.ClientObjects[connection].count(doid) == 0:
+		self.ClientObjects[connection].append(doid)
+	self.DOIDtoZones[doid] = zone
+	self.DOIDtoDClass[doid] = dclass
+	if zone in self.ZonetoDOIDs:
+		if self.ZonetoDOIDs[zone].count(doid)==0:
+			self.ZonetoDOIDs[zone].append(doid)
+	else:
+		self.ZonetoDOIDs[zone] = [doid]
+	self.sendToZoneExcept(zone, datagram, connection)
+	return None
+
+
+# client wants to update an object, forward message along 
+# to corresponding zone
+
+    def handleClientUpdateField(self, datagram, dgi):	
+	connection = datagram.getConnection()
+	doid = dgi.getUint32()
+	fieldid = dgi.getUint16()
+	dclass = self.DOIDtoDClass[doid]
+	dcfield = dclass.getField(fieldid)
+        if (dcfield.isBroadcast()):
+	  if (dcfield.isP2p()):
+	    self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0)
+	  else:
+	    self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, connection)
+	elif (dcfield.isP2p()):
+	  self.cw.send(datagram, self.DOIDtoClients[doid])
+	else:
+          self.notify.warning(
+		"Message is not broadcast, p2p, or broadcast+p2p")
+	return None
+
+# client disables an object, let everyone know who is in
+# that zone know about it
+
+    def handleClientDisable(self, datagram, doid):
+	# now send disable message to all clients that need to know
+	if doid in self.DOIDtoZones:
+		self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0)
+	return None
+
+# client deletes an object, let everyone who is in zone with
+# object know about it
+
+    def handleClientDeleteObject(self, datagram, doid):
+	if doid in self.DOIDtoZones:	
+		self.sendToZoneExcept(self.DOIDtoZones[doid], datagram, 0)
+		self.ClientObjects[datagram.getConnection()].remove(doid)
+		self.ZonetoDOIDs[self.DOIDtoZones[doid]].remove(doid)
+		del self.DOIDtoZones[doid]
+		del self.DOIDtoDClass[doid]
+	return None
+
+    def sendAvatarGenerate(self):
+        datagram = PyDatagram()
+        # Message type is 1
+        datagram.addUint16(ALL_OBJECT_GENERATE_WITH_REQUIRED)
+        # Avatar class type is 2
+        datagram.addUint8(2)
+        # A sample id
+        datagram.addUint32(10)
+        # The only required field is the zone field
+        datagram.addUint32(999)
+        self.cw.send(datagram, self.lastConnection)
+
+#  sends the client the range of doid's that the client can use
+
+    def sendDOIDrange(self, connection):
+	# reuse DOID assignments if we can
+	if len(self.RemovedDOIDs) > 0:
+		id = self.RemovedDOIDs[0]
+		self.RemovedDOIDs.remove(id)
+	else:
+		id = self.DOIDnext + self.DOIDrange
+		self.DOIDnext = self.DOIDnext + self.DOIDrange
+	self.DOIDtoClients[id] = connection
+	self.ClientDOIDbase[connection] = id
+	datagram = NetDatagram()
+	datagram.addUint16(CLIENT_SET_DOID_RANGE)
+	datagram.addUint32(id)
+	datagram.addUint32(self.DOIDrange)
+	print "Sending DOID range: ",id,self.DOIDrange
+	self.cw.send(datagram, connection)	
+	return None
+
+    # a client disconnected from us, we need to update our data, also tell other clients to remove
+    # the disconnected clients objects
+    def handleClientDisconnect(self, connection):
+	if (self.ClientIP.has_key(connection)):
+		self.RemovedDOIDs.append(self.ClientDOIDbase[connection])
+		del self.DOIDtoClients[self.ClientDOIDbase[connection]]
+		for zone in self.ClientZones[connection]:
+			if len(self.ZonesToClients[zone]) == 1:
+				del self.ZonesToClients[zone]
+			else:
+				self.ZonesToClients[zone].remove(connection)
+		for obj in self.ClientObjects[connection]:
+			#create and send delete message
+			datagram = NetDatagram()
+			datagram.addUint16(CLIENT_OBJECT_DELETE_RESP)
+			datagram.addUint32(obj)
+			self.sendToZoneExcept(self.DOIDtoZones[obj], datagram, 0)
+			self.ZonetoDOIDs[self.DOIDtoZones[obj]].remove(obj)
+			del self.DOIDtoZones[obj]
+			del self.DOIDtoDClass[obj]
+		del self.ClientIP[connection]
+		del self.ClientZones[connection]
+		del self.ClientDOIDbase[connection]
+		del self.ClientObjects[connection]
+	self.RemovedDOIDs.sort()
+	return None
+
+    #  client told us it's zone(s), store information
+    def handleSetZone(self, dgi, connection):
+	while dgi.getRemainingSize() > 0:
+		ZoneID = dgi.getUint32()
+		if self.ClientZones[connection].count(ZoneID) == 0:
+			self.ClientZones[connection].append(ZoneID)
+		if ZoneID in self.ZonesToClients:
+			if self.ZonesToClients[ZoneID].count(connection) == 0:
+				self.ZonesToClients[ZoneID].append(connection)
+		else:
+			self.ZonesToClients[ZoneID] = [connection]
+
+		# We have a new member, need to get all of the data from clients who may have objects in this zone
+		datagram = NetDatagram()
+		datagram.addUint16(CLIENT_REQUEST_GENERATES)
+		datagram.addUint32(ZoneID)
+		self.sendToAll(datagram)
+		print "SENDING REQUEST GENERATES (",ZoneID,") TO ALL"
+	return None
+
+    # client has moved zones, need to update them
+    def handleRemoveZone(self, dgi, connection):
+	while dgi.getRemainingSize() > 0:
+		ZoneID = dgi.getUint32()		
+		if self.ClientZones[connection].count(ZoneID) == 1:
+			self.ClientZones[connection].remove(ZoneID)
+		if ZoneID in self.ZonesToClients:
+			if self.ZonesToClients[ZoneID].count(connection) == 1:
+				self.ZonesToClients[ZoneID].remove(connection)	
+		for i in self.ZonetoDOIDs[ZoneID]:
+			datagram = NetDatagram()
+			datagram.addUint16(CLIENT_OBJECT_DELETE)
+			datagram.addUint32(i)
+			self.cw.send(datagram, connection)	
+	return None
+
+    # client did not tell us he was leaving but we lost connection to him, so we need to update our data and tell others
+
+    def clientHardDisconnectTask(self, task):
+	for i in self.ClientIP.keys():	
+		if (not self.qcr.isConnectionOk(i)):
+			self.handleClientDisconnect(i)
+	return Task.cont
+
+
+    # sends a message to everyone who is in the zone	
+    def sendToZoneExcept(self, ZoneID, datagram, connection):	
+	if ZoneID in self.ZonesToClients:
+		for conn in self.ZonesToClients[ZoneID]:
+			if (conn != connection): self.cw.send(datagram, conn)
+	return None	 
+
+    # sends a message to all connected clients
+    def sendToAll(self, datagram):
+	for client in self.ClientIP.keys():
+            self.cw.send(datagram, client)
+	return None

+ 0 - 2
direct/src/distributed/cConnectionRepository.cxx

@@ -135,7 +135,6 @@ check_datagram() {
   if (_simulated_disconnect) {
     return false;
   }
-
   while (do_check_datagram()) {
 #ifndef NDEBUG
     if (get_verbose()) {
@@ -164,7 +163,6 @@ check_datagram() {
     }
 
     _msg_type = _di.get_uint16();
-
     // Is this a message that we can process directly?
     switch (_msg_type) {
 #ifdef HAVE_PYTHON

+ 1 - 1
direct/src/ffi/DoGenPyCode.py

@@ -49,8 +49,8 @@ outputDir = ''
 extensionsDir = ''
 interrogateLib = ''
 codeLibs = []
-doSqueeze = 1
 etcPath = []
+doSqueeze = 1
 
 def doGetopts():
     global outputDir

+ 3 - 0
direct/src/interval/SoundInterval.py

@@ -41,10 +41,13 @@ class SoundInterval(Interval.Interval):
             duration = max(self.soundDuration - self.startTime, 0)
             #if (duration == 0):
             #    self.notify.warning('zero length duration!')
+            
             # MPG - hack for Miles bug
             #duration += 1.5
+            
             # DCR - hack for Miles bug - adding 1.5 seconds caused
             # problems for MG_neg_buzzer.wav
+            
             # DCR - what this is all about: Miles is under-reporting the
             # length of MP3 files, and they're getting cut off too early.
             # This is a temporary hack. We could:

+ 86 - 53
direct/src/showbase/ShowBase.py

@@ -76,6 +76,9 @@ class ShowBase(DirectObject.DirectObject):
         # magic-word override
         self.mwClientSleep = 0.
 
+        # using 'sleep' once per frame to limit CPU usage.
+        self.sleepCycle = 0.0
+        
         # Fill this in with a function to invoke when the user "exits"
         # the program by closing the main window.
         self.exitFunc = None
@@ -108,10 +111,12 @@ class ShowBase(DirectObject.DirectObject):
         self.mainWinMinimized = 0
         self.pipe = None
         self.pipeList = []
-        self.mak = None
         self.mouse2cam = None
-        self.mouseInterface = None
+        self.buttonThrowers = None
+        self.mouseWatcher = None
         self.mouseWatcherNode = None
+        self.pointerWatcherNodes = None
+        self.mouseInterface = None
         self.drive = None
         self.trackball = None
         self.cam = None
@@ -547,6 +552,22 @@ class ShowBase(DirectObject.DirectObject):
 
         return success
 
+    def setSleep(self, amount):
+        """
+        Sets up a task that calls python 'sleep' every frame.  This is a simple
+        way to reduce the CPU usage (and frame rate) of a panda program.
+        """
+        if (self.sleepCycle == amount): return()
+        if (time == 0.0):
+          self.taskMgr.remove('sleep-cycle')
+        else:
+          self.sleepCycle = amount
+          self.taskMgr.add(self.sleepCycleTask, 'sleep-cycle')
+
+    def sleepCycleTask(self, state):
+        time.sleep(self.sleepCycle)
+        return Task.cont
+
     def setFrameRateMeter(self, flag):
         """
         Turns on or off (according to flag) a standard frame rate
@@ -829,51 +850,71 @@ class ShowBase(DirectObject.DirectObject):
         """
         Creates the structures necessary to monitor the mouse input,
         using the indicated window.  If the mouse has already been set
-        up for a different window, this changes the mouse to reference
-        the new window.
+        up for a different window, those structures are deleted first.
         """
-        if self.mak != None:
-            # The mouse has already been set up; reappropriate it.
-            self.mak.node().setSource(win, 0)
-
-            # Reset the currently-held modifier button list for good
-            # measure.
-            bt = self.buttonThrower.node()
-            mb = ModifierButtons(bt.getModifierButtons())
-            mb.allButtonsUp()
-            bt.setModifierButtons(mb)
-            return
-
-        # The mouse has not yet been set up in this application;
-        # create the mouse structures now.
         
-        # We create both a MouseAndKeyboard object and a MouseWatcher object
-        # for the window.  The MouseAndKeyboard generates mouse events and
-        # mouse button/keyboard events; the MouseWatcher passes them through
+        if self.buttonThrowers != None:
+          for bt in self.buttonThrowers:
+            mw = bt.getParent()
+            mk = mw.getParent()
+            bt.remove()
+            mw.remove()
+            mk.remove()
+        
+        # For each mouse/keyboard device, we create
+        #  - MouseAndKeyboard
+        #  - MouseWatcher
+        #  - ButtonThrower
+        # The ButtonThrowers are stored in a list, self.buttonThrowers.
+        # Given a ButtonThrower, one can access the MouseWatcher and
+        # MouseAndKeyboard using getParent.  
+        #
+        # The MouseAndKeyboard generates mouse events and mouse
+        # button/keyboard events; the MouseWatcher passes them through
         # unchanged when the mouse is not over a 2-d button, and passes
         # nothing through when the mouse *is* over a 2-d button.  Therefore,
         # objects that don't want to get events when the mouse is over a
         # button, like the driveInterface, should be parented to
-        # mouseWatcher, while objects that want events in all cases, like the
-        # chat interface, should be parented to mak.
-        self.mak = self.dataRoot.attachNewNode(MouseAndKeyboard(win, 0, 'mak'))
-        self.mouseWatcherNode = MouseWatcher('mouseWatcher')
-        self.mouseWatcher = self.mak.attachNewNode(self.mouseWatcherNode)
+        # MouseWatcher, while objects that want events in all cases, like the
+        # chat interface, should be parented to the MouseAndKeyboard.
+
+        self.buttonThrowers = []
+        self.pointerWatcherNodes = []
+        for i in range(win.getNumInputDevices()):
+            name = win.getInputDeviceName(i)
+            mk = self.dataRoot.attachNewNode(MouseAndKeyboard(win, i, name))
+            mw = mk.attachNewNode(MouseWatcher(name))
+            mb = mw.node().getModifierButtons()
+            mb.addButton(KeyboardButton.shift())
+            mb.addButton(KeyboardButton.control())
+            mb.addButton(KeyboardButton.alt())
+            mw.node().setModifierButtons(mb)
+            bt = mw.attachNewNode(ButtonThrower(name))
+            if (i != 0):
+                bt.node().setPrefix('mousedev'+str(i)+'-')
+            mods = ModifierButtons()
+            mods.addButton(KeyboardButton.shift())
+            mods.addButton(KeyboardButton.control())
+            mods.addButton(KeyboardButton.alt())
+            bt.node().setModifierButtons(mods)
+            self.buttonThrowers.append(bt)
+            if (win.hasPointer(i)):
+                self.pointerWatcherNodes.append(mw.node())
+
+        self.mouseWatcher = self.buttonThrowers[0].getParent()
+        self.mouseWatcherNode = self.mouseWatcher.node()
+        # print "ButtonThrowers = ",self.buttonThrowers
+        # print "PointerWatcherNodes = ",self.pointerWatcherNodes
 
         if self.recorder:
             # If we have a recorder, the mouseWatcher belongs under a
             # special MouseRecorder node, which may intercept the
             # mouse activity.
+            mw = self.buttonThrowers[0].getParent()
             mouseRecorder = MouseRecorder('mouse')
             self.recorder.addRecorder('mouse', mouseRecorder.upcastToRecorderBase())
-            np = self.mak.attachNewNode(mouseRecorder)
-            self.mouseWatcher.reparentTo(np)
-        
-        mb = self.mouseWatcherNode.getModifierButtons()
-        mb.addButton(KeyboardButton.shift())
-        mb.addButton(KeyboardButton.control())
-        mb.addButton(KeyboardButton.alt())
-        self.mouseWatcherNode.setModifierButtons(mb)
+            np = mw.getParent().attachNewNode(mouseRecorder)
+            mw.reparentTo(np)
 
         # Now we have the main trackball & drive interfaces.
         # useTrackball() and useDrive() switch these in and out; only
@@ -890,31 +931,20 @@ class ShowBase(DirectObject.DirectObject):
         self.mouseInterface = self.trackball
         self.useTrackball()
 
-        # A ButtonThrower to generate events from the mouse and
-        # keyboard buttons as they are pressed.
-        self.buttonThrower = self.mouseWatcher.attachNewNode(ButtonThrower('buttons'))
-
-        # Specialize the events based on whether the modifier keys are
-        # being held down.
-        mods = ModifierButtons()
-        mods.addButton(KeyboardButton.shift())
-        mods.addButton(KeyboardButton.control())
-        mods.addButton(KeyboardButton.alt())
-        self.buttonThrower.node().setModifierButtons(mods)
-
         # A special ButtonThrower to generate keyboard events and
         # include the time from the OS.  This is separate only to
         # support legacy code that did not expect a time parameter; it
         # will eventually be folded into the normal ButtonThrower,
         # above.
-        self.timeButtonThrower = self.mouseWatcher.attachNewNode(ButtonThrower('timeButtons'))
+        mw = self.buttonThrowers[0].getParent()
+        self.timeButtonThrower = mw.attachNewNode(ButtonThrower('timeButtons'))
         self.timeButtonThrower.node().setPrefix('time-')
         self.timeButtonThrower.node().setTimeFlag(1)
 
         # Tell the gui system about our new mouse watcher.
-        self.aspect2d.node().setMouseWatcher(self.mouseWatcherNode)
-        self.aspect2dp.node().setMouseWatcher(self.mouseWatcherNode)
-        self.mouseWatcherNode.addRegion(PGMouseWatcherBackground())
+        self.aspect2d.node().setMouseWatcher(mw.node())
+        self.aspect2dp.node().setMouseWatcher(mw.node())
+        mw.node().addRegion(PGMouseWatcherBackground())
 
     def enableSoftwareMousePointer(self):
         """enableSoftwareMousePointer(self)
@@ -1211,7 +1241,7 @@ class ShowBase(DirectObject.DirectObject):
 
         return VBase4(win.getClearColor())
 
-    def setBackgroundColor(self, r = None, g = None, b = None, win = None):
+    def setBackgroundColor(self, r = None, g = None, b = None, a = 1.0, win = None):
         """
         Sets the window background color to the indicated value.
         This assumes the window is set up to clear the color each
@@ -1221,10 +1251,13 @@ class ShowBase(DirectObject.DirectObject):
         tuple, or the individual r, g, b parameters.
         """
         if g != None:
-            color = VBase4(r, g, b, 1.0)
+            color = VBase4(r, g, b, a)
         else:
             arg = r
-            color = VBase4(arg[0], arg[1], arg[2], 1.0)
+            if isinstance(arg, VBase4):
+                color = arg
+            else:
+                color = VBase4(arg[0], arg[1], arg[2], a)
 
         if win == None:
             win = self.win

+ 1 - 0
direct/src/showbase/pandaSqueezer.py

@@ -48,4 +48,5 @@ def squeezePandaFiles():
     for i in l:
         os.unlink(i)
 
+
 squeezePandaFiles()

+ 10 - 6
doc/Config.prc

@@ -4,8 +4,8 @@
 # Uncomment one of the following lines to choose whether you should
 # run using OpenGL or DirectX rendering.
 
-#load-display pandagl
-load-display pandadx8
+load-display pandagl
+#load-display pandadx8
 
 
 # These control the placement and size of the default rendering window.
@@ -18,6 +18,8 @@ win-height 600
 # in a window.
 #fullscreen #t
 
+# This will be used for sample programs with networking
+dc-file sample.dc
 
 # Windows ships with a software OpenGL driver; if you have not
 # installed an OpenGL driver for your graphics card you may be able to
@@ -41,8 +43,12 @@ gl-allow-software-renderer #t
 # the Panda convention of forward slashes (instead of backslash)
 # separating directory names.  (You may also use Windows-native paths
 # here if you prefer.)
-model-path  /i/alpha/player/install/tagmodels
-sound-path  /c/ttmodels
+model-path  .
+model-path  $PRC_DIR
+model-path  $PRC_DIR/..
+sound-path  .
+sound-path  $PRC_DIR
+sound-path  $PRC_DIR/..
 
 # This makes the egg loader available to load egg files.
 load-file-type pandaegg
@@ -53,11 +59,9 @@ load-file-type pandaegg
 # Lightwave) directly into Panda.
 # load-file-type ptloader
 
-
 # Turn off audio:
 audio-library-name null
 
-
 # This enable the automatic creation of a TK window when running
 # Direct.
 #want-directtools  #t

+ 2 - 2
doc/SceneEditor/AlignTool.py

@@ -2,8 +2,8 @@
 # AlignTool.py
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 
 
 class AlignTool(AppShell):

+ 4 - 4
doc/SceneEditor/MetadataPanel.py

@@ -1,5 +1,5 @@
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 
 
 class MetadataPanel(AppShell,Pmw.MegaWidget):
@@ -55,5 +55,5 @@ class MetadataPanel(AppShell,Pmw.MegaWidget):
 
     def SetIt(self):
         self.Metanode.setTag("Metadata",self.tag_text.get())
-
-
+        
+        

+ 8 - 8
doc/SceneEditor/SeSession.py

@@ -8,21 +8,21 @@
 # Also, the way of selecting, renaming and some hot-key controls are changed.
 #
 #################################################################
-from PandaObject import *
-from DirectGlobals import *
-from DirectUtil import*
-from intervalGlobal import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectGlobals import *
+from direct.directtools.DirectUtil import*
+from direct.interval.intervalGlobal import *
 from seCameraControl import *
 from seManipulation import *
 from seSelection import *
 from seGrid import *
 from seGeometry import *
-import Placer
-import Slider
-import OnscreenText
+from direct.tkpanels import Placer
+from direct.tkwidgets import Slider
+from direct.gui import OnscreenText
 import types
 import string
-import Loader
+from direct.showbase import Loader
 
 class SeSession(PandaObject):  ### Customized DirectSession
 

+ 5 - 5
doc/SceneEditor/SideWindow.py

@@ -2,13 +2,13 @@
 # sideWindow.py
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 
 import seSceneGraphExplorer
-import Floater
-import Slider
-import VectorWidgets
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
+from direct.tkwidgets import VectorWidgets
 
 class sideWindow(AppShell):
     #################################################################

+ 5 - 5
doc/SceneEditor/collisionWindow.py

@@ -3,12 +3,12 @@
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 from seColorEntry import *
-import VectorWidgets
-import Floater
-import Slider
+from direct.tkwidgets import VectorWidgets
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
 import string
 import math
 import types

+ 4 - 4
doc/SceneEditor/controllerWindow.py

@@ -3,10 +3,10 @@
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
-import VectorWidgets
-import Floater
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
+from direct.tkwidgets import VectorWidgets
+from direct.tkwidgets import Floater
 import string
 
 # Define the Category

+ 11 - 11
doc/SceneEditor/dataHolder.py

@@ -1,13 +1,13 @@
 ###############################
 # TK and PMW INTERFACE MODULES#
 ###############################
-from TkGlobal import*
+from direct.showbase.TkGlobal import*
 from tkFileDialog import *
 import Pmw
 import tkFileDialog
 import tkMessageBox
-import Dial
-import Floater
+from direct.tkwidgets import Dial
+from direct.tkwidgets import Floater
 
 
 #############################
@@ -19,7 +19,7 @@ from seFileSaver import * # The actual File Saving Module which generates Python
 ################################
 #Panda Modules                 #
 ################################
-import Actor
+from direct.actor import Actor
 
 ###############################
 # Core Python Modules         #
@@ -588,7 +588,7 @@ class dataHolder:
             return True
 
         return False
-
+        
     def bindCurveToNode(self,node,curveCollection):
         ###########################################################################
         # bindCurveToNode(self,node,curveCollection)
@@ -713,7 +713,7 @@ class dataHolder:
         number = len(self.dummyDict)
         number += 1
         name = 'Dummy%d'%number
-        self.dummyModel = loader.loadModelCopy( "misc/sphere" )
+        self.dummyModel = loader.loadModelCopy( "models/misc/sphere" )
         self.dummyModel.reparentTo(nodePath)
         while self.isInScene(name):
             name = name + '_1'
@@ -936,7 +936,7 @@ class dataHolder:
 
         ### Ask for a filename  
         OpenFilename = tkFileDialog.askopenfilename(filetypes = [("PY","py")],title = "Load Scene")
-        if(not OpenFilename):
+        if(not OpenFilename):   
             return None
         f=Filename.fromOsSpecific(OpenFilename)
         fileName=f.getBasenameWoExtension()
@@ -989,7 +989,7 @@ class dataHolder:
         for light in self.Scene.LightDict:
             #print light
             alight=self.Scene.LightDict[light]
-            type=self.Scene.LightTypes[light]
+            type=self.Scene.LightTypes[light]   
             thenode=self.Scene.LightNodes[light]
             #print type
             if type == 'ambient':
@@ -1032,7 +1032,7 @@ class dataHolder:
                 nodeP.removeNode()
                 thenode=render.find("**/"+str(node))
                 self.bindCurveToNode(thenode,curveColl)
-
+        
         ############################################################################
         # Populate Particle related Dictionaries
         ############################################################################
@@ -1049,8 +1049,8 @@ class dataHolder:
             theeffect.enable()
             self.particleDict[effect]=theeffect
             self.particleNodes[effect]=emitter
-
-
+            
+        
  
         # Clean up things added to scene graph by saved file's code execution
         for light in self.Scene.LightDict:

+ 2 - 2
doc/SceneEditor/duplicateWindow.py

@@ -2,8 +2,8 @@
 # duplicateWindow.py
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 
 import seSceneGraphExplorer
 

+ 5 - 5
doc/SceneEditor/lightingPanel.py

@@ -3,12 +3,12 @@
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 from seColorEntry import *
-import VectorWidgets
-import Floater
-import Slider
+from direct.tkwidgets import VectorWidgets
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
 import string
 import math
 import types

+ 7 - 7
doc/SceneEditor/propertyWindow.py

@@ -2,16 +2,16 @@
 # propertyWindow.py
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 
 from seColorEntry import *
 
-import Floater
-import Dial
-import Slider
-import VectorWidgets
-import Task
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Dial
+from direct.tkwidgets import Slider
+from direct.tkwidgets import VectorWidgets
+from direct.task import Task
 
 class propertyWindow(AppShell,Pmw.MegaWidget):
     #################################################################

+ 31 - 31
doc/SceneEditor/quad.py

@@ -6,11 +6,11 @@
 #########################################################################################################################################
 
 
-from ShowBaseGlobal import *
-from intervalGlobal import *
-import DirectObject
+from direct.showbase.ShowBaseGlobal import *
+from direct.interval.intervalGlobal import *
+from direct.showbase import DirectObject
 import math
-from MouseWatcher import *
+from pandac.MouseWatcher import *
 
 
 class ViewPort:
@@ -89,7 +89,7 @@ class ViewPort:
         self.cam.node().setLens(self.lens)
    
     def resize(self,x,y):
-
+        
         if(self.VPType=="left"):
             self.the_viewport.setDimensions(0,x,0,y)
             w=abs(x-self.VP_X1)
@@ -139,7 +139,7 @@ class ViewPort:
 
     def getCam(self):
         return self.cam
-
+        
 
 class QuadView(DirectObject.DirectObject):
 #########################################################################################################################################
@@ -155,7 +155,7 @@ class QuadView(DirectObject.DirectObject):
         self.AltPressed=0
         self.PanConstantX=50
         self.PanConstantY=50
-        self.ZoomConstant=1
+        self.ZoomConstant=1     
         self.FrontWidth=100
         self.FrontHeight=100
         self.TopWidth=100
@@ -186,7 +186,7 @@ class QuadView(DirectObject.DirectObject):
 
         # Keep track of the currently selected window... values are 1-4 for four quadrants of a standard 
         # Cartesian coordinate system
-
+        
         # These are the orthographic cameras
         # They will be restricted to panning and zooming i.e. no rotation
         # Top could be flipped to back, left to right and front to back
@@ -196,7 +196,7 @@ class QuadView(DirectObject.DirectObject):
 
         # This camera will have a trackball control since its perspective
         self.perspectiveCam = render.attachNewNode(Camera('perspectiveCam'))
-
+        
         #self.toplens=OrthographicLens()
         #self.leftLens=OrthographicLens()
         #self.frontLens=OrthographicLens()
@@ -208,7 +208,7 @@ class QuadView(DirectObject.DirectObject):
         #self.leftCamLens= base.cam.node().getLens()
         #self.perspectiveCamLens= base.cam.node().getLens()
 
-        # Manipulate lenses here if need be
+        # Manipulate lenses here if need be     
         #self.topCamLens.setFilmSize(250)
 
         # Set the Lenses
@@ -237,12 +237,12 @@ class QuadView(DirectObject.DirectObject):
         #self.FrontScene=render.copyTo(self.SceneParent)
         #self.TopScene=render.copyTo(self.SceneParent)
         #self.LeftScene=render.copyTo(self.SceneParent)
-
+                
         self.PerspectiveScene=render
         self.FrontScene=render
         self.TopScene=render
         self.LeftScene=render
-
+        
         #self.PerspectiveScene.reparentTo(self.SceneParent)
         #self.FrontScene.reparentTo(self.SceneParent)
         #self.TopScene.reparentTo(self.SceneParent)
@@ -261,7 +261,7 @@ class QuadView(DirectObject.DirectObject):
         #self.lastPickPoint = None
 
         #base.useTrackball()
-
+        
         #self.dataRoot = NodePath('dataRoot')
         # Cache the node so we do not ask for it every frame
         #self.dataRootNode = self.dataRoot.node()
@@ -270,7 +270,7 @@ class QuadView(DirectObject.DirectObject):
         #self.mak = self.dataRoot.attachNewNode(MouseAndKeyboard(base.win, 0, 'mak'))
         #self.mak.node().setSource(base.win, 0)
         self.mouseWatcherNode = MouseWatcher('mouseWatcher')
-
+        
         self.mouseWatcher = base.mak.attachNewNode(self.mouseWatcherNode)
         #self.Perspective.setDR(self.mouseWatcherNode)
 
@@ -300,7 +300,7 @@ class QuadView(DirectObject.DirectObject):
         self.accept("alt-mouse1-up",self.AltUp)
         self.accept("control-mouse1",self.CtlDown)
         self.accept("control-mouse1-up",self.CtlUp)
-
+        
     # Methods
 
     #def setLastPickPoint( self ):
@@ -435,10 +435,10 @@ class QuadView(DirectObject.DirectObject):
         if(self.oldY<-1 or self.oldY>1):
             return
         taskMgr.add(self.DragAction,'DragAction')
-
+            
     def AltUpHandler(self):
-        taskMgr.remove('DragAction')
-
+        taskMgr.remove('DragAction')    
+        
     def gridtoggle(self):
         #grid=DirectGrid()
         #grid.enable()
@@ -465,11 +465,11 @@ class QuadView(DirectObject.DirectObject):
                 self.setPerspective()
             else:
                 self.setFront()
-
+        
     def MouseTell(self,buttonCode):
         self.MouseButton=buttonCode
         self.setAppropriateViewPort(self.mouseWatcherNode.getMouseX(),self.mouseWatcherNode.getMouseY())
-
+        
         x=base.mouseWatcherNode.getMouseX()
         y=base.mouseWatcherNode.getMouseY()
 
@@ -509,10 +509,10 @@ class QuadView(DirectObject.DirectObject):
         SEditor.manipulationControl.manipulationStop(self.xy)
         #print "MouseX " + str(base.mouseWatcherNode.getMouseX()) + "MouseY " + str(base.mouseWatcherNode.getMouseY()) + "\n" 
         #print "MouseX " + str(self.mouseWatcherNode.getMouseX()) + "MouseY " + str(self.mouseWatcherNode.getMouseY()) + "\n" 
-
+        
 
         base.mouseWatcherNode=self.mouseWatcherNode
-
+        
         self.oldX=self.mouseWatcherNode.getMouseX()
         if(self.oldX<-1 or self.oldX>1):
             return
@@ -531,11 +531,11 @@ class QuadView(DirectObject.DirectObject):
         taskMgr.remove('DragAction')
         self.Mouse_Draggin=0
         #print "Mouse Up"
-
+        
 
     def Max_Style_Mouse_View(self,buttoncode):
         pass
-
+        
     def ChangeBaseDR(self):
         dr=base.win.getDisplayRegion(0)
         if(self.CurrentQuad==1): #Front
@@ -567,7 +567,7 @@ class QuadView(DirectObject.DirectObject):
         self.ChangeBaseDR()
         self.Perspective.setCam()
         #self.Perspective.setDR(self.mouseWatcherNode)
-
+        
     def setFront(self):
         print "FRONT"
         self.CurrentQuad=1
@@ -596,7 +596,7 @@ class QuadView(DirectObject.DirectObject):
              if(self.HorizontalAxis<-1 or self.HorizontalAxis>1 or self.VerticalAxis<-1 or self.VerticalAxis>1):
                  return
              self.resizedr(self.VerticalAxis,self.HorizontalAxis)
-
+        
         #if(self.AltPressed): # View Camera Transforms -> Maya style
         elif(1):
             #print "ALTPRESSED"
@@ -632,26 +632,26 @@ class QuadView(DirectObject.DirectObject):
                     if(self.FrontHeight<=0):
                         FrontHeight=1
                     self.frontCam.node().getLens().setFilmSize(self.FrontWidth,self.FrontHeight)
-                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)
+                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)        
                 elif(self.CurrentQuad==2):
                     self.TopWidth= self.TopWidth + self.diffX
                     self.TopHeight= self.TopHeight + self.diffX
                     self.TopWidth= self.TopWidth + self.diffY
                     self.TopHeight= self.TopHeight + self.diffY
                     self.topCam.node().getLens().setFilmSize(self.TopWidth,self.TopHeight)
-                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)
+                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)        
                 elif(self.CurrentQuad==3):
                     self.LeftWidth= self.LeftWidth + self.diffX
                     self.LeftHeight= self.LeftHeight + self.diffX
                     self.LeftWidth= self.LeftWidth + self.diffY
                     self.LeftHeight= self.LeftHeight + self.diffY
                     self.leftCam.node().getLens().setFilmSize(self.LeftWidth,self.LeftHeight)
-                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)
+                    self.resizedr(self.VerticalAxis,self.HorizontalAxis)        
                 elif(self.CurrentQuad==4):
                     pass
         else:
              pass
-
+                
         self.oldX=self.currX
         self.oldY=self.currY
         return Task.cont
@@ -667,7 +667,7 @@ class QuadView(DirectObject.DirectObject):
             self.leftCam.setPos(self.leftCam.getX()+X_amt,self.leftCam.getY()+Y_amt,self.leftCam.getZ()+Z_amt)
         elif(quad==4):
             self.perspectiveCam.setPos(self.perspectiveCam.getX()+X_amt,self.perspectiveCam.getY()+Y_amt,self.perspectiveCam.getZ()+Z_amt)
-
+        
     
 
 #View=QuadView()

+ 3 - 3
doc/SceneEditor/seAnimPanel.py

@@ -3,13 +3,13 @@
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 from tkSimpleDialog import askfloat
 import string
 import math
 import types
-import Task
+from direct.task import Task
 
 FRAMES = 0
 SECONDS = 1

+ 3 - 3
doc/SceneEditor/seBlendAnimPanel.py

@@ -3,13 +3,13 @@
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 from tkSimpleDialog import askfloat
 import string
 import math
 import types
-import Task
+from direct.task import Task
 
 FRAMES = 0
 SECONDS = 1

+ 6 - 6
doc/SceneEditor/seCameraControl.py

@@ -11,11 +11,11 @@
 # (If we do change original directools, it will force user has to install the latest version of OUR Panda)
 #
 #################################################################
-from PandaObject import *
-from DirectUtil import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectUtil import *
 from seGeometry import *
-from DirectGlobals import *
-import Task
+from direct.directtools.DirectGlobals import *
+from direct.task import Task
 
 CAM_MOVE_DURATION = 1.2
 COA_MARKER_SF = 0.0075
@@ -312,7 +312,7 @@ class DirectCameraControl(PandaObject):
             nodePath = entry.getIntoNodePath()
             if SEditor.camera not in nodePath.getAncestry():
                 # Compute new hit point
-                hitPt = entry.getFromIntersectionPoint()
+                hitPt = entry.getSurfacePoint(entry.getFromNodePath())
                 # Move coa marker to new point
                 self.updateCoa(hitPt, ref = self.coaMarkerRef)
             else:
@@ -332,7 +332,7 @@ class DirectCameraControl(PandaObject):
         elif entry:
             # Got a hit point (hit point is in camera coordinates)
             # Set center of action
-            hitPt = entry.getFromIntersectionPoint()
+            hitPt = entry.getSurfacePoint(entry.getFromNodePath())
             hitPtDist = Vec3(hitPt).length()
             coa.assign(hitPt)
             # Handle case of bad coa point (too close or too far)

+ 5 - 5
doc/SceneEditor/seColorEntry.py

@@ -9,13 +9,13 @@
 # So we make one from them.
 #
 #################################################################
-from TkGlobal import *
-import Valuator
-import Floater
-import Slider
+from direct.showbase.TkGlobal import *
+from direct.tkwidgets import Valuator
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
 import string
 import tkColorChooser
-from VectorWidgets import VectorEntry
+from direct.tkwidgets.VectorWidgets import VectorEntry
 
 class seColorEntry(VectorEntry):
     def __init__(self, parent = None, **kw):

+ 66 - 67
doc/SceneEditor/seFileSaver.py

@@ -3,12 +3,11 @@
 # This code saves the scene out as python code... the scene is stored in the various dictionaries in "dataHolder.py" ...the class "AllScene"
 # 
 ####################################################################################################################################################
-from PandaModules import *
+from pandac.PandaModules import *
 
-from ShowBaseGlobal import *
+from direct.showbase.ShowBaseGlobal import *
 import os
 import shutil
-from EggData import *
 import string
 
 ####################################################################################################################################################
@@ -35,11 +34,11 @@ class FileSaver:
 
     def SaveFile(self,AllScene,filename,dirname,reSaveFlag=0):
 
-        ################################################################################################################################################
+      ################################################################################################################################################  
         # This function takes the "dataHolder" instance "AllScene" which has dictionaries containing scene information
         # The filename is where the scene will be written to
         ################################################################################################################################################
-
+        
         i1="    " # indentation
         i2=i1+i1  # double indentation
         out_file = open(filename,"w")
@@ -58,18 +57,18 @@ class FileSaver:
         out_file.write("# theScene=SavedScene() #instantiate the class\n")
         out_file.write("# IMPORTANT: All the documentation below refers to \"theScene\" as the instance of SavedScene()\n")
         out_file.write("##########################################################################################################\n\n")
-
+        
         out_file.write("##########################################################################################################\n")
         out_file.write("# Import Panda Modules\n")
         out_file.write("##########################################################################################################\n")
-        out_file.write("from ShowBaseGlobal import * # Core functionality for running the \"show\"\n")
-        out_file.write("import Actor # Importing models with animations\n")
-        out_file.write("import Mopath # Motion Paths\n")
-        out_file.write("import MopathInterval # Motion Paths\n")
-        out_file.write("from IntervalGlobal import * # Intervals for interpolation, sequencing and parallelization\n")
-        out_file.write("import ParticleEffect # Particle Systems\n")
-        out_file.write("import ForceGroup # Forces acting on Particles\n")
-        out_file.write("import Particles\n\n")
+        out_file.write("from direct.directbase.DirectStart import * # Core functionality for running the \"show\"\n")
+        out_file.write("from direct.actor import Actor # Importing models with animations\n")
+        out_file.write("from direct.directutil import Mopath # Motion Paths\n")
+        out_file.write("from direct.interval import MopathInterval # Motion Paths\n")
+        out_file.write("from direct.interval.IntervalGlobal import * # Intervals for interpolation, sequencing and parallelization\n")
+        out_file.write("from direct.particles import ParticleEffect # Particle Systems\n")
+        out_file.write("from direct.particles import ForceGroup # Forces acting on Particles\n")
+        out_file.write("from direct.particles import Particles\n\n")
         out_file.write("##########################################################################################################\n")
         out_file.write("# This class stores the entire scene\n")
         out_file.write("##########################################################################################################\n\n")
@@ -147,7 +146,7 @@ class FileSaver:
         for model in AllScene.ModelDic:
             out_file.write("\n")
             modelS=str(model)
-
+            
             if(1): # This is kept for now... perhaps later some sort of check might have to be enforced based on loadMode
                 #Loading Code
                 out_file.write(i2+"# Loading model's egg file\n")
@@ -172,27 +171,27 @@ class FileSaver:
                         if(texfilename.resolveFilename(getTexturePath(),"")):
                             oldFilename=texfilename
                     oldtexpath=oldFilename.toOsSpecific();
-
+                
                     newtexpath=dirname + "/" + texfilename.getBasename()
                     newtexpathF=Filename(newtexpath)
                     newtexpathSpecific=newtexpathF.toOsSpecific()
-
+                    
                     print "TEXTURE SAVER:: copying" + oldtexpath + " to " + newtexpathSpecific
                     if(oldtexpath != newtexpathSpecific):
                         shutil.copyfile(oldtexpath,newtexpathSpecific)
 
+                    
+                
+                    
 
-
-
-
-
+                
                 # Copy the file over to the relative directory
                 oldModelpath=AllScene.ModelRefDic[model].toOsSpecific()
                 print "FILESAVER:: copying from " + AllScene.ModelRefDic[model].toOsSpecific() + "to" + newpathSpecific 
                 if(oldModelpath!=newpathSpecific):
                     shutil.copyfile(oldModelpath,newpathSpecific)
 
-
+                
                 e=EggData()
                 e.read(AllScene.ModelRefDic[model])
                 etc=EggTextureCollection()
@@ -204,10 +203,10 @@ class FileSaver:
                     fn.setDirname("")
                     tex.setFilename(fn)
                     e.writeEgg(Filename.fromOsSpecific(newpathSpecific))
+                
 
 
-
-                out_file.write(i2+"if(self.loadmode==1):\n")
+                out_file.write(i2+"if(self.loadmode==1):\n")    
                 out_file.write(i2+i1+ "self."+ modelS + "=loader.loadModel(\'" + self.savepath + "/" +  AllScene.ModelRefDic[model].getBasename() + "')\n")#Relative Path
                 out_file.write(i2+"else:\n")
                 out_file.write(i2+i1+ "self."+ modelS + "=loader.loadModel(self.executionpath + \'/" +  AllScene.ModelRefDic[model].getBasename() + "')\n")#Relative Path with execution point specified by the invoking-level-editor
@@ -222,7 +221,7 @@ class FileSaver:
                     out_file.write(i2+"# Alpha\n")
                     out_file.write(i2+ "self."+ modelS + ".setTransparency(1)\n")
                     clr=AllScene.ModelDic[model].getColor()
-                    out_file.write(i2+ "self."+ modelS + ".setColor(%.4f,%.4f,%.4f,%.4f)\n"%(clr.getX(),clr.getY(),clr.getZ(),clr.getW()))
+                    out_file.write(i2+ "self."+ modelS + ".setColor(%.4f,%.4f,%.4f,%.4f)\n"%(clr.getX(),clr.getY(),clr.getZ(),clr.getW()))                  
 
                 out_file.write("\n")
                 out_file.write(i2+ "# Reparent To Render for now and later we update all the parentings\n")
@@ -235,7 +234,7 @@ class FileSaver:
                 out_file.write(i2+ "self.ModelDic[\'" + modelS + "\']=self." + AllScene.ModelDic[model].getName()+"\n")
                 #out_file.write(i2+ "self.ModelRefDic[\'" + modelS + "\']=Filename(\'"+ AllScene.ModelRefDic[model].getFullpath() +"\')\n")# The old Absolute Path way
                 out_file.write(i2+ "self.ModelRefDic[\'" + modelS + "\']=\'"+ AllScene.ModelRefDic[model].getBasename() +"\'\n")# Relative paths
-                out_file.write(i2+ "self.ModelDic[\'"+ modelS + "\'].setName(\'"+ modelS +"\')\n")
+                out_file.write(i2+ "self.ModelDic[\'"+ modelS + "\'].setName(\'"+ modelS +"\')\n")              
                 out_file.write("\n")
 
         ####################################################################################################################################################
@@ -249,9 +248,9 @@ class FileSaver:
         for dummy in AllScene.dummyDict:
             out_file.write("\n")
             dummyS=str(dummy)
-
+            
             if(1): # This is kept for now... perhaps later some sort of check might have to be enforced based on loadMode
-                out_file.write(i2+ "self."+ dummyS + "=loader.loadModelCopy(\"misc/sphere\")\n")
+                out_file.write(i2+ "self."+ dummyS + "=loader.loadModelCopy(\"models/misc/sphere\")\n")
                 #Transformation Code
                 out_file.write(i2+"# Transforming the Dummy\n")
                 out_file.write(i2+ "self."+ dummyS + ".setPosHprScale(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n"% (AllScene.dummyDict[dummy].getX(),AllScene.dummyDict[dummy].getY(),AllScene.dummyDict[dummy].getZ(),AllScene.dummyDict[dummy].getH(),AllScene.dummyDict[dummy].getP(),AllScene.dummyDict[dummy].getR(),AllScene.dummyDict[dummy].getSx(),AllScene.dummyDict[dummy].getSy(),AllScene.dummyDict[dummy].getSz()))
@@ -260,13 +259,13 @@ class FileSaver:
                 out_file.write(i2+ "self.dummyDict[\'" + dummyS + "\']=self." + AllScene.dummyDict[dummy].getName()+"\n")
                 out_file.write(i2+ "self.dummyDict[\'"+ dummyS + "\'].setName(\'"+ dummyS +"\')\n")
                 out_file.write("\n")
-                out_file.write(i2+ "# Save Metadata...can be retrieved by doing theScene.dummyDict[\"Dummy_Name\"].getTag(\"Metadata\")\n")
+                out_file.write(i2+ "# Save Metadata...can be retrieved by doing theScene.dummyDict[\"Dummy_Name\"].getTag(\"Metadata\")\n")             
                 out_file.write(i2+ "self."+ dummyS + ".setTag(\"Metadata\",\"" + AllScene.dummyDict[dummy].getTag("Metadata") + "\")\n")
                 out_file.write("\n")
 
         ####################################################################################################################################################
         # Saving Actors and their animations
-        ####################################################################################################################################################
+        ####################################################################################################################################################                    
         out_file.write(i2+"##########################################################################################################\n")
         out_file.write(i2+"# Code for all the Actors and animations\n")
         out_file.write(i2+"# To access the Actors\n")
@@ -316,7 +315,7 @@ class FileSaver:
                 print "FILESAVER:: copying from " + AllScene.ActorRefDic[actor].toOsSpecific() + "to" + newpathSpecific 
                 if(oldActorpath!=newpathSpecific):
                     shutil.copyfile(oldActorpath,newpathSpecific)
-
+                
 
                 e=EggData()
                 e.read(AllScene.ActorRefDic[actor])
@@ -329,10 +328,10 @@ class FileSaver:
                     fn.setDirname("")
                     tex.setFilename(fn)
                     e.writeEgg(Filename.fromOsSpecific(newpathSpecific))
+                
 
 
-
-                out_file.write(i2+"if(self.loadmode==1):\n")
+                out_file.write(i2+"if(self.loadmode==1):\n")    
                 out_file.write(i2+i1+ "self."+ actorS + "=Actor.Actor(\'" + self.savepath + "/" +  AllScene.ActorRefDic[actor].getBasename() + "')\n")#Relative Path
                 out_file.write(i2+"else:\n")
                 out_file.write(i2+i1+ "self."+ actorS + "=Actor.Actor(self.executionpath + \'/" +  AllScene.ActorRefDic[actor].getBasename() + "')\n")#Relative Path with execution point specified by the invoking-level-editor
@@ -361,7 +360,7 @@ class FileSaver:
                 if(ActorAnimations!={}):  #Check if a dictionary of animations exists for this actor
                     for animation in ActorAnimations:
                         #out_file.write(i2+ "self."+ actorS + ".loadAnims(" + str(ActorAnimations) +")\n") # Old way with absolute paths
-                        print "ACTOR ANIMATIONS" + ActorAnimations[animation]
+                        print "ACTOR ANIMATIONS" + ActorAnimations[animation]   
                         oldAnimPath=Filename(ActorAnimations[animation])
                         oldAnim=oldAnimPath.toOsSpecific()
                         dirOS=Filename(dirname)
@@ -379,24 +378,24 @@ class FileSaver:
                 out_file.write(i2+"else:\n")
                 theloadAnimString=str(ActorAnimationsInvoke)# We hack the "self.executionpath" part into the dictionary as a variable using string replace
                 print "LOAD ANIM STRING BEFORE" + theloadAnimString
-                theloadAnimString=theloadAnimString.replace('\'self.executionpath +','self.executionpath + \'')
+                theloadAnimString=theloadAnimString.replace('\'self.executionpath +','self.executionpath + \'')         
                 print "LOAD ANIM STRING AFTER" + theloadAnimString
                 out_file.write(i2+ i1+"self."+ actorS + ".loadAnims(" + theloadAnimString +")\n") # Now with new relative paths based on editor invocation
 
                 out_file.write(i2+ "self.ActorDic[\'" + actorS + "\']=self." + AllScene.ActorDic[actor].getName()+"\n")
                 #out_file.write(i2+ "self.ActorRefDic[\'" + actorS + "\']=Filename(\'"+AllScene.ActorRefDic[actor].getFullpath() +"\')\n") # Old way with absolute paths
                 out_file.write(i2+ "self.ActorRefDic[\'" + actorS + "\']=\'"+ AllScene.ActorRefDic[actor].getBasename() +"\'\n")# Relative paths
-                out_file.write(i2+ "self.ActorDic[\'"+ actorS + "\'].setName(\'"+ actorS +"\')\n")
+                out_file.write(i2+ "self.ActorDic[\'"+ actorS + "\'].setName(\'"+ actorS +"\')\n")              
                 if(AllScene.blendAnimDict.has_key(actor)): # Check if a dictionary of blended animations exists
                     out_file.write(i2+ "self.blendAnimDict[\"" + actorS +"\"]=" + str(AllScene.blendAnimDict[actor]) + "\n")
-
-
+                
+                
                 out_file.write("\n")
-
+        
         ####################################################################################################################################################
         # Collsion Node Saving
         ####################################################################################################################################################
-
+        
         out_file.write(i2+"##########################################################################################################\n")
         out_file.write(i2+"# Code for setting up Collision Nodes\n")
         out_file.write(i2+"# To use collision detection:\n")
@@ -409,7 +408,7 @@ class FileSaver:
             nodetype=solid.getType().getName()
 
             if(nodetype=="CollisionSphere"): #Save Collison Sphere
-                out_file.write(i2+"collSolid=CollisionSphere(%.3f,%.3f,%.3f,%.3f)\n"%(solid.getCenter().getX(),solid.getCenter().getY(),solid.getCenter().getZ(),solid.getRadius()))
+                out_file.write(i2+"collSolid=CollisionSphere(%.3f,%.3f,%.3f,%.3f)\n"%(solid.getCenter().getX(),solid.getCenter().getY(),solid.getCenter().getZ(),solid.getRadius()))            
                 pass
             elif(nodetype=="CollisionPolygon"): #Save Collison Polygon
 
@@ -429,13 +428,13 @@ class FileSaver:
                 out_file.write(i2+"pointB =  Point3(" + bx + "," + by + "," + bz + ")\n")
                 out_file.write(i2+"pointC =  Point3(" + cx + "," + cy + "," + cz + ")\n")
                 out_file.write(i2+"collSolid=CollisionPolygon(pointA, pointB, pointC)\n")
-
+                
                 pass
 
             elif(nodetype=="CollisionSegment"): #Save Collison Segment
                 A=AllScene.collisionDict[collnode].node().getSolid(0).getPointA()
                 B=AllScene.collisionDict[collnode].node().getSolid(0).getPointB()
-
+                
                 out_file.write(i2+"pointA =  Point3(%.3f,%.3f,%.3f)\n"%(A.getX(),A.getY(),A.getZ()))
                 out_file.write(i2+"pointB =  Point3(%.3f,%.3f,%.3f)\n"%(B.getX(),B.getY(),B.getZ()))
                 out_file.write(i2+"collSolid=CollisionSegment()\n")
@@ -465,7 +464,7 @@ class FileSaver:
             out_file.write(i2+"self." + collnodeS + "_Node" + ".addSolid(collSolid)\n")
             out_file.write(i2+"base.cTrav.addCollider(self." + collnodeS + "_Node,self.CollisionHandler)\n")
             out_file.write("\n")
-
+           
 
 
 
@@ -488,7 +487,7 @@ class FileSaver:
                      out_file.write (i2+ "alight.setColor(VBase4("+ str(light.getLightColor().getX())+ "," + str(light.getLightColor().getY())+ "," + str(light.getLightColor().getZ()) + "," + str(light.getLightColor().getW()) + "))\n")
                      out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
                      out_file.write (i2+ "self."+light.getName()+"= render.attachNewNode(alight.upcastToPandaNode())\n") 
-                     out_file.write (i2+ "self."+light.getName()+".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
+                     out_file.write (i2+ "self."+light.getName()+".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")        
                      out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
                      out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
                      out_file.write (i2+ "self.LightNodes[\'" + light.getName() + "\']=self." + light.getName() + "\n")
@@ -505,7 +504,7 @@ class FileSaver:
                      out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToPandaNode())\n") 
                      out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
                      out_file.write (i2+ "self."+light.getName()+ ".setHpr(Vec3("+ str(light.getH())+ "," + str(light.getP())+ "," + str(light.getR()) + "))\n")
-                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
+                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")       
                      #out_file.write (i2+ "alight.setPos
                      out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
                      out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
@@ -521,7 +520,7 @@ class FileSaver:
                      out_file.write (i2+ "alight.setAttenuation(Vec3("+ str(light.getAttenuation().getX()) + "," + str(light.getAttenuation().getY()) + "," + str(light.getAttenuation().getZ()) + "))\n")
                      out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
                      out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToPandaNode())\n") 
-                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
+                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")       
                      out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
                      out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
                      out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
@@ -539,7 +538,7 @@ class FileSaver:
                      out_file.write (i2+ "alight.setExponent(" +str(light.getExponent()) +")\n")
                      out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
                      out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToLensNode())\n") 
-                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
+                     out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")       
                      out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
                      out_file.write (i2+ "self."+light.getName()+ ".setHpr(Vec3("+ str(light.getH())+ "," + str(light.getP())+ "," + str(light.getR()) + "))\n")
                      out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
@@ -551,7 +550,7 @@ class FileSaver:
                      out_file.write (i2+ "return None")
                  out_file.write("\n")
 
-
+        
 
         ####################################################################################################################################################
         # Enable Lighting
@@ -570,18 +569,18 @@ class FileSaver:
         out_file.write(i2+"# Load Particle Effects. The parameters to this function are to allow us to use our modified versions of the Particle Effects modules when loading this file with the level editor\n")
         out_file.write(i2+"self.starteffects(self.loadmode,self.seParticleEffect,self.seParticles)\n")
         out_file.write("\n")
-
+                
         ####################################################################################################################################################
         # Save Camera Settings
         ####################################################################################################################################################
 
         out_file.write("\n")
         out_file.write(i2+ "# Save Camera Settings\n")
-        out_file.write(i2+ "camera.setX(" + str(camera.getX()) + ")\n") 
-        out_file.write(i2+ "camera.setY(" + str(camera.getY()) + ")\n") 
-        out_file.write(i2+ "camera.setZ(" + str(camera.getZ()) + ")\n") 
-        out_file.write(i2+ "camera.setH(" + str(camera.getH()) + ")\n") 
-        out_file.write(i2+ "camera.setP(" + str(camera.getP()) + ")\n") 
+        out_file.write(i2+ "camera.setX(" + str(camera.getX()) + ")\n")         
+        out_file.write(i2+ "camera.setY(" + str(camera.getY()) + ")\n")         
+        out_file.write(i2+ "camera.setZ(" + str(camera.getZ()) + ")\n")         
+        out_file.write(i2+ "camera.setH(" + str(camera.getH()) + ")\n")         
+        out_file.write(i2+ "camera.setP(" + str(camera.getP()) + ")\n")         
         out_file.write(i2+ "camera.setR(" + str(camera.getR()) + ")\n") 
         out_file.write(i2+ "camera.getChild(0).node().getLens().setNear(" + str(camera.getChild(0).node().getLens().getNear()) + ")\n") 
         out_file.write(i2+ "camera.getChild(0).node().getLens().setFar(" + str(camera.getChild(0).node().getLens().getFar()) + ")\n") 
@@ -589,13 +588,13 @@ class FileSaver:
         FilmSize=camera.getChild(0).node().getLens().getFilmSize()
         out_file.write(i2+ "camera.getChild(0).node().getLens().setFilmSize(%.3f,%.3f)\n"%(FilmSize.getX(),FilmSize.getY())) 
         out_file.write(i2+ "camera.getChild(0).node().getLens().setFocalLength(" + str(camera.getChild(0).node().getLens().getFocalLength()) + ")\n") 
-        out_file.write(i2+ "camera.setTag(\"Metadata\",\"" + camera.getTag("Metadata") + "\")\n")
+        out_file.write(i2+ "camera.setTag(\"Metadata\",\"" + camera.getTag("Metadata") + "\")\n")       
         out_file.write(i2+ "camera.reparentTo(render)\n")
         out_file.write(i2+ "base.disableMouse()\n")
         self.bgColor=base.getBackgroundColor()
         out_file.write(i2+ "base.setBackgroundColor(%.3f,%.3f,%.3f)\n"%(self.bgColor.getX(),self.bgColor.getY(),self.bgColor.getZ()))
         out_file.write("\n")
-
+        
 
         ####################################################################################################################################################
         # Mopath Saving
@@ -625,7 +624,7 @@ class FileSaver:
 
                 out_file.write(i2+"mp=MopathInterval(m,self." + str(node) + ")\n")
                 out_file.write(i2+"self.curveIntervals.append(mp)\n")
-
+                
                 out_file.write(i2+"if(self.loadmode==1):\n")
                 out_file.write(i2+i1+"self.curveRefColl.append(\"" + self.savepath +"/"+ filestring +"\")\n")
                 out_file.write(i2+"else:\n")
@@ -674,7 +673,7 @@ class FileSaver:
             out_file.write(i2+"\n")
 
         for actor in AllScene.ActorDic:
-            actorS=str(actor)
+            actorS=str(actor)   
             parent=AllScene.ActorDic[actor].getParent().getName()
             if(parent=="render" or parent=="camera"):
                 out_file.write(i2+ "self."+ actorS + ".reparentTo(" + parent + ")\n")
@@ -686,7 +685,7 @@ class FileSaver:
 
             out_file.write(i2+ "self.ActorDic[\'" + actorS + "\']=self." + AllScene.ActorDic[actor].getName()+"\n")
             out_file.write(i2+"\n")
-
+        
 
         for collnode in AllScene.collisionDict:
             collnodeS=str(collnode)
@@ -739,7 +738,7 @@ class FileSaver:
         for effect in AllScene.particleDict:
             parent=AllScene.particleNodes[effect].getParent().getName()
             if(parent=="render" or parent=="camera"):
-                out_file.write(i2+"self.particleDict[\""+ str(effect) +"\"].reparentTo("  + parent + ")\n")
+                out_file.write(i2+"self.particleDict[\""+ str(effect) +"\"].reparentTo("  + parent + ")\n")             
             else:
                 out_file.write(i2+"self.particleDict[\""+ str(effect) +"\"].reparentTo(self."  + parent + ")\n")
             out_file.write(i2+"\n")
@@ -807,11 +806,11 @@ class FileSaver:
         out_file.write(i2+"blendList=blendDicts[blendName]\n")
         out_file.write(i2+"actor.stop(blendList[0])\n")
         out_file.write(i2+"actor.stop(blendList[1])\n")
-        out_file.write("\n")
+        out_file.write("\n")    
 
         out_file.write(i1+"def changeBlending(self,actor,blendName,blending):\n")
         out_file.write(i2+"blendDicts=self.blendAnimDict[actor.getName()]\n")
-        out_file.write(i2+"blendList=blendDicts[blendName]\n")
+        out_file.write(i2+"blendList=blendDicts[blendName]\n")  
         out_file.write(i2+"blendList[2]=blending\n")
         out_file.write(i2+"self.blendAnimDict[actor.getName()]={blendName:[blendList[0],blendList[1],blending]}\n")
         out_file.write("\n")
@@ -834,7 +833,7 @@ class FileSaver:
         out_file.write("\n")
         out_file.write(i2+"for dummy in self.dummyDict:\n")
         out_file.write(i2+i1+"self.dummyDict[dummy].reparentTo(hidden)\n")
-
+        
        
         out_file.write("\n")
         out_file.write(i1+"def hideCollSolids(self):\n")
@@ -855,7 +854,7 @@ class FileSaver:
         out_file.write("\n")
         out_file.write(i2+"for dummy in self.dummyDict:\n")
         out_file.write(i2+i1+"self.dummyDict[dummy].reparentTo(hidden)\n")
-
+        
        
         out_file.write("\n")
         out_file.write(i1+"def showCollSolids(self):\n")
@@ -909,5 +908,5 @@ class FileSaver:
         #out_file.write("run()\n")
 
         out_file.close()
-
-
+                
+                

+ 5 - 5
doc/SceneEditor/seForceGroup.py

@@ -1,9 +1,9 @@
-from PandaModules import *
-from DirectObject import *
-from PhysicsManagerGlobal import *
+from pandac.PandaModules import *
+from direct.showbase.DirectObject import *
+from direct.showbase.PhysicsManagerGlobal import *
 
-import ForceNode
-import DirectNotifyGlobal
+from pandac import ForceNode
+from direct.directnotify import DirectNotifyGlobal
 import sys
 
 class ForceGroup(DirectObject):

+ 4 - 4
doc/SceneEditor/seGeometry.py

@@ -12,10 +12,10 @@
 #
 #################################################################
 
-from PandaModules import *
-from PandaObject import *
-from DirectGlobals import *
-from DirectUtil import *
+from pandac.PandaModules import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectGlobals import *
+from direct.directtools.DirectUtil import *
 import math
 
 class LineNodePath(NodePath):

+ 2 - 2
doc/SceneEditor/seGrid.py

@@ -11,8 +11,8 @@
 # (If we do change original directools, it will force user has to install the latest version of OUR Panda)
 #
 #################################################################
-from PandaObject import *
-from DirectUtil import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectUtil import *
 from seGeometry import *
 
 class DirectGrid(NodePath,PandaObject):

+ 8 - 8
doc/SceneEditor/seLights.py

@@ -2,9 +2,9 @@
 # seLights.py
 # Written by Yi-Hong Lin, [email protected], 2004
 #################################################################
-from PandaObject import *
+from direct.showbase.PandaObject import *
 from string import lower
-import DirectUtil
+from direct.directtools import DirectUtil
 import string
 
 
@@ -74,10 +74,10 @@ class seLight(NodePath):
             self.LightNode.setHpr(self.orientation)
             self.LightNode.setPos(self.position)
         else:
-            self.LightNode.setHpr(self.orientation)
+            self.LightNode.setHpr(self.orientation)     
             self.LightNode.setPos(self.position)
-
-
+            
+        
         self.assign(self.LightNode)
         if(self.type=='spot'):
             self.helpModel = loader.loadModelCopy( "Spotlight" )
@@ -86,7 +86,7 @@ class seLight(NodePath):
         elif(self.type=='directional'):
             self.helpModel = loader.loadModelCopy( "Dirlight" )
         else:
-            self.helpModel = loader.loadModelCopy( "misc/Sphere" )
+            self.helpModel = loader.loadModelCopy( "models/misc/sphere" )
         self.helpModel.setColor(self.lightcolor)
         self.helpModel.reparentTo(self)
         DirectUtil.useDirectRenderStyle(self.helpModel)
@@ -202,7 +202,7 @@ class seLight(NodePath):
         #################################################################
         self.orientation = self.LightNode.getHpr()
         return self.orientation
-
+        
     def setOrientation(self,orient):
         #################################################################
         # setOrientation(self, orient)
@@ -303,7 +303,7 @@ class seLightManager(NodePath):
         # Originally, we don't do this load model thing.
         # But the problem is, if we don't, then it will cause some
         # Bounding calculation error...
-        self.helpModel = loader.loadModelCopy( "misc/sphere" )
+        self.helpModel = loader.loadModelCopy( "models/misc/sphere" )
         self.helpModel.reparentTo(self)
         self.helpModel.hide()
    

+ 7 - 7
doc/SceneEditor/seManipulation.py

@@ -12,11 +12,11 @@
 #
 #################################################################
 
-from PandaObject import *
-from DirectGlobals import *
-from DirectUtil import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectGlobals import *
+from direct.directtools.DirectUtil import *
 from seGeometry import *
-import Task
+from direct.task import Task
 
 class DirectManipulationControl(PandaObject):
     def __init__(self):
@@ -58,7 +58,7 @@ class DirectManipulationControl(PandaObject):
         # Did we hit a widget?
         if entry:
             # Yes!
-            self.hitPt.assign(entry.getFromIntersectionPoint())
+            self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath()))
             self.hitPtDist = Vec3(self.hitPt).length()
             # Constraint determined by nodes name
             self.constraint = entry.getIntoNodePath().getName()
@@ -107,7 +107,7 @@ class DirectManipulationControl(PandaObject):
             entry = SEditor.iRay.pickGeom(skipFlags = skipFlags)
             if entry:
                 # Record hit point information
-                self.hitPt.assign(entry.getFromIntersectionPoint())
+                self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath()))
                 self.hitPtDist = Vec3(self.hitPt).length()
                 # Select it
                 SEditor.select(entry.getIntoNodePath(), SEditor.fShift)
@@ -499,7 +499,7 @@ class DirectManipulationControl(PandaObject):
             SEditor.selected.getWrtAll()
             # Move selected
             SEditor.widget.setPos(
-                SEditor.camera,entry.getFromIntersectionPoint())
+                SEditor.camera,entry.getSurfacePoint(entry.getFromNodePath()))
             # Move all the selected objects with widget
             # Move the objects with the widget
             SEditor.selected.moveWrtWidgetAll()

+ 13 - 12
doc/SceneEditor/seMopathRecorder.py

@@ -13,21 +13,21 @@
 #################################################################
 
 # Import Tkinter, Pmw, and the dial code from this directory tree.
-from PandaObject import *
-from TkGlobal import *
-from AppShell import *
-from DirectGlobals import *
-from DirectUtil import *
+from direct.showbase.PandaObject import *
+from direct.showbase.TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.directtools.DirectGlobals import *
+from direct.directtools.DirectUtil import *
 from SeGeometry import *
 from SeSelection import *
 from tkFileDialog import *
 import os
 import string
-import Dial
-import Floater
-import Slider
-import EntryScale
-import VectorWidgets
+from direct.tkwidgets import Dial
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
+from direct.tkwidgets import EntryScale
+from direct.tkwidgets import VectorWidgets
 import __builtin__
 
 PRF_UTILITIES = [
@@ -1717,7 +1717,8 @@ class MopathRecorder(AppShell, PandaObject):
         self.iRay.rayCollisionNodePath.reparentTo(self.nodePath)
         entry = self.iRay.pickGeom3D()
         if entry:
-            hitPtDist = Vec3(entry.getFromIntersectionPoint()).length()
+            fromNodePath = entry.getFromNodePath()
+            hitPtDist = Vec3(entry.getSurfacePoint(fromNodePath))
             self.nodePath.setZ(self.nodePath, height - hitPtDist)
         self.iRay.rayCollisionNodePath.reparentTo(self.recorderNodePath)
 
@@ -1825,7 +1826,7 @@ class MopathRecorder(AppShell, PandaObject):
         kw['max'] = max
         kw['resolution'] = resolution
         #widget = apply(EntryScale.EntryScale, (parent,), kw)
-        import Slider
+        from direct.tkwidgets import Slider
         widget = apply(Slider.Slider, (parent,), kw)
         # Do this after the widget so command isn't called on creation
         widget['command'] = command

+ 2 - 2
doc/SceneEditor/seParticleEffect.py

@@ -1,7 +1,7 @@
-from PandaModules import *
+from pandac.PandaModules import *
 import seParticles
 import seForceGroup
-import DirectNotifyGlobal
+from direct.directnotify import DirectNotifyGlobal
 
 class ParticleEffect(NodePath):
 

+ 9 - 9
doc/SceneEditor/seParticlePanel.py

@@ -1,15 +1,15 @@
 """PANDA3D Particle Panel"""
 
 # Import Tkinter, Pmw, and the floater code from this directory tree.
-from AppShell import *
-from TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.showbase.TkGlobal import *
 from tkFileDialog import *
 from tkSimpleDialog import askstring
 import os
-import Dial
-import Floater
-import Slider
-import VectorWidgets
+from direct.tkwidgets import Dial
+from direct.tkwidgets import Floater
+from direct.tkwidgets import Slider
+from direct.tkwidgets import VectorWidgets
 import sePlacer
 import seForceGroup
 import seParticles
@@ -48,16 +48,16 @@ class ParticlePanel(AppShell):
             pe = seParticleEffect.ParticleEffect('effect1', particles)
             self.particleEffect = pe
             self.emitter=loader.loadModel("sphere")
-            pe.reparentTo(self.emitter)
+            pe.reparentTo(self.emitter) 
             self.emitter.setName("effect1")
             self.emitter.reparentTo(render)
             pe.enable()
             messenger.send('ParticlePanel_Added_Effect',['effect1',pe,self.emitter])
             self.effectsDict[self.particleEffect.getName()]=self.particleEffect
-
+        
 
         messenger.send('SGE_Update Explorer',[render])
-
+        
         # Initialize application specific info
         AppShell.__init__(self)
 

+ 25 - 25
doc/SceneEditor/seParticles.py

@@ -1,31 +1,31 @@
-from PandaModules import *
-from ParticleManagerGlobal import *
-from PhysicsManagerGlobal import *
+from pandac.PandaModules import *
+from direct.particles.ParticleManagerGlobal import *
+from direct.showbase.PhysicsManagerGlobal import *
 
-import ParticleSystem
-import BaseParticleFactory
-import PointParticleFactory
-import ZSpinParticleFactory
+from pandac import ParticleSystem
+from pandac import BaseParticleFactory
+from pandac import PointParticleFactory
+from pandac import ZSpinParticleFactory
 #import OrientedParticleFactory
-import BaseParticleRenderer
-import PointParticleRenderer
-import LineParticleRenderer
-import GeomParticleRenderer
-import SparkleParticleRenderer
-import SpriteParticleRenderer
-import BaseParticleEmitter
-import BoxEmitter
-import DiscEmitter
-import LineEmitter
-import PointEmitter
-import RectangleEmitter
-import RingEmitter
-import SphereSurfaceEmitter
-import SphereVolumeEmitter
-import TangentRingEmitter
+from pandac import BaseParticleRenderer
+from pandac import PointParticleRenderer
+from pandac import LineParticleRenderer
+from pandac import GeomParticleRenderer
+from pandac import SparkleParticleRenderer
+from pandac import SpriteParticleRenderer
+from pandac import BaseParticleEmitter
+from pandac import BoxEmitter
+from pandac import DiscEmitter
+from pandac import LineEmitter
+from pandac import PointEmitter
+from pandac import RectangleEmitter
+from pandac import RingEmitter
+from pandac import SphereSurfaceEmitter
+from pandac import SphereVolumeEmitter
+from pandac import TangentRingEmitter
 import string
 import os
-import DirectNotifyGlobal
+from direct.directnotify import DirectNotifyGlobal
 import sys
 
 class Particles(ParticleSystem.ParticleSystem):
@@ -135,7 +135,7 @@ class Particles(ParticleSystem.ParticleSystem):
             npath = NodePath('default-geom')
             # This was moved here because we do not want to download
             # the direct tools with toontown.
-            import DirectSelection
+            from direct.directtools import DirectSelection
             bbox = DirectSelection.DirectBoundingBox(npath)
             self.renderer.setGeomNode(bbox.lines.node())
         elif (type == "SparkleParticleRenderer"):

+ 6 - 6
doc/SceneEditor/sePlacer.py

@@ -1,12 +1,12 @@
 """ DIRECT Nine DoF Manipulation Panel """
 
 # Import Tkinter, Pmw, and the dial code from this directory tree.
-from PandaObject import *
-from DirectGlobals import *
-from TkGlobal import *
-from AppShell import *
-import Dial
-import Floater
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectGlobals import *
+from direct.showbase.TkGlobal import *
+from direct.tkwidgets.AppShell import *
+from direct.tkwidgets import Dial
+from direct.tkwidgets import Floater
 """
 TODO:
 Task to monitor pose

+ 2 - 2
doc/SceneEditor/seSceneGraphExplorer.py

@@ -8,8 +8,8 @@
 # Do forget to check the seTree. 
 #
 #################################################################
-from PandaObject import *
-from TkGlobal import *
+from direct.showbase.PandaObject import *
+from direct.showbase.TkGlobal import *
 from seTree import *
 
 # changing these strings requires changing sceneEditor.py SGE_ strs too!

+ 12 - 9
doc/SceneEditor/seSelection.py

@@ -11,9 +11,9 @@
 # (If we do change original directools, it will force user has to install the latest version of OUR Panda)
 #
 #################################################################
-from PandaObject import *
-from DirectGlobals import *
-from DirectUtil import *
+from direct.showbase.PandaObject import *
+from direct.directtools.DirectGlobals import *
+from direct.directtools.DirectUtil import *
 from seGeometry import *
 from quad import *
 COA_ORIGIN = 0
@@ -483,12 +483,13 @@ class SelectionQueue(CollisionHandlerQueue):
         # If dot product of collision point surface normal and
         # ray from camera to collision point is positive, we are
         # looking at the backface of the polygon
-        if not entry.hasFromSurfaceNormal():
+        if not entry.hasSurfaceNormal():
             # Well, no way to tell.  Assume we're not backfacing.
             return 0
-        
-        v = Vec3(entry.getFromIntersectionPoint())
-        n = entry.getFromSurfaceNormal()
+
+        fromNodePath = entry.getFromNodePath()
+        v = Vec3(entry.getSurfacePoint(fromNodePath))
+        n = entry.getSurfaceNormal(fromNodePath)
         # Convert to camera space for backfacing test
         if self.collisionNodePath.getParent() != base.cam:
             # Problem: assumes base.cam is the camera in question
@@ -687,9 +688,10 @@ class SelectionSphere(SelectionQueue):
         # If dot product of collision point surface normal and
         # ray from sphere origin to collision point is positive, 
         # center is on the backside of the polygon
-        v = Vec3(entry.getFromIntersectionPoint() -
+        fromNodePath = entry.getFromNodePath()
+        v = Vec3(entry.getSurfacePoint(fromNodePath) -
                  entry.getFrom().getCenter())
-        n = entry.getFromSurfaceNormal()
+        n = entry.getSurfaceNormal(fromNodePath)
         # If points almost on top of each other, reject face
         # (treat as backfacing)
         if v.length() < 0.05:
@@ -698,6 +700,7 @@ class SelectionSphere(SelectionQueue):
         v.normalize()
         return v.dot(n) >= 0
 
+
     def pick(self, targetNodePath, skipFlags):
         self.ct.traverse( targetNodePath )
         self.sortEntries()

+ 2 - 2
doc/SceneEditor/seTree.py

@@ -15,8 +15,8 @@
 import os
 import sys
 import string
-from TkGlobal import *
-from PandaObject import *
+from direct.showbase.TkGlobal import *
+from direct.showbase.PandaObject import *
 
 # Initialize icon directory
 f = Filename('icons')

+ 8 - 8
dtool/Config.pp

@@ -33,7 +33,6 @@
 // designed to be easy to use as a macro language to generate
 // makefiles and their ilk.
 //
-
 // Some of the variables below are defined using the #define command,
 // and others are defined using #defer.  The two are very similar in
 // their purpose; the difference is that, if the variable definition
@@ -265,7 +264,7 @@
 // genPyCode.  You may wish to add to this list to add your own
 // libraries, or if you want to use some of the more obscure
 // interfaces like libpandaegg and libpandafx.
-#define GENPYCODE_LIBS libpandaexpress libpanda libpandaphysics libdirect
+#define GENPYCODE_LIBS libpandaexpress libpanda libpandaphysics libdirect libpandafx
 
 // Normally, Python source files are copied into the INSTALL_LIB_DIR
 // defined above, along with the compiled C++ library objects, when
@@ -385,8 +384,8 @@
 
 // Is Cg installed, and where?
 #if $[WINDOWS_PLATFORM]
-  #define CG_IPATH c:/Progra~1/Micros~1.NET/Vc7/include
-  #define CG_LPATH c:/Progra~1/Micros~1.NET/Vc7/lib
+  #define CG_IPATH 
+  #define CG_LPATH
   #define CG_LIBS cg.lib
 #else
   #define CG_IPATH
@@ -567,12 +566,13 @@
 // On Unix, freetype comes with the freetype-config executable, which
 // tells us where to look for the various files.  On Windows, we need to
 // supply this information explicitly.
-#define FREETYPE_CONFIG freetype-config
+#defer FREETYPE_CONFIG $[if $[not $[WINDOWS_PLATFORM]],freetype-config]
 #defer HAVE_FREETYPE $[or $[libtest $[FREETYPE_LPATH],$[FREETYPE_LIBS]],$[bintest $[FREETYPE_CONFIG]]]
-#define FREETYPE_CFLAGS
+
+#define FREETYPE_CFLAGS 
 #define FREETYPE_IPATH
-#define FREETYPE_LPATH
-#define FREETYPE_LIBS
+#define FREETYPE_LPATH 
+#define FREETYPE_LIBS 
 
 // Define this true to compile in a default font, so every TextNode
 // will always have a font available without requiring the user to

+ 18 - 0
dtool/pptempl/Global.nmake.pp

@@ -165,3 +165,21 @@
   #defer SHARED_LIB_C++ $[STATIC_LIB_C++]
   #defer ODIR_SHARED $[ODIR_STATIC]
 #endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 2 - 0
dtool/pptempl/Template.nmake.pp

@@ -1093,3 +1093,5 @@ $[TAB] xcopy /I/Y $[osfilename $[local]] $[osfilename $[dest]]
 //////////////////////////////////////////////////////////////////////
 #endif // DIR_TYPE
 
+
+

+ 1 - 3
dtool/src/parser-inc/Sources.pp

@@ -2,10 +2,8 @@
     algorithm deque ft2build.h hash_map hash_set iostream list map memory \
     pair queue set stack stdcompare.h stdtypedefs.h \
     string vector windows.h zlib.h files.h hex.h \
-    bits/pthreadtypes.h \
+    md5.h evp.h bits/pthreadtypes.h \
     openssl/md5.h openssl/evp.h openssl/rand.h openssl/ssl.h openssl/x509.h openssl/err.h \
     nurbs.hh stddef.h krb5.h MainHelix.h dllpath.h hxcom.h \
     hxcomm.h hxcore.h hxengin.h hxerror.h hxfiles.h hxtbuf.h \
     hxtbuff.h hxwin.h Python.h Cg/cg.h Cg/cgGL.h
-
-

+ 14 - 0
panda/metalibs/panda/Sources.pp

@@ -43,3 +43,17 @@
   #define SOURCES panda.cxx panda.h
   #define INSTALL_HEADERS panda.h
 #end metalib_target
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 5 - 4
panda/src/audio/audioManager.h

@@ -105,26 +105,27 @@ PUBLISHED:
   // this call may be for efficient on some implementations.
   virtual void stop_all_sounds() = 0;
 
+
   // Changes to the positions of 3D spacialized sounds and the listener
   // are all made at once when this method is called. It should be put
   // in the main program loop.
   virtual void audio_3d_update();
 
   // This controls the "set of ears" that listens to 3D spacialized sound
-  // px, py, pz are position coordinates.
-  // vx, vy, vz are a velocity vector in UNITS PER SECOND (default: meters).
+  // px, py, pz are position coordinates. 
+  // vx, vy, vz are a velocity vector in UNITS PER SECOND (default: meters). 
   // fx, fy and fz are the respective components of a unit forward-vector
   // ux, uy and uz are the respective components of a unit up-vector
   // These changes will NOT be invoked until audio_3d_update() is called.
   virtual void audio_3d_set_listener_attributes(float px, float py, float pz,
-                                                float vx, float vy, float vz, 
+                                                float vx, float vy, float vz,
                                                 float fx, float fy, float fz,
                                                 float ux, float uy, float uz);
   virtual void audio_3d_get_listener_attributes(float *px, float *py, float *pz,
                                                 float *vx, float *vy, float *vz,
                                                 float *fx, float *fy, float *fz,
                                                 float *ux, float *uy, float *uz);
-  
+ 
   // Control the "relative distance factor" for 3D spacialized audio. Default is 1.0
   // Fmod uses meters internally, so give a float in Units-per meter
   // Don't know what Miles uses.

+ 1 - 0
panda/src/audio/audioSound.h

@@ -103,6 +103,7 @@ PUBLISHED:
   virtual void get_3d_attributes(float *px, float *py, float *pz,
                                  float *vx, float *vy, float *vz);
 
+
   enum SoundStatus { BAD, READY, PLAYING };
   virtual SoundStatus status() const = 0;
 

+ 3 - 0
panda/src/audio/nullAudioManager.cxx

@@ -19,11 +19,13 @@
 
 #include "nullAudioManager.h"
 
+
 //namespace {
     //static const string blank="";
     //static float no_listener_attributes [] = {0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f};
 //}
 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NullAudioManager::NullAudioManager
 //       Access: 
@@ -277,3 +279,4 @@ audio_3d_get_drop_off_factor() const {
     // intentionally blank.
     return 0.0f;
 }
+

+ 1 - 0
panda/src/audio/nullAudioManager.h

@@ -72,6 +72,7 @@ public:
 
   virtual void audio_3d_set_drop_off_factor(float factor);
   virtual float audio_3d_get_drop_off_factor() const;
+
 };
 
 #endif /* __NULL_AUDIO_MANAGER_H__ */

+ 9 - 2
panda/src/audiotraits/fmodAudioManager.cxx

@@ -79,6 +79,7 @@ FmodAudioManager() {
         break;
       }
 
+
       // If the local system doesn't have enough hardware channels,
       // Don't even bother trying to use hardware effects. Play EVERYTHING in software.
       audio_debug("Setting minimum hardware channels(min="<<audio_min_hw_channels<<")");
@@ -222,6 +223,7 @@ get_sound(const string &file_name, bool positional) {
   // FMOD v4.0!
   FSOUND_STREAM *stream = NULL;
   int flags = FSOUND_LOADMEMORY | FSOUND_MPEGACCURATE;
+
   // 3D sounds have to be mono. Forcing stereo streams
   // to be mono will create a speed hit.
   if (positional) {
@@ -237,6 +239,7 @@ get_sound(const string &file_name, bool positional) {
   if (audio_output_channels == 1) {
       flags |= FSOUND_FORCEMONO;
   }
+
   string os_path = path.to_os_specific();
   string suffix = downcase(path.get_extension());
   
@@ -272,6 +275,7 @@ get_sound(const string &file_name, bool positional) {
   audio_debug("  returning 0x" << (void*)audioSound);
   nassertr(is_valid(), NULL);
   audio_debug("GOO!");
+
   return audioSound;
 }
 
@@ -726,6 +730,7 @@ float FmodAudioManager::
 audio_3d_get_drop_off_factor() const {
     audio_debug("FmodAudioManager::audio_3d_get_drop_off_factor()");
     return _drop_off_factor;
+
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -794,13 +799,15 @@ load(const Filename& filename, size_t &size) const {
   string suffix = downcase(filename.get_extension());
   bool bSupported = false;
   if (suffix == "wav" || suffix == "mp3" || suffix == "mid"
-      || suffix == "rmi" || suffix == "midi") {
+      || suffix == "rmi" || suffix == "midi"
+      || suffix == "mod" || suffix == "s3m" || suffix == "it"
+      || suffix == "ogg" || suffix == "aiff" || suffix == "wma") {
     bSupported = true;
   }
   if (!bSupported) {
     audio_error("FmodAudioManager::load: "<<filename
     <<" is not a supported file format.");
-    audio_error("Supported formats are: WAV, MP3, MIDI");
+    audio_error("Supported formats are: WAV, MP3, MIDI, OGG, AIFF, WMA, MODS");
     return NULL;
   }
 

+ 3 - 2
panda/src/audiotraits/fmodAudioSound.cxx

@@ -40,7 +40,7 @@
 //  Description: What happens when a sound ends (not reaches the end
 //               of a loop, but really ends).
 ////////////////////////////////////////////////////////////////////
-signed char
+signed char F_CALLBACKAPI
 pandaFmodFinishedCallback_Stream( FSOUND_STREAM *audio, void *buff, int len, void *p_sound ) {
     FmodAudioSound* sound = (FmodAudioSound*)p_sound;
     assert(sound); //sanity test
@@ -70,6 +70,7 @@ panda_Fmod_finished_callback( FSOUND_STREAM *audio, FmodAudioSound* sound ) {
 //       Access: 
 //  Description: constructor
 ////////////////////////////////////////////////////////////////////
+
 FmodAudioSound::
 FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data,
          string file_name, float length)
@@ -80,6 +81,7 @@ FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data,
   _vel[0] = 0.0f; _vel[1] = 0.0f; _vel[2] = 0.0f;
   nassertv(!file_name.empty());
   nassertv(audio_data != NULL);
+
   fmod_audio_debug("FmodAudioSound(manager="<<(void*)&manager
         <<", file_name="<<file_name<<")");
 }
@@ -142,7 +144,6 @@ if (_bExclusive) {
           audio_error("Unable to set 3d attributes for "<<_file_name<<"!");
       }
   }
-  
   // Set looping -- unimplemented
   
   // Unpause and set status to playing

+ 5 - 0
panda/src/audiotraits/fmodAudioSound.h

@@ -123,3 +123,8 @@ private:
 #endif //]
 
 #endif /* __FMOD_AUDIO_SOUND_H__ */
+
+
+
+
+

+ 1 - 1
panda/src/dxgsg9/dxgsg9base.h

@@ -41,7 +41,7 @@
 #include "pandabase.h"
 #include "graphicsWindow.h"
 
-#if D3D_SDK_VERSION != 31
+#if D3D_SDK_VERSION < 31
 #error you have DX 8.0/8.1 headers, not DX 9, you need to install DX 9 SDK!
 #endif
 

+ 1 - 0
panda/src/glstuff/Sources.pp

@@ -10,6 +10,7 @@
     gsgmisc gsgbase gobj display \
     putil linmath mathutil pnmimage \
     effects
+
     
   #define INSTALL_HEADERS \
      glext.h \

+ 5 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -38,7 +38,9 @@
 #include "colorWriteAttrib.h"
 #include "texMatrixAttrib.h"
 #include "texGenAttrib.h"
+#ifdef HAVE_CGGL
 #include "cgShaderAttrib.h"
+#endif
 #include "materialAttrib.h"
 #include "renderModeAttrib.h"
 #include "rescaleNormalAttrib.h"
@@ -2332,10 +2334,10 @@ issue_tex_matrix(const TexMatrixAttrib *attrib) {
 //               Also maintain the map of CgShader objects to
 //               respective GLCgShaderContexts
 ////////////////////////////////////////////////////////////////////
-
+#ifdef HAVE_CGGL
 void CLP(GraphicsStateGuardian)::
 issue_cg_shader_bind(const CgShaderAttrib *attrib) {
-#ifdef HAVE_CGGL
+
   if (attrib->is_off()) { //Current node has no shaders
     if (_cg_shader != (CgShader *) NULL) {
       _gl_cg_shader_contexts[_cg_shader]->un_bind();// Prev node had shaders
@@ -2359,9 +2361,8 @@ issue_cg_shader_bind(const CgShaderAttrib *attrib) {
       csc->bind(this);// Bind the new shader
     }
   }
-
-#endif
 }
+#endif
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GraphicsStateGuardian)::issue_tex_gen

+ 6 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -35,7 +35,9 @@
 #include "graphicsWindow.h"
 #include "pset.h"
 #include "pmap.h"
+#ifdef HAVE_CGGL
 #include "cgShader.h"
+#endif
 class PlaneNode;
 class Light;
 
@@ -120,9 +122,10 @@ public:
   virtual void issue_fog(const FogAttrib *attrib);
   virtual void issue_depth_offset(const DepthOffsetAttrib *attrib);
   virtual void issue_tex_gen(const TexGenAttrib *attrib);
+#ifdef HAVE_CGGL
   virtual void issue_cg_shader_bind(const CgShaderAttrib *attrib);
-
   //  virtual void issue_stencil(const StencilAttrib *attrib);
+#endif
 
   virtual void bind_light(PointLight *light_obj, const NodePath &light, 
                           int light_id);
@@ -315,3 +318,5 @@ private:
 };
 
 #include "glGraphicsStateGuardian_src.I"
+
+

+ 138 - 138
panda/src/helix/HelixClient.cxx

@@ -43,8 +43,8 @@ const int HelixClient::_guid_length = 64;
 // Return: None
 ////////////////////////////////////////////////////////////////////
 HelixClient::HelixClient() 
-: _engine(0),
-  _dll_access(0) {
+  : _engine(0),
+    _dll_access(0) {
   const char * envName = "PLAYER";
   char* envPath = getenv( envName );
   _dll_home = string(string(envPath) + "\\ExtLib\\HelixLib\\.");
@@ -63,7 +63,7 @@ HelixClient::HelixClient()
 // Return: None
 ////////////////////////////////////////////////////////////////////
 HelixClient::~HelixClient() {
- shutdown();
+  shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -93,7 +93,7 @@ void HelixClient::do_event() {
   // dirty so that it will be updated in memory.
   TEXTURES::iterator iter;
   for(iter = _textures.begin(); iter != _textures.end(); iter++) {
-      iter->second->mark_dirty(Texture::DF_image);
+    iter->second->mark_dirty(Texture::DF_image);
   }
 }
 
@@ -153,85 +153,85 @@ void HelixClient::create_player(const string &name, Texture* tex, bool sink_on)
   // instantiated, otherwise, players cannot be created!
   if (_engine != 0) {
 
-      // For now, check if there is an actual Panda texture present. If not, 
-      // then this player should not be created.
-
-      // NOTE: This portion of the interface must be redesigned as the current
-      // design forces the user to specify a valid texture. A more suitable
-      // approach would be to automatically generate a panda texture and allow
-      // the user to retreive that texture and set it for any piece of geometry
-      // within the world.
-      if( tex == 0 ) {
-          STDOUT("ERROR: HelixClient::CreatePlayer, INVALID Texture Object!\n");
-          STDOUT("ERROR: NO PLAYER CREATED!!\n");
-          return;
-      }
-
-      // Initialize necessary Helix pointers.
-      IHXPlayer* tmp_player = 0;
-      HxClientContext* context = 0;
-      IHXErrorSinkControl* controller = 0;
-      IHXErrorSink* error_sink = 0;
-
-      // Tell the texture object to keep the actual image buffer in memory. If
-      // the image buffer is deallocated, which is the default in panda, Helix
-      // and Panda because the engine will try to Blit to an invalid buffer.
-      tex->set_keep_ram_image(true);
-
-      // Try and create a valid helix player on the engine
-      if (HXR_OK != _engine->CreatePlayer(tmp_player)) {
-        STDOUT("ERROR: HelixClient::CreatePlayer, Failed Player Creation!\n");
-      }
-      else {
-        // Since a player has been successfully instantiated, a context
-        // for that player must be created.
-        context = new HxClientContext(_players.size());
-        if(context != 0) {
-          context->AddRef();
-
-          // Specify a default GUID. Not really necessary, but here for
-          // convenience if needed later on.
-          char guid[_guid_length + 1];
-          IHXPreferences * pref = 0;
-          guid[0] = '\0';
-
-          // Query the Preferences Interface for the player.
-          tmp_player->QueryInterface(IID_IHXPreferences, (void**)&pref);
-
-          // Send the Texture buffer down into the Context. It will then
-          // ship the buffer to the site supplier, where the actual site
-          // and surface are generated.
-          context->init(tmp_player, pref, guid, sink_on, tex);
-          tmp_player->SetClientContext(context);
-          HX_RELEASE(pref);
-
-          // Query the Error Sink Controller
-          tmp_player->QueryInterface(IID_IHXErrorSinkControl, (void**)&controller);
-          if(controller != 0) {
-            context->QueryInterface(IID_IHXErrorSink, (void**)&error_sink);
-            if(error_sink != 0) {
-                controller->AddErrorSink(error_sink, HXLOG_EMERG, HXLOG_INFO);
-            }
-            HX_RELEASE(error_sink);
-            error_sink = 0;
+    // For now, check if there is an actual Panda texture present. If not, 
+    // then this player should not be created.
+    
+    // NOTE: This portion of the interface must be redesigned as the current
+    // design forces the user to specify a valid texture. A more suitable
+    // approach would be to automatically generate a panda texture and allow
+    // the user to retreive that texture and set it for any piece of geometry
+    // within the world.
+    if( tex == 0 ) {
+      STDOUT("ERROR: HelixClient::CreatePlayer, INVALID Texture Object!\n");
+      STDOUT("ERROR: NO PLAYER CREATED!!\n");
+      return;
+    }
+    
+    // Initialize necessary Helix pointers.
+    IHXPlayer* tmp_player = 0;
+    HxClientContext* context = 0;
+    IHXErrorSinkControl* controller = 0;
+    IHXErrorSink* error_sink = 0;
+
+    // Tell the texture object to keep the actual image buffer in memory. If
+    // the image buffer is deallocated, which is the default in panda, Helix
+    // and Panda because the engine will try to Blit to an invalid buffer.
+    tex->set_keep_ram_image(true);
+
+    // Try and create a valid helix player on the engine
+    if (HXR_OK != _engine->CreatePlayer(tmp_player)) {
+      STDOUT("ERROR: HelixClient::CreatePlayer, Failed Player Creation!\n");
+    }
+    else {
+      // Since a player has been successfully instantiated, a context
+      // for that player must be created.
+      context = new HxClientContext(_players.size());
+      if(context != 0) {
+        context->AddRef();
+      
+        // Specify a default GUID. Not really necessary, but here for
+        // convenience if needed later on.
+        char guid[_guid_length + 1];
+        IHXPreferences * pref = 0;
+        guid[0] = '\0';
+
+        // Query the Preferences Interface for the player.
+        tmp_player->QueryInterface(IID_IHXPreferences, (void**)&pref);
+      
+        // Send the Texture buffer down into the Context. It will then
+        // ship the buffer to the site supplier, where the actual site
+        // and surface are generated.
+        context->init(tmp_player, pref, guid, sink_on, tex);
+        tmp_player->SetClientContext(context);
+        HX_RELEASE(pref);
+
+        // Query the Error Sink Controller
+        tmp_player->QueryInterface(IID_IHXErrorSinkControl, (void**)&controller);
+        if(controller != 0) {
+          context->QueryInterface(IID_IHXErrorSink, (void**)&error_sink);
+          if(error_sink != 0) {
+            controller->AddErrorSink(error_sink, HXLOG_EMERG, HXLOG_INFO);
           }
-          HX_RELEASE(controller);
-          controller = 0;
-          context = 0;
+          HX_RELEASE(error_sink);
+          error_sink = 0;
         }
+        HX_RELEASE(controller);
+        controller = 0;
+        context = 0;
+      }
 
-        // Create a new map object for the player and its respective texture.
-        pair<string, IHXPlayer*> player(name, tmp_player);
-        pair<string, PT(Texture)> texture(name, tex);
-
-        // Now that the pair has been created, set the tmp_player
-        // address to 0 to protect against dangling references.
-        tmp_player = 0;
+      // Create a new map object for the player and its respective texture.
+      pair<string, IHXPlayer*> player(name, tmp_player);
+      pair<string, PT(Texture)> texture(name, tex);
+    
+      // Now that the pair has been created, set the tmp_player
+      // address to 0 to protect against dangling references.
+      tmp_player = 0;
 
-        // Now, actually insert the pairs into their respective maps.
-        _players.insert(player);
-        _textures.insert(texture);
-      }
+      // Now, actually insert the pairs into their respective maps.
+      _players.insert(player);
+      _textures.insert(texture);
+    }
   }
   else {
     STDOUT("ERROR: In HelixClient::CreatePlayer, pEngine = NULL");
@@ -367,7 +367,7 @@ bool HelixClient::init() {
   // initialization of the engine.
   if((create_engine == 0) || (set_dll_access_path == 0)) {
     STDOUT("---{ERROR: HelixClient::Init, set_dll_access_path}---");
-
+    
     delete _dll_access;
     _dll_access = 0;
     return false;
@@ -390,11 +390,11 @@ bool HelixClient::init() {
   STDERR("Common DLL path %s\n", next_path );
   UINT32 bytes_to_copy = strlen(next_path) + 1;
   if (bytes_to_copy <= bytes_left)
-  {
-    memcpy(path_next_position, next_path, bytes_to_copy);
-    path_next_position += bytes_to_copy;
-    bytes_left -= bytes_to_copy;
-  }
+    {
+      memcpy(path_next_position, next_path, bytes_to_copy);
+      path_next_position += bytes_to_copy;
+      bytes_left -= bytes_to_copy;
+    }
 
   // Apply the Plug-in DLL Path to the paths string. For simplicity,
   // this is the same path as the clntcore.dll path.
@@ -403,25 +403,25 @@ bool HelixClient::init() {
   bytes_to_copy = strlen(next_path) + 1;
   
   if (bytes_to_copy <= bytes_left)
-  {
-    memcpy(path_next_position, next_path, bytes_to_copy); 
-    path_next_position += bytes_to_copy;
-    bytes_left -= bytes_to_copy;
-  }
+    {
+      memcpy(path_next_position, next_path, bytes_to_copy); 
+      path_next_position += bytes_to_copy;
+      bytes_left -= bytes_to_copy;
+    }
 
   // Apply the Codecs DLL Path to the paths string. For simplicity,
   // this is the same path as the clntcore.dll path.
   SafeSprintf(next_path, 256, "DT_Codecs=%s", _dll_home.c_str());
   bytes_to_copy = strlen(next_path) + 1;
   if (bytes_to_copy <= bytes_left)
-  {
-    memcpy(path_next_position, next_path, bytes_to_copy); 
-    path_next_position += bytes_to_copy;
-    bytes_left -= bytes_to_copy;
-    *path_next_position='\0';
-  }
-   STDOUT((char*)paths);
-   set_dll_access_path((char*)paths);
+    {
+      memcpy(path_next_position, next_path, bytes_to_copy); 
+      path_next_position += bytes_to_copy;
+      bytes_left -= bytes_to_copy;
+      *path_next_position='\0';
+    }
+  STDOUT((char*)paths);
+  set_dll_access_path((char*)paths);
   
   // The dll_access_path has been set, so the engine can now be initialized. If
   // this fails, then deallocate the DLLAccess object from memory and abort the
@@ -451,10 +451,10 @@ void HelixClient::shutdown() {
     // given Helix Engine.
     close_all_players();
     
-
+  
     // Retrieve the Function Pointer for closing the Helix engine.
     FPRMCLOSEENGINE close_engine = (FPRMCLOSEENGINE) _dll_access->getSymbol("CloseEngine");
-
+  
     // If the function pointer was successfully retrieved, close 
     // the helix engine.
     if (close_engine != 0) {
@@ -502,10 +502,10 @@ void HelixClient::begin(const string &name) {
     //UINT32 start_time = GetTickCount();
     //UINT32 end_time = start_time + _time_delta;
     //while(1) {
-     // do_events();
-      //curr_time = GetTickCount();
-      //if(curr_time >= end_time)
-       // break;
+    // do_events();
+    //curr_time = GetTickCount();
+    //if(curr_time >= end_time)
+    // break;
     //}
   }
 }
@@ -522,28 +522,28 @@ void HelixClient::begin(const string &name) {
 ////////////////////////////////////////////////////////////////////
 void HelixClient::begin_all() {
   if (_engine != 0) {
-
-      // Iterate through the _players map and call the Begin 
-      // routine to start playback of the media.
-      PLAYERS::iterator iter;
-      for(iter = _players.begin(); iter != _players.end(); iter++) {
-        iter->second->Begin();
-      } 
-
-      // This is legacy code from the test application, however, it
-      // was necessary for helix to function since do_events was called
-      // to give helix the necessary time-slice of the CPU. I think this
-      // most likely can be removed since Panda calls the necessary 
-      // Win32 API Message calls.
-//    UINT curr_time = 0;
-//    UINT32 start_time = GetTickCount();
-//      UINT32 end_time = start_time + _time_delta;
-//      while(1) {
-//        do_events();
-//        curr_time = GetTickCount();
-//        if (curr_time >= end_time)
- //         break;
-//      }
+    
+    // Iterate through the _players map and call the Begin 
+    // routine to start playback of the media.
+    PLAYERS::iterator iter;
+    for(iter = _players.begin(); iter != _players.end(); iter++) {
+      iter->second->Begin();
+    } 
+    
+    // This is legacy code from the test application, however, it
+    // was necessary for helix to function since do_events was called
+    // to give helix the necessary time-slice of the CPU. I think this
+    // most likely can be removed since Panda calls the necessary 
+    // Win32 API Message calls.
+    //    UINT curr_time = 0;
+    //    UINT32 start_time = GetTickCount();
+    //      UINT32 end_time = start_time + _time_delta;
+    //      while(1) {
+    //        do_events();
+    //        curr_time = GetTickCount();
+    //        if (curr_time >= end_time)
+    //         break;
+    //      }
   }
 }
 
@@ -581,12 +581,12 @@ void HelixClient::pause(const string &name) {
 ////////////////////////////////////////////////////////////////////
 void HelixClient::pause_all() {
   if (_engine != 0) {
-      // Iterate through the _players map and call the Pause 
-      // routine to start playback of the media.
-      PLAYERS::iterator iter;
-      for(iter = _players.begin(); iter != _players.end(); iter++) {
-        iter->second->Pause();
-      }
+    // Iterate through the _players map and call the Pause 
+    // routine to start playback of the media.
+    PLAYERS::iterator iter;
+    for(iter = _players.begin(); iter != _players.end(); iter++) {
+      iter->second->Pause();
+    }
   }
 }
 
@@ -650,12 +650,12 @@ void HelixClient::stop(const string &name) {
 ////////////////////////////////////////////////////////////////////
 void HelixClient::stop_all() {
   if (_engine != 0) {
-      // Iterate through the _players map and call the Pause 
-      // routine to stop playback of the media.
-      PLAYERS::iterator iter;
-      for(iter = _players.begin(); iter != _players.end(); iter++) {
-        iter->second->Stop();
-      }
+    // Iterate through the _players map and call the Pause 
+    // routine to stop playback of the media.
+    PLAYERS::iterator iter;
+    for(iter = _players.begin(); iter != _players.end(); iter++) {
+      iter->second->Stop();
+    }
   }
 }
 

+ 1 - 1
panda/src/helix/HelixClient.h

@@ -120,4 +120,4 @@ private:
   PLAYERS _players;
   TEXTURES _textures;
 }; 
-#endif
+#endif

+ 2 - 2
panda/src/helix/HxAdviseSink.cxx

@@ -337,7 +337,7 @@ void HxAdviseSink::get_all_statistics() {
           // Display source statistic
           get_statistics(RegistryName);
 
-
+          
           SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Stream%ld", RegistryName, StreamIndex);
           while (PT_COMPOSITE == _registry->GetTypeByName(RegistryName)) {
             // Display stream statistic
@@ -397,7 +397,7 @@ STDMETHODIMP HxAdviseSink::OnStatisticsChanged() {
 //  Return: HX_RESULT - result varies.
 ////////////////////////////////////////////////////////////////////
 HX_RESULT HxAdviseSink::dump_reg_tree(const char* tree_name) {
-  //Initialize Local Variables related to the Registry Tree
+  //Initialize Local Variables related to the Registry Tree 
   const char* pszName = NULL;
   ULONG32     ulRegID   = 0;
   HX_RESULT   res     = HXR_OK;

+ 1 - 1
panda/src/helix/HxAuthenticationManager.cxx

@@ -176,7 +176,7 @@ STDMETHODIMP HxAuthenticationManager::HandleAuthenticationRequest(IHXAuthenticat
     char      username[1024] = ""; /* Flawfinder: ignore */
     char      password[1024] = ""; /* Flawfinder: ignore */
     HX_RESULT res = HXR_FAIL;
-
+        
     if( !_sent_password )
     {
         res = HXR_OK;

+ 11 - 11
panda/src/helix/HxErrorSink.cxx

@@ -191,23 +191,23 @@ STDMETHODIMP HxErrorSink::ErrorOccurred(const UINT8 severity, const UINT32 hx_co
 }
 
 
-
-
-
-
-
-
-
-
-
-
+                                        
+                                        
+                                        
+                                        
+                                        
+                                        
+                                        
+                                        
+                                        
+                                        
 
 ////////////////////////////////////////////////////////////////////
 //  Member: HxErrorSink::ConvertErrorToText
 //  Access: Protected
 //  Purpose: Converts the Helix error code to text for the 
 //               client to display.
-////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////        
 //  Params: hx_code - the error code to be translated to text.
 //          buffer - Text buffer that holds the code.
 //          buffer_length - The length of the text buffer.

+ 2 - 2
panda/src/helix/HxErrorSink.h

@@ -52,8 +52,8 @@ public:
 //          be called when an error message is generated.
 ////////////////////////////////////////////////////////////////////
   STDMETHOD (ErrorOccurred) (THIS_ const UINT8 severity, const UINT32 hx_code,
-                                   const UINT32 user_code, const char* user_string,
-                                   const char* more_info_url);
+                             const UINT32 user_code, const char* user_string,
+                             const char* more_info_url);
 
 ////////////////////////////////////////////////////////////////////
 // IHUnkown Interface Methods Prototypes

+ 1 - 1
panda/src/helix/HxSiteSupplier.cxx

@@ -178,7 +178,7 @@ STDMETHODIMP HxSiteSupplier::SitesNeeded(UINT32 request_id, IHXValues*  pProps)
   if (HXR_OK != hres) {
     goto exit;
   }
-
+    
   // Figures out what type of site must be created.
   hres = pProps->GetPropertyCString("playto",pValue);
   if (HXR_OK == hres) {

+ 36 - 36
panda/src/helix/fivemmap.cxx

@@ -73,12 +73,12 @@ BOOL FiveMinuteMap::Lookup(void* Key, void*& Value) const
     // If Key is alrady in the list, replace value
     for (; nIndex < m_nMapSize; nIndex++)
     {
-    if (KeyArray[nIndex] == Key)
-    {
-        Value = ValueArray[nIndex];
-        bFound = TRUE;
-        goto exit;
-    }
+        if (KeyArray[nIndex] == Key)
+        {
+            Value = ValueArray[nIndex];
+            bFound = TRUE;
+            goto exit;
+        }
     }
 
 exit:
@@ -93,16 +93,16 @@ void FiveMinuteMap::RemoveKey(void* Key)
     // If Key is alrady in the list, replace value
     for (; nIndex < m_nMapSize; nIndex++)
     {
-    if (KeyArray[nIndex] == Key)
-    {
-        if (nIndex < (m_nMapSize-1))
+        if (KeyArray[nIndex] == Key)
         {
-        memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
-        memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+            if (nIndex < (m_nMapSize-1))
+            {
+                memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+                memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+            }
+            m_nMapSize--;
+            goto exit;
         }
-        m_nMapSize--;
-        goto exit;
-    }
     }
 
 exit:
@@ -117,16 +117,16 @@ void FiveMinuteMap::RemoveValue(void* Value)
     // If Value is alrady in the list, replace value
     for (; nIndex < m_nMapSize; nIndex++)
     {
-    if (ValueArray[nIndex] == Value)
-    {
-        if (nIndex < (m_nMapSize-1))
+        if (ValueArray[nIndex] == Value)
         {
-        memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
-        memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+            if (nIndex < (m_nMapSize-1))
+            {
+                memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+                memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
+            }
+            m_nMapSize--;
+            goto exit;
         }
-        m_nMapSize--;
-        goto exit;
-    }
     }
 
 exit:
@@ -141,28 +141,28 @@ void FiveMinuteMap::SetAt(void* Key, void* Value)
     // If Key is alrady in the list, replace value
     for (; nIndex < m_nMapSize; nIndex++)
     {
-    if (KeyArray[nIndex] == Key)
-    {
-        ValueArray[nIndex] = Value;
-        goto exit;
-    }
+        if (KeyArray[nIndex] == Key)
+        {
+            ValueArray[nIndex] = Value;
+            goto exit;
+        }
     }
 
     // If we have room, add it to the end!
     if (m_nAllocSize == m_nMapSize)
     {
-    m_nAllocSize += AllocationSize;
-    void** pNewKeys   = new void*[m_nAllocSize];
-    void** pNewValues = new void*[m_nAllocSize];
+        m_nAllocSize += AllocationSize;
+        void** pNewKeys   = new void*[m_nAllocSize];
+        void** pNewValues = new void*[m_nAllocSize];
 
-    memcpy(pNewKeys,KeyArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
-    memcpy(pNewValues,ValueArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
+        memcpy(pNewKeys,KeyArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
+        memcpy(pNewValues,ValueArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
 
-    delete [] KeyArray;
-    delete [] ValueArray;
+        delete [] KeyArray;
+        delete [] ValueArray;
 
-    KeyArray = pNewKeys;
-    ValueArray = pNewValues;
+        KeyArray = pNewKeys;
+        ValueArray = pNewValues;
     }
 
     KeyArray[m_nMapSize] = Key;

+ 10 - 10
panda/src/helix/fivemmap.h

@@ -55,19 +55,19 @@ class FiveMinuteMap {
     int     m_nCursor;
 public:
     FiveMinuteMap()
-    : KeyArray(NULL)
-    , ValueArray(NULL)
-    , m_nMapSize(0)
-    , m_nAllocSize(0)
+        : KeyArray(NULL)
+        , ValueArray(NULL)
+        , m_nMapSize(0)
+        , m_nAllocSize(0)
         , m_nCursor(0)
-    , AllocationSize(10)
-    {};
+        , AllocationSize(10)
+        {};
 
     ~FiveMinuteMap()
-    {
-        delete [] KeyArray;
-        delete [] ValueArray;
-    };
+        {
+            delete [] KeyArray;
+            delete [] ValueArray;
+        };
 
     int  GetCount() {return m_nMapSize;}
 

+ 0 - 16
panda/src/helix/main.cpp

@@ -44,19 +44,3 @@ int main( int argc, char *argv[] )
   
   return 0;
 }
-
-
-
-
-    
-
-
-
-
-
-
-
-
-
-
-  

+ 2 - 0
panda/src/testbed/Sources.pp

@@ -1,6 +1,8 @@
 #define OTHER_LIBS interrogatedb:c prc:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m pystub
 
+#define USE_PACKAGES fftw cg
+
 #define LOCAL_LIBS \
     framework putil collide pgraph chan text \
     pnmimage pnmimagetypes event effects gobj display \

+ 213 - 23
panda/src/windisplay/winGraphicsWindow.cxx

@@ -52,6 +52,27 @@ int WinGraphicsWindow::_window_class_index = 0;
 
 static const char * const errorbox_title = "Panda3D Error";
 
+////////////////////////////////////////////////////////////////////
+//
+// These static variables contain pointers to the Raw Input
+// functions, which are dynamically extracted from USER32.DLL
+//
+////////////////////////////////////////////////////////////////////
+
+typedef WINUSERAPI UINT (WINAPI *tGetRawInputDeviceList)
+  (OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
+typedef WINUSERAPI UINT(WINAPI *tGetRawInputData)
+  (IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize, IN UINT cbSizeHeader);
+typedef WINUSERAPI UINT(WINAPI *tGetRawInputDeviceInfoA)
+  (IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
+typedef WINUSERAPI BOOL (WINAPI *tRegisterRawInputDevices)
+  (IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
+
+static tGetRawInputDeviceList    pGetRawInputDeviceList;
+static tGetRawInputData          pGetRawInputData;
+static tGetRawInputDeviceInfoA   pGetRawInputDeviceInfoA;
+static tRegisterRawInputDevices  pRegisterRawInputDevices;
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::Constructor
 //       Access: Public
@@ -62,9 +83,7 @@ WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
                   const string &name) :
   GraphicsWindow(pipe, gsg, name) 
 {
-  GraphicsWindowInputDevice device =
-  GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
-  _input_devices.push_back(device);
+  initialize_input_devices();
   _hWnd = (HWND)0;
   _ime_open = false;
   _ime_active = false;
@@ -391,9 +410,99 @@ open_window() {
   //     characters.  This is only available under Windows NT; it is
   //     stubbed out in Windows 95/98/Me.
 
+  // Registers to receive the WM_INPUT messages
+  if ((pRegisterRawInputDevices)&&(_input_devices.size() > 1)) {
+    RAWINPUTDEVICE Rid;
+    Rid.usUsagePage = 0x01; 
+    Rid.usUsage = 0x02; 
+    Rid.dwFlags = 0;// RIDEV_NOLEGACY;   // adds HID mouse and also ignores legacy mouse messages
+    Rid.hwndTarget = _hWnd;
+    pRegisterRawInputDevices(&Rid, 1, sizeof (Rid));
+  }
+  
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::initialize_input_devices
+//       Access: Private
+//  Description: Creates the array of input devices.  The first
+//               one is always the system mouse and keyboard.
+//               Each subsequent one is a raw mouse device. Also
+//               initializes a parallel array, _input_device_handle,
+//               with the win32 handle of each raw input device.
+////////////////////////////////////////////////////////////////////
+
+void WinGraphicsWindow::
+initialize_input_devices() {
+  UINT nInputDevices;
+  PRAWINPUTDEVICELIST pRawInputDeviceList;
+
+  nassertv(_input_devices.size() == 0);
+  
+  // Clear the handle array, and set up the system keyboard/mouse
+  memset(_input_device_handle, 0, sizeof(_input_device_handle));
+  GraphicsWindowInputDevice device =
+    GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
+  _input_devices.push_back(device);
+  
+  // Try initializing the Raw Input function pointers.
+  if (pRegisterRawInputDevices==0) {
+    HMODULE user32 = LoadLibrary("user32.dll");
+    if (user32) {
+      pRegisterRawInputDevices = (tRegisterRawInputDevices)GetProcAddress(user32,"RegisterRawInputDevices");
+      pGetRawInputDeviceList   = (tGetRawInputDeviceList)  GetProcAddress(user32,"GetRawInputDeviceList");
+      pGetRawInputDeviceInfoA  = (tGetRawInputDeviceInfoA) GetProcAddress(user32,"GetRawInputDeviceInfoA");
+      pGetRawInputData         = (tGetRawInputData)        GetProcAddress(user32,"GetRawInputData");
+    }
+  }
+  
+  if (pRegisterRawInputDevices==0) return;
+  if (pGetRawInputDeviceList==0) return;
+  if (pGetRawInputDeviceInfoA==0) return;
+  if (pGetRawInputData==0) return;
+
+  // Get the number of devices.
+  if (pGetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0)
+    return;
+  
+  // Allocate the array to hold the DeviceList
+  pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(sizeof(RAWINPUTDEVICELIST) * nInputDevices);
+  if (pRawInputDeviceList==0) return;
+
+  // Fill the Array
+  if (pGetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1)
+    return;
+  
+  // Loop through all raw devices and find the raw mice
+  for (int i = 0; i < (int)nInputDevices; i++) {
+    if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) {
+      // Fetch information about specified mouse device.
+      UINT nSize;
+      if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)0, &nSize) != 0)
+        return;
+      char *psName = (char*)alloca(sizeof(TCHAR) * nSize);
+      if (psName == 0) return;
+      if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0)
+        return;
+
+      // If it's not an RDP mouse, add it to the list of raw mice.
+      if (strncmp(psName,"\\??\\Root#RDP_MOU#0000#",22)!=0) {
+        if (_input_devices.size() < 32) {
+          if (strncmp(psName,"\\??\\",4)==0) psName += 4;
+          char *pound1 = strchr(psName,'#');
+          char *pound2 = pound1 ? strchr(pound1+1,'#') : 0;
+          if (pound2) *pound2 = 0;
+          _input_device_handle[_input_devices.size()] = pRawInputDeviceList[i].hDevice;
+          GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_only(psName);
+          device.set_pointer_in_window(0,0);
+          _input_devices.push_back(device);
+        }
+      }
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::fullscreen_minimized
 //       Access: Protected, Virtual
@@ -856,6 +965,10 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
             return 0;
         break;
     
+      case WM_INPUT:
+        handle_raw_input((HRAWINPUT)lparam);
+        break;
+      
       case WM_MOUSELEAVE:
         _tracking_mouse_leaving = false;
         handle_mouse_exit();
@@ -949,43 +1062,54 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
         break;
     
       case WM_LBUTTONDOWN:
-        button = 0;
-        // fall through
+        if (_lost_keypresses) {
+          resend_lost_keypresses();
+        }
+        SetCapture(hwnd);
+        _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+        _input_devices[0].button_down(MouseButton::button(0), get_message_time());
+        break;
+        
       case WM_MBUTTONDOWN:
-        if (button < 0) {
-          button = 1;
+        if (_lost_keypresses) {
+          resend_lost_keypresses();
         }
-        // fall through
+        SetCapture(hwnd);
+        _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+        _input_devices[0].button_down(MouseButton::button(1), get_message_time());
+        break;
+
       case WM_RBUTTONDOWN:
         if (_lost_keypresses) {
           resend_lost_keypresses();
         }
-        if (button < 0) {
-          button = 2;
-        }
         SetCapture(hwnd);
-        handle_keypress(MouseButton::button(button), 
-                        translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)),
-                        get_message_time());
+        _input_devices[0].set_pointer_in_window(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
+        _input_devices[0].button_down(MouseButton::button(2), get_message_time());
         break;
     
       case WM_LBUTTONUP:
-        button = 0;
-        // fall through
+        if (_lost_keypresses) {
+          resend_lost_keypresses();
+        }
+        ReleaseCapture();
+        _input_devices[0].button_up(MouseButton::button(0), get_message_time());
+        break;
+
       case WM_MBUTTONUP:
-        if (button < 0) {
-          button = 1;
+        if (_lost_keypresses) {
+          resend_lost_keypresses();
         }
-        // fall through
+        ReleaseCapture();
+        _input_devices[0].button_up(MouseButton::button(1), get_message_time());
+        break;
+
       case WM_RBUTTONUP:
         if (_lost_keypresses) {
           resend_lost_keypresses();
         }
-        if (button < 0) {
-          button = 2;
-        }
         ReleaseCapture();
-        handle_keyrelease(MouseButton::button(button), get_message_time());
+        _input_devices[0].button_up(MouseButton::button(2), get_message_time());
         break;
 
       case WM_MOUSEWHEEL:
@@ -1784,6 +1908,72 @@ lookup_key(WPARAM wparam) const {
   return ButtonHandle::none();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WinGraphicsWindow::handle_raw_input
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+void WinGraphicsWindow::
+handle_raw_input(HRAWINPUT hraw) {
+  LPBYTE lpb;
+  UINT dwSize;
+
+  if (hraw == 0) {
+    return;
+  }
+  if (pGetRawInputData(hraw, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) {
+    return;
+  }
+  
+  lpb = (LPBYTE)alloca(sizeof(LPBYTE) * dwSize);
+  if (lpb == NULL) {
+    return;
+  }
+  
+  if (pGetRawInputData(hraw, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {
+    return;
+  }
+  
+  RAWINPUT *raw = (RAWINPUT *)lpb;
+  if (raw->header.hDevice == 0) {
+    return;
+  }
+  
+  for (int i = 1; i < (int)(_input_devices.size()); i++) {
+    if (_input_device_handle[i] == raw->header.hDevice) {
+      int adjx = raw->data.mouse.lLastX;
+      int adjy = raw->data.mouse.lLastY;
+      
+      if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
+        _input_devices[i].set_pointer_in_window(adjx, adjy);
+      } else {
+        int oldx = _input_devices[i].get_pointer().get_x();
+        int oldy = _input_devices[i].get_pointer().get_y();
+        _input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy);
+      }
+      
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) {
+        _input_devices[i].button_down(MouseButton::button(0), get_message_time());
+      }
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) {
+        _input_devices[i].button_up(MouseButton::button(0), get_message_time());
+      }
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) {
+        _input_devices[i].button_down(MouseButton::button(2), get_message_time());
+      }
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) {
+        _input_devices[i].button_up(MouseButton::button(2), get_message_time());
+      }
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) {
+        _input_devices[i].button_down(MouseButton::button(1), get_message_time());
+      }
+      if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) {
+        _input_devices[i].button_up(MouseButton::button(1), get_message_time());
+      }
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WinGraphicsWindow::handle_mouse_motion
 //       Access: Private

+ 4 - 1
panda/src/windisplay/winGraphicsWindow.h

@@ -84,7 +84,8 @@ private:
   void adjust_z_order();
   void adjust_z_order(WindowProperties::ZOrder last_z_order,
                       WindowProperties::ZOrder this_z_order);
-
+  void initialize_input_devices();
+  void handle_raw_input(HRAWINPUT hraw);
   void track_mouse_leaving(HWND hwnd);
 
   static void process_1_event();
@@ -117,6 +118,8 @@ private:
   bool _ime_composition_w;
   bool _tracking_mouse_leaving;
   bool _maximized;
+  bool _bCursor_in_WindowClientArea;
+  HANDLE _input_device_handle[32];
   HCURSOR _cursor;
   DEVMODE _fullscreen_display_mode;
 

+ 2 - 0
pandatool/src/bam/Sources.pp

@@ -1,3 +1,5 @@
+#define USE_PACKAGES fftw
+
 #begin bin_target
   #define TARGET bam-info
   #define LOCAL_LIBS \

+ 1 - 0
pandatool/src/dxfprogs/Sources.pp

@@ -1,4 +1,5 @@
 #define UNIX_SYS_LIBS m
+#define USE_PACKAGES fftw
 
 #begin bin_target
   #define TARGET dxf-points

+ 1 - 1
pandatool/src/mayaprogs/mayaSavePview.h

@@ -31,7 +31,7 @@
 
 // This will ask Maya 5.0 or better to use the new <iostream> library
 // instead of the old <iostream.h> library.
-#define REQUIRE_IOSTREAM
+#define REQUIRE_IOSTREAM 1
 
 #include <maya/MArgList.h>
 #include <maya/MPxCommand.h>