mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
code reorg; handling of dynamic zone entity creation and deletion
This commit is contained in:
parent
d62dc09acf
commit
4b4c1e3a62
@ -40,7 +40,7 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||||||
# all our entities at that time.
|
# all our entities at that time.
|
||||||
toonbase.tcr.timeManager.synchronize('DistributedLevel.generate')
|
toonbase.tcr.timeManager.synchronize('DistributedLevel.generate')
|
||||||
|
|
||||||
# required fields (these ought to be required fields, but
|
# "required" fields (these ought to be required fields, but
|
||||||
# the AI level obj doesn't know the data values until it has been
|
# the AI level obj doesn't know the data values until it has been
|
||||||
# generated.)
|
# generated.)
|
||||||
def setZoneIds(self, zoneIds):
|
def setZoneIds(self, zoneIds):
|
||||||
@ -92,8 +92,6 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||||||
# similar handlers in base classes
|
# similar handlers in base classes
|
||||||
if entType == 'levelMgr':
|
if entType == 'levelMgr':
|
||||||
self.__handleLevelMgrCreated()
|
self.__handleLevelMgrCreated()
|
||||||
elif entType == 'zone':
|
|
||||||
self.__handleAllZonesCreated()
|
|
||||||
|
|
||||||
def __handleLevelMgrCreated(self):
|
def __handleLevelMgrCreated(self):
|
||||||
# as soon as the levelMgr has been created, load up the model
|
# as soon as the levelMgr has been created, load up the model
|
||||||
@ -129,20 +127,9 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||||||
self.zoneNums.sort()
|
self.zoneNums.sort()
|
||||||
self.notify.debug('zones: %s' % self.zoneNums)
|
self.notify.debug('zones: %s' % self.zoneNums)
|
||||||
|
|
||||||
# hack in another doorway
|
# fix up the floor collisions for walkable zones *before*
|
||||||
dw = self.geom.attachNewNode('Doorway27')
|
|
||||||
dw.setPos(-49.4,86.7,19.26)
|
|
||||||
dw.setH(0)
|
|
||||||
|
|
||||||
# find the doorway nodes
|
|
||||||
self.doorwayNum2Node = findNumberedNodes('Doorway')
|
|
||||||
|
|
||||||
def __handleAllZonesCreated(self):
|
|
||||||
# fix up the floor collisions for walkable zones before
|
|
||||||
# any entities get put under the model
|
# any entities get put under the model
|
||||||
for zoneNum in self.zoneNums:
|
for zoneNum,zoneNode in self.zoneNum2node.items():
|
||||||
zoneNode = self.zoneNum2node[zoneNum]
|
|
||||||
|
|
||||||
# if this is a walkable zone, fix up the model
|
# if this is a walkable zone, fix up the model
|
||||||
allColls = zoneNode.findAllMatches('**/+CollisionNode').asList()
|
allColls = zoneNode.findAllMatches('**/+CollisionNode').asList()
|
||||||
# which of them, if any, are floors?
|
# which of them, if any, are floors?
|
||||||
@ -170,6 +157,14 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||||||
self.toonEnterZone(zoneNum)
|
self.toonEnterZone(zoneNum)
|
||||||
self.accept('enter%s' % floorCollName, handleZoneEnter)
|
self.accept('enter%s' % floorCollName, handleZoneEnter)
|
||||||
|
|
||||||
|
# hack in another doorway
|
||||||
|
dw = self.geom.attachNewNode('Doorway27')
|
||||||
|
dw.setPos(-49.4,86.7,19.26)
|
||||||
|
dw.setH(0)
|
||||||
|
|
||||||
|
# find the doorway nodes
|
||||||
|
self.doorwayNum2Node = findNumberedNodes('Doorway')
|
||||||
|
|
||||||
def announceGenerate(self):
|
def announceGenerate(self):
|
||||||
self.notify.debug('announceGenerate')
|
self.notify.debug('announceGenerate')
|
||||||
DistributedObject.DistributedObject.announceGenerate(self)
|
DistributedObject.DistributedObject.announceGenerate(self)
|
||||||
@ -270,7 +265,9 @@ 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:
|
||||||
self.setVisibility(self.zoneNums)
|
zoneNums = list(self.zoneNums)
|
||||||
|
zoneNums.remove(Level.Level.uberZoneNum)
|
||||||
|
self.setVisibility(zoneNums)
|
||||||
|
|
||||||
def toonEnterZone(self, zoneNum):
|
def toonEnterZone(self, zoneNum):
|
||||||
self.notify.debug('toonEnterZone%s' % zoneNum)
|
self.notify.debug('toonEnterZone%s' % zoneNum)
|
||||||
@ -328,7 +325,7 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||||||
# accepts list of visible zone numbers
|
# accepts list of visible zone numbers
|
||||||
# convert the zone numbers into their actual zoneIds
|
# convert the zone numbers into their actual zoneIds
|
||||||
# always include Toontown and factory uberZones
|
# always include Toontown and factory uberZones
|
||||||
factoryUberZone = self.getZoneId(zoneNum=0)
|
factoryUberZone = self.getZoneId(zoneNum=Level.Level.UberZoneNum)
|
||||||
visibleZoneIds = [ToontownGlobals.UberZone, factoryUberZone]
|
visibleZoneIds = [ToontownGlobals.UberZone, factoryUberZone]
|
||||||
for vz in vizList:
|
for vz in vizList:
|
||||||
visibleZoneIds.append(self.getZoneId(zoneNum=vz))
|
visibleZoneIds.append(self.getZoneId(zoneNum=vz))
|
||||||
|
@ -30,11 +30,6 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
|||||||
def delete(self):
|
def delete(self):
|
||||||
self.notify.debug('delete')
|
self.notify.debug('delete')
|
||||||
self.destroyLevel()
|
self.destroyLevel()
|
||||||
|
|
||||||
# we do not allocate the uberZone for now, so don't deallocate it
|
|
||||||
for zoneId in self.zoneIds[1:]:
|
|
||||||
self.air.deallocateZone(zoneId)
|
|
||||||
|
|
||||||
DistributedObjectAI.DistributedObjectAI.delete(self)
|
DistributedObjectAI.DistributedObjectAI.delete(self)
|
||||||
|
|
||||||
def initializeLevel(self, spec):
|
def initializeLevel(self, spec):
|
||||||
@ -48,9 +43,6 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
|||||||
scenario = wc.choose()
|
scenario = wc.choose()
|
||||||
scenarioIndex = spec['scenarios'].index(scenario)
|
scenarioIndex = spec['scenarios'].index(scenario)
|
||||||
|
|
||||||
# this will hold the network zoneIds that we allocate
|
|
||||||
self.zoneIds = [self.uberZoneId]
|
|
||||||
|
|
||||||
Level.Level.initializeLevel(self, self.doId,
|
Level.Level.initializeLevel(self, self.doId,
|
||||||
spec, scenarioIndex)
|
spec, scenarioIndex)
|
||||||
|
|
||||||
@ -59,30 +51,23 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
|||||||
Inheritors, override if desired."""
|
Inheritors, override if desired."""
|
||||||
return EntityCreatorAI.EntityCreatorAI(self.air, level=self)
|
return EntityCreatorAI.EntityCreatorAI(self.air, level=self)
|
||||||
|
|
||||||
def allocateZoneId(self):
|
|
||||||
# set aside a zoneId for each zone; this is called by ZoneEntityAI
|
|
||||||
# there is error checking in air.allocateZone
|
|
||||||
self.zoneIds.append(self.air.allocateZone())
|
|
||||||
|
|
||||||
def getEntityZoneId(self, entId):
|
def getEntityZoneId(self, entId):
|
||||||
"""figure out what network zoneId an entity is in"""
|
"""figure out what network zoneId an entity is in"""
|
||||||
# TODO: where should the zone info come from? It could come
|
|
||||||
# from the 'parent' scene-graph info... but what about intangible
|
|
||||||
# distributed objects? I guess if they don't inherit from
|
|
||||||
# NodePathEntity et al, they'll just have an unused 'parent'
|
|
||||||
# attribute hanging around, which isn't the end of the world...
|
|
||||||
|
|
||||||
# this func is called before the entity has been created; look
|
# this func is called before the entity has been created; look
|
||||||
# into the spec data, since we can't get a handle on the object itself
|
# into the spec data, since we can't yet get a handle on the
|
||||||
|
# object itself at this point
|
||||||
spec = self.entId2spec[entId]
|
spec = self.entId2spec[entId]
|
||||||
type = spec['type']
|
type = spec['type']
|
||||||
if type == 'zone':
|
if type == 'zone':
|
||||||
if not hasattr(self, 'zoneNum2zoneId'):
|
if not hasattr(self, 'zoneNum2zoneId'):
|
||||||
# we haven't even created our zone entities yet;
|
# we haven't even started creating our zone entities yet;
|
||||||
# we have no idea yet which zoneNums map to which
|
# we have no idea yet which zoneNums map to which
|
||||||
# network zoneIds. just return None.
|
# network zoneIds. just return None.
|
||||||
return None
|
return None
|
||||||
return self.zoneNum2zoneId[spec['modelZoneNum']]
|
# If the entity *is* the zone, it will not yet be in the
|
||||||
|
# table; but since zone entities are currently not distributed,
|
||||||
|
# it's fine to return None.
|
||||||
|
return self.zoneNum2zoneId.get(spec['modelZoneNum'])
|
||||||
if not spec.has_key('parent'):
|
if not spec.has_key('parent'):
|
||||||
return None
|
return None
|
||||||
return self.getEntityZoneId(spec['parent'])
|
return self.getEntityZoneId(spec['parent'])
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
"""Entity.py: contains the Entity class"""
|
"""Entity.py: contains the Entity class"""
|
||||||
|
|
||||||
|
from DirectObject import *
|
||||||
|
from PythonUtil import lineInfo
|
||||||
import string
|
import string
|
||||||
import DirectNotifyGlobal
|
import DirectNotifyGlobal
|
||||||
from PythonUtil import lineInfo
|
|
||||||
|
|
||||||
class Entity:
|
class Entity(DirectObject):
|
||||||
"""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')
|
notify = DirectNotifyGlobal.directNotify.newCategory('Entity')
|
||||||
@ -32,6 +33,7 @@ class Entity:
|
|||||||
return 'ent%s(%s)' % (self.entId, self.level.getEntityType(self.entId))
|
return 'ent%s(%s)' % (self.entId, self.level.getEntityType(self.entId))
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
|
self.level.onEntityDestroy(self.entId)
|
||||||
del self.level
|
del self.level
|
||||||
|
|
||||||
def privGetSetter(self, attrib):
|
def privGetSetter(self, attrib):
|
||||||
@ -40,6 +42,15 @@ class Entity:
|
|||||||
return getattr(self, setFuncName)
|
return getattr(self, setFuncName)
|
||||||
return None
|
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"""
|
||||||
|
self.privCallSetters(0, *attribs)
|
||||||
|
|
||||||
|
def callSettersAndDelete(self, *attribs):
|
||||||
|
"""same as callSetters, but also removes attribs from entity"""
|
||||||
|
self.privCallSetters(1, *attribs)
|
||||||
|
|
||||||
def privCallSetters(self, doDelete, *attribs):
|
def privCallSetters(self, doDelete, *attribs):
|
||||||
"""common implementation of callSetters and callSettersAndDelete"""
|
"""common implementation of callSetters and callSettersAndDelete"""
|
||||||
for attrib in attribs:
|
for attrib in attribs:
|
||||||
@ -51,15 +62,6 @@ class Entity:
|
|||||||
delattr(self, attrib)
|
delattr(self, attrib)
|
||||||
setter(value)
|
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 callSettersAndDelete(self, *attribs):
|
|
||||||
"""same as callSetters, but also removes attribs from entity"""
|
|
||||||
self.privCallSetters(1, *attribs)
|
|
||||||
|
|
||||||
# this will be called with each item of our spec data on initialization
|
# this will be called with each item of our spec data on initialization
|
||||||
def setAttribInit(self, attrib, value):
|
def setAttribInit(self, attrib, value):
|
||||||
if hasattr(self, attrib):
|
if hasattr(self, attrib):
|
||||||
|
@ -30,6 +30,7 @@ class Level:
|
|||||||
entities and their interrelations, and creates and destroys entities"""
|
entities and their interrelations, and creates and destroys entities"""
|
||||||
notify = DirectNotifyGlobal.directNotify.newCategory('Level')
|
notify = DirectNotifyGlobal.directNotify.newCategory('Level')
|
||||||
|
|
||||||
|
UberZoneNum = 0
|
||||||
UberZoneEntId = 0
|
UberZoneEntId = 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -61,10 +62,13 @@ class Level:
|
|||||||
|
|
||||||
# there should be one and only one levelMgr
|
# there should be one and only one levelMgr
|
||||||
assert len(self.entType2ids['levelMgr']) == 1
|
assert len(self.entType2ids['levelMgr']) == 1
|
||||||
|
# make sure the uberzone is there
|
||||||
|
assert Level.UberZoneEntId in self.entType2ids['zone']
|
||||||
|
|
||||||
# get an entity creator object
|
# get an entity creator object
|
||||||
self.entityCreator = self.createEntityCreator()
|
self.entityCreator = self.createEntityCreator()
|
||||||
# create all the entities
|
# create all the entities
|
||||||
|
# TODO: we should leave this to a subclass or the level user
|
||||||
self.createAllEntities(priorityTypes=['levelMgr','zone'])
|
self.createAllEntities(priorityTypes=['levelMgr','zone'])
|
||||||
|
|
||||||
def destroyLevel(self):
|
def destroyLevel(self):
|
||||||
@ -132,6 +136,13 @@ class Level:
|
|||||||
# below.
|
# below.
|
||||||
if entity is not None:
|
if entity is not None:
|
||||||
self.createdEntities.append(entity)
|
self.createdEntities.append(entity)
|
||||||
|
|
||||||
|
# call the create handler
|
||||||
|
# we used to do this in initializeEntity, but that did not
|
||||||
|
# allow for additional initialization to be performed in
|
||||||
|
# derived entity __init__ funcs
|
||||||
|
self.onEntityCreate(entId)
|
||||||
|
|
||||||
return entity
|
return entity
|
||||||
|
|
||||||
def initializeEntity(self, entity):
|
def initializeEntity(self, entity):
|
||||||
@ -150,11 +161,8 @@ class Level:
|
|||||||
# 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
|
||||||
|
|
||||||
# call the create handler
|
|
||||||
self.onEntityCreate(entId)
|
|
||||||
|
|
||||||
def getEntity(self, entId):
|
def getEntity(self, entId):
|
||||||
return self.entities[entId]
|
return self.entities.get(entId)
|
||||||
|
|
||||||
def getEntityType(self, entId):
|
def getEntityType(self, entId):
|
||||||
return self.entId2spec[entId]['type']
|
return self.entId2spec[entId]['type']
|
||||||
@ -213,8 +221,6 @@ class Level:
|
|||||||
messenger.send(self.getEntityTypePreCreateEvent(entType))
|
messenger.send(self.getEntityTypePreCreateEvent(entType))
|
||||||
def onEntityTypePostCreate(self, entType):
|
def onEntityTypePostCreate(self, entType):
|
||||||
"""Level has just created these entities"""
|
"""Level has just created these entities"""
|
||||||
if entType == 'zone':
|
|
||||||
self.__handleAllZonesCreated()
|
|
||||||
messenger.send(self.getEntityTypePostCreateEvent(entType))
|
messenger.send(self.getEntityTypePostCreateEvent(entType))
|
||||||
# ENTITY
|
# ENTITY
|
||||||
def onEntityCreate(self, entId):
|
def onEntityCreate(self, entId):
|
||||||
@ -226,31 +232,12 @@ class Level:
|
|||||||
self.getEntityOfTypeCreateEvent(self.getEntityType(entId)),
|
self.getEntityOfTypeCreateEvent(self.getEntityType(entId)),
|
||||||
[entId])
|
[entId])
|
||||||
|
|
||||||
def __handleAllZonesCreated(self):
|
# these are events and handlers that are invoked as entities are destroyed
|
||||||
"""once all the zone entities have been created, and we've got a
|
def getEntityDestroyEvent(self, entId):
|
||||||
list of zoneIds in self.zoneIds, init zone tables"""
|
"""This is the event that is thrown immediately before an
|
||||||
# create a table mapping the model's zone numbers to the zone
|
entity is destroyed"""
|
||||||
# entIds; zone entities are tied to model zone nums in the level spec,
|
return 'entityDestroy-%s-%s' % (self.levelId, entId)
|
||||||
# this is just for convenient lookup
|
def onEntityDestroy(self, entId):
|
||||||
self.zoneNum2entId = {}
|
"""Level is about to destroy this entity"""
|
||||||
for entId in self.entType2ids['zone']:
|
# send the entity-destroy event
|
||||||
zoneEnt = self.getEntity(entId)
|
messenger.send(self.getEntityDestroyEvent(entId))
|
||||||
# NOTE: modelZoneNum comes from the entity's spec data
|
|
||||||
self.zoneNum2entId[zoneEnt.modelZoneNum] = entId
|
|
||||||
|
|
||||||
# At this point, we need to have a 'self.zoneIds' table of network
|
|
||||||
# zoneIds, one for each zone including the UberZone. This is where
|
|
||||||
# we decide which zoneNum/entId gets mapped to which zoneId.
|
|
||||||
# We sort the zoneNums, and then pair the sorted zoneNums up with the
|
|
||||||
# zoneIds in the order that they appear in the self.zoneIds table.
|
|
||||||
modelZoneNums = self.zoneNum2entId.keys()
|
|
||||||
modelZoneNums.sort()
|
|
||||||
# maps of zoneNum/zoneEntId to network zoneId
|
|
||||||
self.zoneNum2zoneId = {}
|
|
||||||
self.zoneEntId2zoneId = {}
|
|
||||||
for i in range(len(modelZoneNums)):
|
|
||||||
modelZoneNum = modelZoneNums[i]
|
|
||||||
zoneEntId = self.zoneNum2entId[modelZoneNum]
|
|
||||||
zoneId = self.zoneIds[i]
|
|
||||||
self.zoneNum2zoneId[modelZoneNum] = zoneId
|
|
||||||
self.zoneEntId2zoneId[zoneEntId] = zoneId
|
|
||||||
|
@ -1,18 +1,82 @@
|
|||||||
"""LevelMgr module: contains the LevelMgr class"""
|
"""LevelMgr module: contains the LevelMgr class"""
|
||||||
|
|
||||||
import Entity
|
from PythonUtil import Functor
|
||||||
|
import LevelMgrBase
|
||||||
|
|
||||||
class LevelMgr(Entity.Entity):
|
class LevelMgr(LevelMgrBase.LevelMgrBase):
|
||||||
"""This class manages editable client-side level attributes"""
|
"""This class manages editable client-side level attributes"""
|
||||||
def __init__(self, level, entId):
|
def __init__(self, level, entId):
|
||||||
Entity.Entity.__init__(self, level, entId)
|
LevelMgrBase.LevelMgrBase.__init__(self, level, entId)
|
||||||
self.level.levelMgr = self
|
|
||||||
|
|
||||||
# load the model
|
# load the model
|
||||||
self.geom = loader.loadModel(self.modelFilename)
|
self.geom = loader.loadModel(self.modelFilename)
|
||||||
|
|
||||||
|
# modelZoneNum -> zone entId
|
||||||
|
self.level.zoneNum2entId = {}
|
||||||
|
# modelZoneNum -> network zoneId
|
||||||
|
self.level.zoneNum2zoneId = {}
|
||||||
|
# zone entId -> network zoneId
|
||||||
|
self.level.zoneEntId2zoneId = {}
|
||||||
|
|
||||||
|
# listen for every zone creation
|
||||||
|
self.accept(self.level.getEntityOfTypeCreateEvent('zone'),
|
||||||
|
self.handleZoneCreated)
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
del self.level.levelMgr
|
del self.level.zoneIds
|
||||||
|
del self.level.zoneEntId2zoneId
|
||||||
|
del self.level.zoneNum2zoneId
|
||||||
|
del self.level.zoneNum2entId
|
||||||
self.geom.removeNode()
|
self.geom.removeNode()
|
||||||
del self.geom
|
del self.geom
|
||||||
Entity.Entity.destroy(self)
|
LevelMgrBase.LevelMgrBase.destroy(self)
|
||||||
|
|
||||||
|
def handleZoneCreated(self, entId):
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
|
||||||
|
# register the zone's info in the tables
|
||||||
|
# right off the bat, we have the zone's modelZoneNum and entId
|
||||||
|
self.level.zoneNum2entId[zoneEnt.modelZoneNum] = entId
|
||||||
|
|
||||||
|
# we can assume that we have a complete list of zoneIds in
|
||||||
|
# self.level.zoneIds. As each zone entity is created, set up
|
||||||
|
# as if we have all of the zone entities. This allows dynamic
|
||||||
|
# zone entity creation and deletion during editing.
|
||||||
|
# TODO: we should delay this until all zone entities have been
|
||||||
|
# created on level init
|
||||||
|
self.privAssignZoneIds()
|
||||||
|
|
||||||
|
# listen for the zone's destruction
|
||||||
|
self.accept(self.level.getEntityDestroyEvent(entId),
|
||||||
|
Functor(self.handleZoneDestroy, entId))
|
||||||
|
|
||||||
|
def handleZoneDestroy(self, entId):
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
# unregister the zone from the maps
|
||||||
|
del self.level.zoneNum2entId[zoneEnt.modelZoneNum]
|
||||||
|
del self.level.zoneNum2zoneId[zoneEnt.modelZoneNum]
|
||||||
|
del self.level.zoneEntId2zoneId[entId]
|
||||||
|
# reassign the zoneIds (we may not need to do this, if all of the
|
||||||
|
# other entities already have their correct zoneId...?)
|
||||||
|
self.privAssignZoneIds()
|
||||||
|
|
||||||
|
def privAssignZoneIds(self):
|
||||||
|
"""assign zoneIds from self.level.zoneIds, according to the zones
|
||||||
|
that are registered so far in self.level.zoneNum2entId"""
|
||||||
|
# sort the model zoneNums
|
||||||
|
modelZoneNums = self.level.zoneNum2entId.keys()
|
||||||
|
modelZoneNums.sort()
|
||||||
|
|
||||||
|
# dole out the zoneIds, in increasing order of zoneNum
|
||||||
|
for i in range(len(modelZoneNums)):
|
||||||
|
zoneNum = modelZoneNums[i]
|
||||||
|
entId = self.level.zoneNum2entId[zoneNum]
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
zoneEnt.setZoneId(self.level.zoneIds[i])
|
||||||
|
|
||||||
|
# the zoneIds have shifted. update the tables
|
||||||
|
for entId in self.level.zoneNum2entId.values():
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
zoneId = zoneEnt.getZoneId()
|
||||||
|
self.level.zoneNum2zoneId[zoneEnt.modelZoneNum] = zoneId
|
||||||
|
self.level.zoneEntId2zoneId[entId] = zoneId
|
||||||
|
@ -1,10 +1,68 @@
|
|||||||
"""LevelMgrAI module: contains the LevelMgrAI class"""
|
"""LevelMgrAI module: contains the LevelMgrAI class"""
|
||||||
|
|
||||||
import Entity
|
from PythonUtil import Functor
|
||||||
|
import LevelMgrBase
|
||||||
|
|
||||||
class LevelMgrAI(Entity.Entity):
|
class LevelMgrAI(LevelMgrBase.LevelMgrBase):
|
||||||
"""This class manages editable AI level attributes"""
|
"""This class manages editable AI level attributes"""
|
||||||
def __init__(self, level, entId):
|
def __init__(self, level, entId):
|
||||||
Entity.Entity.__init__(self, level, entId)
|
LevelMgrBase.LevelMgrBase.__init__(self, level, entId)
|
||||||
self.level.levelMgr = self
|
|
||||||
|
# modelZoneNum -> zone entId
|
||||||
|
self.level.zoneNum2entId = {}
|
||||||
|
# modelZoneNum -> network zoneId
|
||||||
|
self.level.zoneNum2zoneId = {}
|
||||||
|
# zone entId -> network zoneId
|
||||||
|
self.level.zoneEntId2zoneId = {}
|
||||||
|
# list of network zoneIDs, sorted by modelZoneNum
|
||||||
|
self.level.zoneIds = []
|
||||||
|
|
||||||
|
# listen for every zone creation
|
||||||
|
self.accept(self.level.getEntityOfTypeCreateEvent('zone'),
|
||||||
|
self.handleZoneCreated)
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
del self.level.zoneIds
|
||||||
|
del self.level.zoneEntId2zoneId
|
||||||
|
del self.level.zoneNum2zoneId
|
||||||
|
del self.level.zoneNum2entId
|
||||||
|
LevelMgrBase.LevelMgrBase.destroy(self)
|
||||||
|
|
||||||
|
def handleZoneCreated(self, entId):
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
|
||||||
|
# register the zone's info in the tables
|
||||||
|
self.level.zoneNum2entId[zoneEnt.modelZoneNum] = entId
|
||||||
|
self.level.zoneNum2zoneId[zoneEnt.modelZoneNum] = zoneEnt.getZoneId()
|
||||||
|
self.level.zoneEntId2zoneId[entId] = zoneEnt.getZoneId()
|
||||||
|
|
||||||
|
# TODO: we should delay this until all zone entities have been
|
||||||
|
# created on level init
|
||||||
|
self.privCreateSortedZoneIdList()
|
||||||
|
|
||||||
|
# listen for the zone's destruction
|
||||||
|
self.accept(self.level.getEntityDestroyEvent(entId),
|
||||||
|
Functor(self.handleZoneDestroy, entId))
|
||||||
|
|
||||||
|
def handleZoneDestroy(self, entId):
|
||||||
|
zoneEnt = self.level.getEntity(entId)
|
||||||
|
# unregister the zone from the maps
|
||||||
|
del self.level.zoneNum2entId[zoneEnt.modelZoneNum]
|
||||||
|
del self.level.zoneNum2zoneId[zoneEnt.modelZoneNum]
|
||||||
|
del self.level.zoneEntId2zoneId[entId]
|
||||||
|
# recreate the sorted network zoneId list
|
||||||
|
self.privCreateSortedZoneIdList()
|
||||||
|
|
||||||
|
def privCreateSortedZoneIdList(self):
|
||||||
|
# sort the model zoneNums
|
||||||
|
modelZoneNums = self.level.zoneNum2entId.keys()
|
||||||
|
modelZoneNums.sort()
|
||||||
|
|
||||||
|
# create a list of network zoneIds, ordered by their corresponding
|
||||||
|
# sorted model zoneNum values
|
||||||
|
self.level.zoneIds = []
|
||||||
|
for zoneNum in modelZoneNums:
|
||||||
|
self.level.zoneIds.append(self.level.zoneNum2zoneId[zoneNum])
|
||||||
|
|
||||||
|
# TODO: if we just added or removed a zone entity AFTER the level
|
||||||
|
# was initialized, we need to re-send the zoneId list
|
||||||
|
14
direct/src/level/LevelMgrBase.py
Executable file
14
direct/src/level/LevelMgrBase.py
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
"""LevelMgrBase module: contains the LevelMgrBase class"""
|
||||||
|
|
||||||
|
import Entity
|
||||||
|
|
||||||
|
class LevelMgrBase(Entity.Entity):
|
||||||
|
"""This class contains LevelMgr code shared by the AI and client"""
|
||||||
|
def __init__(self, level, entId):
|
||||||
|
Entity.Entity.__init__(self, level, entId)
|
||||||
|
self.level.levelMgr = self
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
del self.level.levelMgr
|
||||||
|
Entity.Entity.destroy(self)
|
||||||
|
self.ignoreAll()
|
@ -1,11 +1,11 @@
|
|||||||
"""ZoneEntity module: contains the ZoneEntity class"""
|
"""ZoneEntity module: contains the ZoneEntity class"""
|
||||||
|
|
||||||
import Entity
|
import ZoneEntityBase
|
||||||
import BasicEntities
|
import BasicEntities
|
||||||
|
|
||||||
class ZoneEntity(Entity.Entity, BasicEntities.NodePathAttribs):
|
class ZoneEntity(ZoneEntityBase.ZoneEntityBase, BasicEntities.NodePathAttribs):
|
||||||
def __init__(self, level, entId):
|
def __init__(self, level, entId):
|
||||||
Entity.Entity.__init__(self, level, entId)
|
ZoneEntityBase.ZoneEntityBase.__init__(self, level, entId)
|
||||||
|
|
||||||
self.nodePath = self.level.getZoneNode(self.modelZoneNum)
|
self.nodePath = self.level.getZoneNode(self.modelZoneNum)
|
||||||
self.initNodePathAttribs(doReparent=0)
|
self.initNodePathAttribs(doReparent=0)
|
||||||
|
@ -1,9 +1,21 @@
|
|||||||
"""ZoneEntityAI module: contains the ZoneEntityAI class"""
|
"""ZoneEntityAI module: contains the ZoneEntityAI class"""
|
||||||
|
|
||||||
import Entity
|
import ZoneEntityBase
|
||||||
|
|
||||||
class ZoneEntityAI(Entity.Entity):
|
class ZoneEntityAI(ZoneEntityBase.ZoneEntityBase):
|
||||||
def __init__(self, level, entId):
|
def __init__(self, level, entId):
|
||||||
Entity.Entity.__init__(self, level, entId)
|
ZoneEntityBase.ZoneEntityBase.__init__(self, level, entId)
|
||||||
# allocate a network zoneId for each zone
|
|
||||||
self.level.allocateZoneId()
|
if self.isUberZone():
|
||||||
|
print 'uberZone'
|
||||||
|
# the uberzone is already allocated
|
||||||
|
self.setZoneId(self.level.uberZoneId)
|
||||||
|
else:
|
||||||
|
# allocate a network zoneId for this zone
|
||||||
|
# there is error checking in air.allocateZone
|
||||||
|
self.setZoneId(self.level.air.allocateZone())
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
if not self.isUberZone():
|
||||||
|
self.level.air.deallocateZone(self.getZoneId())
|
||||||
|
ZoneEntityBase.ZoneEntityBase.destroy(self)
|
||||||
|
23
direct/src/level/ZoneEntityBase.py
Executable file
23
direct/src/level/ZoneEntityBase.py
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
"""ZoneEntityBase module: contains the ZoneEntityBase class"""
|
||||||
|
|
||||||
|
import Entity
|
||||||
|
import Level
|
||||||
|
|
||||||
|
class ZoneEntityBase(Entity.Entity):
|
||||||
|
def __init__(self, level, entId):
|
||||||
|
Entity.Entity.__init__(self, level, entId)
|
||||||
|
self.zoneId = None
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
del self.zoneId
|
||||||
|
Entity.Entity.destroy(self)
|
||||||
|
|
||||||
|
def isUberZone(self):
|
||||||
|
return self.entId == Level.Level.UberZoneEntId
|
||||||
|
|
||||||
|
def setZoneId(self, zoneId):
|
||||||
|
"""set the network zoneId that this zone entity corresponds to"""
|
||||||
|
self.zoneId = zoneId
|
||||||
|
|
||||||
|
def getZoneId(self):
|
||||||
|
return self.zoneId
|
Loading…
x
Reference in New Issue
Block a user