added SpecUtil funcs for creating and adapting specs to new level models

This commit is contained in:
Darren Ranalli 2003-10-25 01:10:17 +00:00
parent cf7a1d1427
commit be086b33d7
4 changed files with 98 additions and 34 deletions

View File

@ -10,6 +10,7 @@ import DirectNotifyGlobal
import EntityCreator
import OnscreenText
import Task
import LevelUtil
class DistributedLevel(DistributedObject.DistributedObject,
Level.Level):
@ -181,34 +182,13 @@ class DistributedLevel(DistributedObject.DistributedObject,
def __handleLevelMgrCreated(self):
# as soon as the levelMgr has been created, load up the model
# and extract zone info
# and extract zone info. We need to do this before any entities
# get parented to the level!
levelMgr = self.getEntity(LevelConstants.LevelMgrEntId)
self.geom = levelMgr.geom
def findNumberedNodes(baseString, model=self.geom, self=self):
# finds nodes whose name follows the pattern 'baseString#'
# where there are no characters after #
# returns dictionary that maps # to node
potentialNodes = model.findAllMatches(
'**/%s*' % baseString).asList()
num2node = {}
for potentialNode in potentialNodes:
name = potentialNode.getName()
DistributedLevel.notify.debug('potential match for %s: %s' %
(baseString, name))
try:
num = int(name[len(baseString):])
except:
continue
num2node[num] = potentialNode
return num2node
# find the zones in the model and fix them up
self.zoneNum2node = findNumberedNodes('Zone')
# add the UberZone to the table
self.zoneNum2node[0] = self.geom
self.zoneNum2node = LevelUtil.getZoneNum2Node(self.geom)
self.zoneNums = self.zoneNum2node.keys()
self.zoneNums.sort()
@ -250,6 +230,27 @@ class DistributedLevel(DistributedObject.DistributedObject,
dw.setH(0)
# find the doorway nodes
# this is going to go away soon.
def findNumberedNodes(baseString, model=self.geom, self=self):
# finds nodes whose name follows the pattern 'baseString#'
# where there are no characters after #
# returns dictionary that maps # to node
potentialNodes = model.findAllMatches(
'**/%s*' % baseString).asList()
num2node = {}
for potentialNode in potentialNodes:
name = potentialNode.getName()
DistributedLevel.notify.debug('potential match for %s: %s' %
(baseString, name))
try:
num = int(name[len(baseString):])
except:
continue
num2node[num] = potentialNode
return num2node
self.doorwayNum2Node = findNumberedNodes('Doorway')
def announceGenerate(self):

View File

@ -6,3 +6,5 @@ UberZoneNum = 0
LevelMgrEntId = 10
EditMgrEntId = 20
ZoneEntIdStart = 100

View File

@ -16,22 +16,24 @@ class LevelSpec:
def __init__(self, spec=None, scenario=0):
"""spec must be passed in as a python module or a dictionary"""
newSpec = 0
if type(spec) is types.ModuleType:
self.specDict = spec.levelSpec
else:
if __debug__:
self.setFilename(spec.__file__)
elif type(spec) is types.DictType:
# we need this for repr/eval-ing LevelSpecs
assert type(spec) is types.DictType
self.specDict = spec
if __debug__:
newSpec = 0
if self.specDict == None:
elif spec is None:
if __debug__:
newSpec = 1
self.specDict = {
'globalEntities': {},
'scenarios': [[{}, 1]],
}
assert hasattr(self, 'specDict')
# this maps an entId to the dict that holds its spec;
# entities are either in the global dict or a scenario dict
# update the map of entId to spec dict

View File

@ -2,13 +2,14 @@
import LevelSpec
import LevelConstants
import LevelUtil
from PythonUtil import list2dict
def makeNewSpec(filename, modelPath):
"""call this to create a new level spec for the level model at 'modelPath'.
Spec will be saved as 'filename'"""
spec = LevelSpec.LevelSpec()
spec.doSetAttrib(LevelConstants.LevelMgrEntId,
'modelFilename', modelPath)
privUpdateSpec(spec, modelPath)
spec.saveToDisk(filename, makeBackup=0)
def updateSpec(specModule, modelPath=None):
@ -16,10 +17,68 @@ def updateSpec(specModule, modelPath=None):
model. If the level model has a new path, pass it in as 'modelPath'.
specModule must be a Python module"""
spec = LevelSpec.LevelSpec(specModule)
privUpdateSpec(spec, modelPath)
spec.saveToDisk()
def privUpdateSpec(spec, modelPath=None):
"""internal: take a spec and update it to match its level model"""
if modelPath is None:
modelPath = spec.getEntitySpec(
LevelConstants.LevelMgrEntId)['modelFilename']
else:
spec.doSetAttrib(LevelConstants.LevelMgrEntId,
'modelFilename', modelPath)
# ...
# load the model
model = loader.loadModel(modelPath)
# get the model's zone info
modelZoneNum2node = LevelUtil.getZoneNum2Node(model)
modelZoneNums = modelZoneNum2node.keys()
spec.saveToDisk()
# what zone entities do we have specs for?
type2ids = spec.getEntType2ids(spec.getAllEntIds())
type2ids.setdefault('zone', [])
zoneEntIds = type2ids['zone']
zoneEntId2spec = list2dict(zoneEntIds)
for entId in zoneEntIds:
zoneEntId2spec[entId] = spec.getEntitySpec(entId)
def removeZoneEntity(entId, spec=spec, zoneEntIds=zoneEntIds,
zoneEntId2spec=zoneEntId2spec):
spec.removeEntity(entId)
zoneEntIds.remove(entId)
del zoneEntId2spec[entId]
# create dict of zoneNum -> entId
zoneNum2entId = {}
for entId in list(zoneEntIds):
zoneNum = zoneEntId2spec[entId]['modelZoneNum']
if zoneNum in zoneNum2entId:
print ('multiple zone entities reference zoneNum %s; removing '
'entity %s' % (zoneNum, entId))
removeZoneEntity(entId)
continue
zoneNum2entId[zoneNum] = entId
# prune zone entities that reference zones that no longer exist
for entId in list(zoneEntIds):
zoneNum = zoneEntId2spec[entId]['modelZoneNum']
if zoneNum not in modelZoneNums:
print 'zone %s no longer exists; removing entity %s' % (
zoneNum, entId)
removeZoneEntity(entId)
del zoneNum2entId[zoneNum]
# add new zone entities for new zones
for zoneNum in modelZoneNums:
if zoneNum not in zoneNum2entId:
entIdDict = list2dict(spec.getAllEntIds())
entId = LevelConstants.ZoneEntIdStart
# we could do better than linear
while entId in entIdDict:
entId += 1
print 'adding entity %s for new zone %s' % (entId, zoneNum)
spec.insertEntity(entId, 'zone', LevelConstants.UberZoneEntId)
spec.doSetAttrib(entId, 'name', 'zone%s' % zoneNum)
spec.doSetAttrib(entId, 'modelZoneNum', zoneNum)