def __init__(self, _base): self.base = _base self.leveldata = LevelData(self) self.levelPhysics = None
class LevelLoader: def __init__(self, _base): self.base = _base self.leveldata = LevelData(self) self.levelPhysics = None def run(self): self.leveldata.generate() def read(self, levelFilename, isInsideMF=True): """This function reads the given level file and store the data for further use inside the self.levelPhysics and self.levelPhysics.level variables""" # use try except block for reading the xml file # if something happen, we simply return False to # indicate the loading failed try: if isInsideMF: # as we can't parse files which are inside multifiles, # we need to read them with the vfs and then parse the String from panda3d.core import VirtualFileSystem vfs = VirtualFileSystem.getGlobalPtr() lvlFile = vfs.readFile(levelFilename, False) levelTree = ElementTree.XML(lvlFile) else: lvlFile = levelFilename levelTree = ElementTree.parse(lvlFile) # read some basic informations of the level like # author name and creation date author = levelTree.find("author") if author != None: self.leveldata.author = author.text date = levelTree.find("date") if date != None: self.leveldata.date = date.text name = levelTree.find("name") if name != None: self.leveldata.name = name.text model = self.__readModel(levelTree.find("baseModel")) if model != None: self.leveldata.model = model else: # We have a problem with loading the base model return False collision = levelTree.find("collisionModel") if collision != None: colModel = self.__readModel(levelTree.find("collisionModel")) if colModel != None: self.leveldata.colModel = colModel walls = levelTree.find("wallCollision") if walls != None: colWall = self.__readCollisionModel(walls) if colWall != None: self.leveldata.colWall = colWall colGround = self.__readCollisionModel( levelTree.find("groundCollision")) if colGround != None: self.leveldata.colGround = colGround wallRunSensor = SensorWallRun() wallRunSensor.sensorID = "wallrun" if self.leveldata.colWall != None: wallRunSensor.model = self.leveldata.colWall elif self.leveldata.colModel != None: wallRunSensor.model = self.leveldata.colModel elif self.leveldata.colGround != None: wallRunSensor.model = self.leveldata.colGround wallRunSensor.sensorType = "wallRuns" self.leveldata.sensors.append(wallRunSensor) startPos = levelTree.find("startPos") if startPos != None: pos = self.__readPos(startPos) self.leveldata.playerStartPos = pos hpr = self.__readHpr(startPos) self.leveldata.playerStartHpr = hpr if levelTree.find("exit") is not None: colExit = self.__readCollisionModel(levelTree.find("exit")) if colExit != None: sensor = SensorExit() sensor.sensorID = "exit" sensor.model = colExit sensor.sensorType = "exit" self.leveldata.sensors.append(sensor) objects = levelTree.find("objects") if objects != None: self.__readObjects(objects) sensors = levelTree.find("sensors") if sensors != None: self.__readSensors(sensors) lights = levelTree.find("lights") if lights != None: self.__readLights(lights) aiUnits = levelTree.find("aiUnits") if aiUnits != None: self.__readAIUnits(aiUnits) except: logging.error("Error while loading level: %s %s", levelFilename, sys.exc_info()) return False return True def __readObjects(self, root): """Read the objects stored in the given root node""" for entry in list(root): newObject = None objType = entry.get("type", default="object").lower() if objType == "object": pass elif objType == "item": itemType = entry.find("type").text.lower() if itemType == "medikit": newObject = ItemHealth() elif itemType == "staminarefill": newObject = ItemStamina() elif objType == "collectible": pass if newObject != None: pos = self.__readPos(entry) newObject.model.setPos(pos) scale = self.__readScale(entry) newObject.model.setScale(scale) if objType == "item": self.leveldata.items.append(newObject) else: self.leveldata.objects.append(newObject) def __readSensors(self, root): for entry in list(root): objType = entry.get("type", default="object").lower() if objType == "ladder": sensor = SensorClimbeable() sensor.sensorID = entry.find("id").text sensor.model = self.__readCollisionModel(entry) sensor.sensorType = "ladder" self.leveldata.sensors.append(sensor) elif objType == "pipe": sensor = SensorClimbeable() sensor.sensorID = entry.find("id").text sensor.model = self.__readCollisionModel(entry) sensor.sensorType = "pipe" self.leveldata.sensors.append(sensor) elif objType == "hint": sensor = SensorMessage() sensor.sensorID = entry.find("id").text sensor.model = self.__readCollisionModel(entry) textEntry = entry.find("text") translateableEntry = entry.find("translateable") if textEntry != None: sensor.message = textEntry.text if translateableEntry != None: sensor.translated = eval(translateableEntry.text) sensor.setActOnCollide(True) sensor.sensorType = "hint" self.leveldata.sensors.append(sensor) def __readLights(self, root): lightCounter = 0 for entry in list(root): # read in the type of the light lightType = entry.get("type", default="PointLight").lower() light = None if lightType == "pointlight": light = PointLight("Pnt_Light%03d" % lightCounter) elif lightType == "directionallight": light = DirectionalLight("Dir_Light%03d" % lightCounter) elif lightType == "ambientlight": light = AmbientLight("Amb_Light%03d" % lightCounter) elif lightType == "spotlight": light = Spotlight("Spt_Light%03d" % lightCounter) if light != None: color = entry.find("color") if color != None: # set the light"s color r = float(color.get("r", "1")) g = float(color.get("g", "1")) b = float(color.get("b", "1")) a = float(color.get("a", "1")) light.setColor(VBase4(r, g, b, a)) # now create a new nodepath with the light lightnp = NodePath(light) # set the light"s position pos = self.__readPos(entry) lightnp.setPos(pos) # and it"s orientation hpr = self.__readHpr(entry) lightnp.setHpr(hpr) # finaly append the light to the list of lights self.leveldata.lights.append(lightnp) lightCounter += 1 def __readAIUnits(self, root): for entry in list(root): aiUnitType = entry.get("type", default="Worker").lower() if aiUnitType == "worker": pass def __readModel(self, root): model = None if root is None: return None # try get the model path modelFile = root.find("model") if modelFile != None: # if we got a path try load it try: model = loader.loadModel(modelFile.text) except: logging.error(sys.exc_info()[1]) # only if the model is loaded correctly, we can proceed if model is None: return None pos = self.__readPos(root) model.setPos(pos) scale = self.__readScale(root) model.setScale(scale) hpr = self.__readHpr(root) model.setHpr(hpr) return model def __readCollisionModel(self, root): modelData = root.find("collision") if "modelName" in modelData.keys(): # The model is inside the main Model colNodeName = modelData.get("modelName") if self.leveldata.colModel != None: colModel = self.leveldata.colModel.find("**/" + colNodeName) else: colModel = self.leveldata.model.find("**/" + colNodeName) return colModel else: # The collision object has its own model file return self.__readModel(modelData) def __readPos(self, root): pos = root.find("position") if pos != None: if "nodeName" in pos.keys(): posNodeName = pos.get("nodeName") p = self.leveldata.model.find( "**/" + posNodeName).getPos() p.setX(p.getX() * self.leveldata.model.getScale().getX()) p.setY(p.getY() * self.leveldata.model.getScale().getY()) p.setZ(p.getZ() * self.leveldata.model.getScale().getZ()) return p else: x = float(pos.get("x", "0.0")) \ * self.leveldata.model.getScale().getX() y = float(pos.get("y", "0.0")) \ * self.leveldata.model.getScale().getY() z = float(pos.get("z", "0.0")) \ * self.leveldata.model.getScale().getZ() return (x, y, z) return (0, 0, 0) def __readHpr(self, root): """Read heading Pinch and roll from the given root of the xml file. if the <hpr> tag is not found in the root tag, then (0, 0, 0) will be returned""" hpr = root.find("hpr") if hpr != None: if "nodeName" in hpr.keys(): hprNodeName = hpr.get("nodeName") hpr = self.leveldata.model.find("**/" + hprNodeName).getHpr() return hpr else: h = float(hpr.get("h", "0.0")) p = float(hpr.get("p", "0.0")) r = float(hpr.get("r", "0.0")) return (h, p, r) return (0, 0, 0) def __readScale(self, root): """Read scale from the given root of the xml file. If the <scale> tag is not found, the default scale of 1.0 will be returned""" scale = root.find("scale") if scale != None: t = scale.get("type", "float") s = scale.text return eval("%s('%s')" % (t, s)) return 1.0