Bläddra i källkod

foundations for level editor: entity attrib modification

Darren Ranalli 22 år sedan
förälder
incheckning
e78cd9f6b3

+ 0 - 1
direct/src/level/DistributedLevel.py

@@ -265,7 +265,6 @@ class DistributedLevel(DistributedObject.DistributedObject,
         # if no viz, listen to all the zones
         if not DistributedLevel.WantVisibility:
             zones = list(self.zoneNums)
-            #zones.remove(0)
             self.sendSetZone(0, zones)
 
     def toonEnterZone(self, zoneNum):

+ 11 - 0
direct/src/level/DistributedLevelAI.py

@@ -107,3 +107,14 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
         self.destroyLevel()
 
         DistributedObjectAI.DistributedObjectAI.delete(self)
+
+    if __debug__:
+        # level editors should call this func to tweak attributes of level
+        # entities
+        def setAttribChange(self, entId, attribName, value):
+            # send a copy to the client-side level obj
+            self.sendUpdate('setAttribChange',
+                            [entId, attribName, repr(value)])
+            
+            entity = self.getEntity(entId)
+            entity.handleAttribChange(attribName, value)

+ 54 - 19
direct/src/level/Entity.py

@@ -1,10 +1,13 @@
 """Entity.py: contains the Entity class"""
 
 import string
+import DirectNotifyGlobal
+from PythonUtil import lineInfo
 
 class Entity:
     """Entity is the base class for all objects that exist in a Level
     and can be edited with the LevelEditor."""
+    notify = DirectNotifyGlobal.directNotify.newCategory('Entity')
 
     # these are values that can be changed in the level editor
     Attribs = (
@@ -22,6 +25,9 @@ class Entity:
         if attribs is not None:
             self.attribs.update(attribs)
 
+    def __str__(self):
+        return 'ent%s(%s)' % (self.entId, self.level.getEntityType(self.entId))
+    
     def initializeEntity(self):
         """Call this once on initialization to set this entity's
         spec data"""
@@ -36,33 +42,62 @@ class Entity:
             return getattr(self, setFuncName)
         return None
 
-    def callSetters(self, *attribs):
-        """call this with a list of attribs, and any that exist on the
-        entity and have setters will be passed to their setter"""
+    def privCallSetters(self, doDelete, *attribs):
+        """common implementation of callSetters and callSettersAndDelete"""
         for attrib in attribs:
             if hasattr(self, attrib):
                 setter = self.privGetSetter(attrib)
                 if setter is not None:
-                    setter(getattr(self, attrib))
+                    value = getattr(self, attrib)
+                    if doDelete:
+                        delattr(self, attrib)
+                    setter(value)
+
+    def callSetters(self, *attribs):
+        """call this with a list of attribs, and any that exist on the
+        entity and have setters will be passed to their setter"""
+        self.privCallSetters(0, *attribs)
 
-    def attribChanged(self):
-        """This is called when a parameter is tweaked and no setter
-        is called; i.e. the value is set directly on the object.
-        Some Entities might want to completely reset every time anything
-        is tweaked; this is the place to do it; override this func in your
-        derived class
-        """
-        pass
+    def callSettersAndDelete(self, *attribs):
+        """same as callSetters, but also removes attribs from entity"""
+        self.privCallSetters(1, *attribs)
 
-    def getAttribInfo(self):
-        return self.attribs
+    # this will be called with each item of our spec data on initialization
+    def setAttribInit(self, attrib, value):
+        if hasattr(self, attrib):
+            Entity.notify.warning('%s already has member %s in %s' %
+                                  (self, attrib, lineInfo()[2]))
+        # TODO: we should probably put this crep in a dictionary
+        # rather than dump it into the entity's namespace
+        self.__dict__[attrib] = value
 
-    def privTweak(self, name, value):
-        self.__dict__[name] = value
+    if __debug__:
+        # support for level editing
+        def handleAttribChange(self, attrib, value):
+            # call callback function if it exists
+            # otherwise set attrib directly and call notify func
+            setter = self.privGetSetter(attrib)
+            if setter is not None:
+                # call the setter
+                setter(value)
+            else:
+                # set the attrib directly
+                self.__dict__[attrib] = value
+                # and call the notify func
+                self.attribChanged(attrib)
+
+        def attribChanged(self, attrib):
+            """This is called when a parameter is tweaked and no setter
+            is called; i.e. the value is set directly on the object.
+            Some Entities might want to completely reset every time anything
+            is tweaked; this is the place to do it, just override this func
+            in your derived class
+            """
+            pass
+
+        def getAttribInfo(self):
+            return self.attribs
 
-    def __str__(self):
-        return 'ent%s(%s)' % (self.entId, self.level.getEntityType(self.entId))
-    
     if __debug__:
         def debugPrint(self, message):
             """for debugging"""

+ 1 - 1
direct/src/level/EntityCreator.py

@@ -37,6 +37,6 @@ class EntityCreator:
     def createEntity(self, entType, level, entId):
         if not self.entType2Ctor.has_key(entType):
             EntityCreator.notify.warning(
-                'createEntity(entType=%s) not found' % entType)
+                'createEntity(entType=%s): entType not found' % entType)
             return None
         return self.entType2Ctor[entType](level, entId)

+ 1 - 1
direct/src/level/EntityCreatorAI.py

@@ -48,7 +48,7 @@ class EntityCreatorAI:
         if not self.entType2Ctor.has_key(entType):
             EntityCreatorAI.notify.warning(
                 'createEntity(entType=%s, levelDoId=%s, '
-                'entId=%s, zoneId=%s) not found' %
+                'entId=%s, zoneId=%s): entType not found' %
                 (entType, levelDoId, entId, zoneId))
             return None
 

+ 1 - 22
direct/src/level/LevelBase.py

@@ -69,34 +69,13 @@ class LevelBase:
         for key,value in spec.items():
             if key in ('type', 'name', 'comment',):
                 continue
-            if hasattr(entity, key):
-                self.notify.warning('entity %s (%s) already has member %s' %
-                                    (entId, spec['type'], key))
-            entity.__dict__[key] = value
+            entity.setAttribInit(key, value)
 
         # entity is initialized, add it to the list of entities
         self.entities[entity.entId] = entity
         # send the create event
         messenger.send(self.getEntityCreateEvent(entity.entId))
 
-        """
-        # set items directly on entity, or call callback functions...
-        for key,value in spec.items():
-            # filter out some entries; we might want to restructure the
-            # spec data into different categories of properties instead
-            # of filtering them here
-            if key in ('type', 'name', 'comment', 'zone',):
-                continue
-            setFuncName = 'set%s%s' % (string.upper(key[0]), key[1:])
-            if hasattr(entity, setFuncName):
-                # call the setter
-                func = getattr(entity, setFuncName)
-                func(value)
-            else:
-                # set the param directly on the object
-                entity.__dict__[key] = value
-                """
-
     def getEntityCreateEvent(self, entId):
         """This is the event that is thrown immediately after an entity
         is initialized"""