foundations for level editor: entity attrib modification

This commit is contained in:
Darren Ranalli 2003-09-15 23:10:11 +00:00
parent 122b4b778c
commit e78cd9f6b3
6 changed files with 68 additions and 44 deletions

View File

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

View File

@ -107,3 +107,14 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
self.destroyLevel() self.destroyLevel()
DistributedObjectAI.DistributedObjectAI.delete(self) 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)

View File

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

View File

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

View File

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

View File

@ -69,34 +69,13 @@ class LevelBase:
for key,value in spec.items(): for key,value in spec.items():
if key in ('type', 'name', 'comment',): if key in ('type', 'name', 'comment',):
continue continue
if hasattr(entity, key): entity.setAttribInit(key, value)
self.notify.warning('entity %s (%s) already has member %s' %
(entId, spec['type'], key))
entity.__dict__[key] = value
# entity is initialized, add it to the list of entities # entity is initialized, add it to the list of entities
self.entities[entity.entId] = entity self.entities[entity.entId] = entity
# send the create event # send the create event
messenger.send(self.getEntityCreateEvent(entity.entId)) 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): def getEntityCreateEvent(self, entId):
"""This is the event that is thrown immediately after an entity """This is the event that is thrown immediately after an entity
is initialized""" is initialized"""