added SpecUtil funcs for creating and adapting specs to new level models
This commit is contained in:
parent
cf7a1d1427
commit
be086b33d7
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -6,3 +6,5 @@ UberZoneNum = 0
|
|||
LevelMgrEntId = 10
|
||||
|
||||
EditMgrEntId = 20
|
||||
|
||||
ZoneEntIdStart = 100
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue