# HG changeset patch # User prock@33b003aa-7bff-0310-803a-e67f0ece8222 # Date 1273858662 0 # Node ID 3dff106b945b98056c59e3c09e56e5da6e099872 # Parent 5ff83f2093336b3c5690b82c18949bafa98da25e Combined the settings extension with the editor settings module. It is now a little more robust. Note that the settings file format has changed. All demos and tools now use the new settings extension. diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/run.py --- a/demos/rio_de_hola/run.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/run.py Fri May 14 17:37:42 2010 +0000 @@ -118,47 +118,53 @@ class IslandDemo(ApplicationBase): def __init__(self): super(IslandDemo,self).__init__() - pychan.init(self.engine, debug=TDS.readSetting("PychanDebug", type='bool')) + pychan.init(self.engine, debug=TDS.get("FIFE", "PychanDebug")) self.world = world.World(self.engine) self.listener = ApplicationListener(self.engine, self.world) - self.world.load(str(TDS.readSetting("MapFile"))) + self.world.load(str(TDS.get("rio", "MapFile"))) def loadSettings(self): """ Load the settings from a python file and load them into the engine. - Called in the ApplicationBase constructor. + Called in the ApplicationBase constructor. """ + + self._setting = TDS + glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\\\"" engineSetting = self.engine.getSettings() - engineSetting.setDefaultFontGlyphs(str(TDS.readSetting("FontGlyphs", strip=False))) - engineSetting.setDefaultFontPath(str(TDS.readSetting("Font"))) - engineSetting.setDefaultFontSize(12) - engineSetting.setBitsPerPixel(int(TDS.readSetting("BitsPerPixel"))) - engineSetting.setInitialVolume(float(TDS.readSetting("InitialVolume"))) - engineSetting.setSDLRemoveFakeAlpha(int(TDS.readSetting("SDLRemoveFakeAlpha"))) - engineSetting.setScreenWidth(int(TDS.readSetting("ScreenWidth"))) - engineSetting.setScreenHeight(int(TDS.readSetting("ScreenHeight"))) - engineSetting.setRenderBackend(str(TDS.readSetting("RenderBackend"))) - engineSetting.setFullScreen(int(TDS.readSetting("FullScreen"))) + engineSetting.setDefaultFontGlyphs(self._setting.get("FIFE", "FontGlyphs", glyphDft)) + engineSetting.setDefaultFontPath(self._setting.get("FIFE", "Font", "fonts/FreeSans.ttf")) + engineSetting.setDefaultFontSize(self._setting.get("FIFE", "DefaultFontSize", 12)) + engineSetting.setBitsPerPixel(self._setting.get("FIFE", "BitsPerPixel", 0)) + engineSetting.setInitialVolume(self._setting.get("FIFE", "InitialVolume", 5.0)) + engineSetting.setSDLRemoveFakeAlpha(self._setting.get("FIFE", "SDLRemoveFakeAlpha", 1)) + engineSetting.setScreenWidth(self._setting.get("FIFE", "ScreenWidth", 1024)) + engineSetting.setScreenHeight(self._setting.get("FIFE", "ScreenHeight", 768)) + engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL")) + engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", 0)) - try: - engineSetting.setWindowTitle(str(TDS.readSetting("WindowTitle"))) - engineSetting.setWindowIcon(str(TDS.readSetting("WindowIcon"))) - except: - pass - try: - engineSetting.setImageChunkingSize(int(TDS.readSetting("ImageChunkSize"))) - except: - pass + engineSetting.setWindowTitle(self._setting.get("FIFE", "WindowTitle", "No window title set")) + engineSetting.setWindowIcon(self._setting.get("FIFE", "WindowIcon", "")) + engineSetting.setImageChunkingSize(self._setting.get("FIFE", "ImageChunkSize", 256)) def initLogging(self): """ Initialize the LogManager. """ - LogModules = TDS.readSetting("LogModules", type='list') - self.log = fifelog.LogManager(self.engine, int(TDS.readSetting("LogToPrompt")), int(TDS.readSetting("LogToFile"))) - if LogModules: - self.log.setVisibleModules(*LogModules) + + engineSetting = self.engine.getSettings() + logmodules = self._setting.get("FIFE", "LogModules", "controller") + + #log to both the console and log file + self._log = fifelog.LogManager(self.engine, + self._setting.get("FIFE", "LogToPrompt", "0"), + self._setting.get("FIFE", "LogToFile", "0")) + + self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG) + + if logmodules: + self._log.setVisibleModules(*logmodules) def createListener(self): pass # already created in constructor @@ -185,7 +191,7 @@ if __name__ == '__main__': - if TDS.readSetting("ProfilingOn", type='bool'): + if TDS.get("FIFE", "ProfilingOn"): import hotshot, hotshot.stats print "Starting profiler" prof = hotshot.Profile("fife.prof") @@ -197,7 +203,7 @@ stats.sort_stats('time', 'calls') stats.print_stats(20) else: - if TDS.readSetting("UsePsyco", type='bool'): + if TDS.get("FIFE", "UsePsyco"): # Import Psyco if available try: import psyco diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/agents/agent.py --- a/demos/rio_de_hola/scripts/agents/agent.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/agents/agent.py Fri May 14 17:37:42 2010 +0000 @@ -25,8 +25,9 @@ from scripts.common.common import ProgrammingError class Agent(fife.InstanceActionListener): - def __init__(self, model, agentName, layer, uniqInMap=True): + def __init__(self, settings, model, agentName, layer, uniqInMap=True): fife.InstanceActionListener.__init__(self) + self.settings = settings self.model = model self.agentName = agentName self.layer = layer @@ -41,14 +42,14 @@ raise ProgrammingError('No start defined for Agent') -def create_anonymous_agents(model, objectName, layer, agentClass): +def create_anonymous_agents(settings, model, objectName, layer, agentClass): agents = [] instances = [a for a in layer.getInstances() if a.getObject().getId() == objectName] i = 0 for a in instances: agentName = '%s:i:%d' % (objectName, i) i += 1 - agent = agentClass(model, agentName, layer, False) + agent = agentClass(settings, model, agentName, layer, False) agent.agent = a a.addActionListener(agent) agents.append(agent) diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/agents/beekeeper.py --- a/demos/rio_de_hola/scripts/agents/beekeeper.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/agents/beekeeper.py Fri May 14 17:37:42 2010 +0000 @@ -28,8 +28,8 @@ _STATE_NONE, _STATE_TALK = 0, 1 class Beekeeper(Agent): - def __init__(self, model, agentName, layer, uniqInMap=True): - super(Beekeeper, self).__init__(model, agentName, layer, uniqInMap) + def __init__(self, settings, model, agentName, layer, uniqInMap=True): + super(Beekeeper, self).__init__(settings, model, agentName, layer, uniqInMap) self.state = _STATE_NONE def onInstanceActionFinished(self, instance, action): diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/agents/cloud.py --- a/demos/rio_de_hola/scripts/agents/cloud.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/agents/cloud.py Fri May 14 17:37:42 2010 +0000 @@ -28,8 +28,8 @@ _STATE_NONE, _STATE_FLOATING, _STATE_DISAPPEAR, _STATE_APPEAR = 0, 1, 2, 3 class Cloud(Agent): - def __init__(self, model, agentName, layer, uniqInMap=False): - super(Cloud, self).__init__(model, agentName, layer, uniqInMap) + def __init__(self, settings, model, agentName, layer, uniqInMap=False): + super(Cloud, self).__init__(settings, model, agentName, layer, uniqInMap) self.state = _STATE_NONE def isOutOfBounds(self, c): diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/agents/girl.py --- a/demos/rio_de_hola/scripts/agents/girl.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/agents/girl.py Fri May 14 17:37:42 2010 +0000 @@ -25,18 +25,19 @@ from fife import fife from fife.extensions.fife_settings import Setting -TDS = Setting(app_name="rio_de_hola") +#TDS = Setting(app_name="rio_de_hola") _STATE_NONE, _STATE_IDLE, _STATE_RUN, _STATE_FOLLOW = 0, 1, 2, 3 -GIRL_SPEED = 3 * float(TDS.readSetting("TestAgentSpeed")) class Girl(Agent): - def __init__(self, model, agentName, layer, uniqInMap=True): - super(Girl, self).__init__(model, agentName, layer, uniqInMap) + def __init__(self, settings, model, agentName, layer, uniqInMap=True): + super(Girl, self).__init__(settings, model, agentName, layer, uniqInMap) self.state = _STATE_NONE self.waypoints = ((67, 80), (75, 44)) self.waypoint_counter = 0 self.hero = self.layer.getInstance('PC') + + self.GIRL_SPEED = 3 * float(self.settings.get("rio", "TestAgentSpeed")) def onInstanceActionFinished(self, instance, action): if self.state in (_STATE_RUN, _STATE_FOLLOW): @@ -63,8 +64,8 @@ def follow_hero(self): self.state = _STATE_FOLLOW - self.agent.follow('run', self.hero, GIRL_SPEED) + self.agent.follow('run', self.hero, self.GIRL_SPEED) def run(self, location): self.state = _STATE_RUN - self.agent.move('run', location, GIRL_SPEED) + self.agent.move('run', location, self.GIRL_SPEED) diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/agents/hero.py --- a/demos/rio_de_hola/scripts/agents/hero.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/agents/hero.py Fri May 14 17:37:42 2010 +0000 @@ -25,13 +25,13 @@ from agent import Agent from fife.extensions.fife_settings import Setting -TDS = Setting(app_name="rio_de_hola") +#TDS = Setting(app_name="rio_de_hola") _STATE_NONE, _STATE_IDLE, _STATE_RUN, _STATE_KICK, _STATE_TALK = xrange(5) class Hero(Agent): - def __init__(self, model, agentName, layer, uniqInMap=True): - super(Hero, self).__init__(model, agentName, layer, uniqInMap) + def __init__(self, settings, model, agentName, layer, uniqInMap=True): + super(Hero, self).__init__(settings, model, agentName, layer, uniqInMap) self.state = _STATE_NONE self.idlecounter = 1 @@ -42,7 +42,7 @@ else: self.idlecounter += 1 if self.idlecounter % 7 == 0: - heroTexts = TDS.readSetting("heroTexts", type='list', text=True) + heroTexts = self.settings.get("rio", "heroTexts") txtindex = random.randint(0, len(heroTexts) - 1) instance.say(heroTexts[txtindex], 2500) @@ -55,7 +55,7 @@ def run(self, location): self.state = _STATE_RUN - self.agent.move('run', location, 4 * float(TDS.readSetting("TestAgentSpeed"))) + self.agent.move('run', location, 4 * self.settings.get("rio", "TestAgentSpeed")) def kick(self, target): self.state = _STATE_KICK diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/scripts/world.py --- a/demos/rio_de_hola/scripts/world.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/scripts/world.py Fri May 14 17:37:42 2010 +0000 @@ -163,7 +163,7 @@ self.initAgents() self.initCameras() - if int(TDS.readSetting("PlaySounds")): + if int(TDS.get("FIFE", "PlaySounds")): # play track as background music self.music = self.soundmanager.createSoundEmitter('music/rio_de_hola.ogg') self.music.looping = True @@ -186,22 +186,22 @@ to the python agents for later reference. """ self.agentlayer = self.map.getLayer('TechdemoMapGroundObjectLayer') - self.hero = Hero(self.model, 'PC', self.agentlayer) + self.hero = Hero(TDS, self.model, 'PC', self.agentlayer) self.instance_to_agent[self.hero.agent.getFifeId()] = self.hero self.hero.start() - self.girl = Girl(self.model, 'NPC:girl', self.agentlayer) + self.girl = Girl(TDS, self.model, 'NPC:girl', self.agentlayer) self.instance_to_agent[self.girl.agent.getFifeId()] = self.girl self.girl.start() - self.beekeepers = create_anonymous_agents(self.model, 'beekeeper', self.agentlayer, Beekeeper) + self.beekeepers = create_anonymous_agents(TDS, self.model, 'beekeeper', self.agentlayer, Beekeeper) for beekeeper in self.beekeepers: self.instance_to_agent[beekeeper.agent.getFifeId()] = beekeeper beekeeper.start() # Clouds are currently defunct. cloudlayer = self.map.getLayer('TechdemoMapTileLayer') - self.clouds = create_anonymous_agents(self.model, 'Cloud', cloudlayer, Cloud) + self.clouds = create_anonymous_agents(TDS, self.model, 'Cloud', cloudlayer, Cloud) for cloud in self.clouds: cloud.start(0.1, 0.05) @@ -230,7 +230,7 @@ # You'll se that for our demo we use a image font, so we have to specify the font glyphs # for that one. renderer = fife.FloatingTextRenderer.getInstance(self.cameras['main']) - textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.readSetting("FontGlyphs", strip=False))); + textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.get("FIFE", "FontGlyphs"))); renderer.changeDefaultFont(textfont) renderer.activateAllLayers(self.map) @@ -242,20 +242,19 @@ # So we disable the renderer simply by setting its font to None. renderer = fife.FloatingTextRenderer.getInstance(self.cameras['small']) renderer.changeDefaultFont(None) - # The following renderers are used for debugging. # Note that by default ( that is after calling View.resetRenderers or Camera.resetRenderers ) # renderers will be handed all layers. That's handled here. renderer = self.cameras['main'].getRenderer('CoordinateRenderer') renderer.clearActiveLayers() - renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("CoordinateLayerName")))) + renderer.addActiveLayer(self.map.getLayer(str(TDS.get("rio", "CoordinateLayerName")))) renderer = self.cameras['main'].getRenderer('QuadTreeRenderer') renderer.setEnabled(True) renderer.clearActiveLayers() - if str(TDS.readSetting("QuadTreeLayerName")): - renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("QuadTreeLayerName")))) + if str(TDS.get("rio", "QuadTreeLayerName")): + renderer.addActiveLayer(self.map.getLayer(str(TDS.get("rio", "QuadTreeLayerName")))) # Set up the second camera # NOTE: We need to explicitly call setLocation, there's a bit of a messup in the Camera code. @@ -370,10 +369,10 @@ instance = self.instancemenu.instance self.hero.talk(instance.getLocationRef()) if instance.getObject().getId() == 'beekeeper': - beekeeperTexts = TDS.readSetting("beekeeperTexts", type='list', text=True) + beekeeperTexts = TDS.get("rio", "beekeeperTexts") instance.say(random.choice(beekeeperTexts), 5000) if instance.getObject().getId() == 'girl': - girlTexts = TDS.readSetting("girlTexts", type='list', text=True) + girlTexts = TDS.get("rio", "girlTexts") instance.say(random.choice(girlTexts), 5000) def onKickButtonPress(self): diff -r 5ff83f209333 -r 3dff106b945b demos/rio_de_hola/settings-dist.xml --- a/demos/rio_de_hola/settings-dist.xml Fri May 14 16:23:52 2010 +0000 +++ b/demos/rio_de_hola/settings-dist.xml Fri May 14 17:37:42 2010 +0000 @@ -1,35 +1,39 @@ + - 0 - 1 - OpenGL - 1024 - 768 - 0 - 5.0 - 1 - FIFE - Rio de hola - gui/icons/boy.png + + 0 + 1 + OpenGL + 1024 + 768 + 0 + 5.0 + 1 + FIFE - Rio de hola + gui/icons/boy.png + fonts/FreeSans.ttf + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" + 16 + controller + False + 1 + False + False + 0 + - maps/shrine.xml - fonts/FreeSans.ttf - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" - controller - False - 1 - 0 - False - False - 256 + + maps/shrine.xml + + TechdemoMapTileLayer + - TechdemoMapTileLayer - + I wonder when the guys will get this world ready for me ; Bring it on baby, I'm ready for action! ; humm di dum.... + Why I am running? Haven't you heard that the bees are coming?! ; Heeelp!!! The bees are going to get us! + Some idiot has grown mutated bees around here ; Want to take a look at my farm? ; Did you know that I actually cannot do anything else than stand still and greet everybody? - I wonder when the guys will \n get this world ready for me ; Bring it on baby, \n I'm ready for action! ; humm di dum.... - Why I am running? Haven't you heard \n that the bees are coming?! ; Heeelp!!! The bees are going to get us! - Some idiot has grown mutated bees around here ; Want to take a look at my farm? ; Did you know that I actually cannot do anything \n else than stand still and greet everybody? - - - 0 - TechdemoMapObjectLayer - 0.5 + 0 + TechdemoMapTileLayer + 0.5 + diff -r 5ff83f209333 -r 3dff106b945b demos/shooter/run.py --- a/demos/shooter/run.py Fri May 14 16:23:52 2010 +0000 +++ b/demos/shooter/run.py Fri May 14 17:37:42 2010 +0000 @@ -93,60 +93,39 @@ """ self._setting = TDS - + + glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\\\"" engineSetting = self.engine.getSettings() - engineSetting.setDefaultFontGlyphs(str(self._setting.readSetting("FontGlyphs", strip=False))) - engineSetting.setDefaultFontPath(str(self._setting.readSetting("Font"))) - engineSetting.setDefaultFontSize(int(self._setting.readSetting("DefaultFontSize"))) - engineSetting.setBitsPerPixel(int(self._setting.readSetting("BitsPerPixel"))) - engineSetting.setInitialVolume(float(self._setting.readSetting("InitialVolume"))) - engineSetting.setSDLRemoveFakeAlpha(int(self._setting.readSetting("SDLRemoveFakeAlpha"))) - engineSetting.setScreenWidth(int(self._setting.readSetting("ScreenWidth"))) - engineSetting.setScreenHeight(int(self._setting.readSetting("ScreenHeight"))) - engineSetting.setRenderBackend(str(self._setting.readSetting("RenderBackend"))) - engineSetting.setFullScreen(int(self._setting.readSetting("FullScreen"))) + engineSetting.setDefaultFontGlyphs(self._setting.get("FIFE", "FontGlyphs", glyphDft)) + engineSetting.setDefaultFontPath(self._setting.get("FIFE", "Font", "fonts/FreeSans.ttf")) + engineSetting.setDefaultFontSize(self._setting.get("FIFE", "DefaultFontSize", 12)) + engineSetting.setBitsPerPixel(self._setting.get("FIFE", "BitsPerPixel", 0)) + engineSetting.setInitialVolume(self._setting.get("FIFE", "InitialVolume", 5.0)) + engineSetting.setSDLRemoveFakeAlpha(self._setting.get("FIFE", "SDLRemoveFakeAlpha", 1)) + engineSetting.setScreenWidth(self._setting.get("FIFE", "ScreenWidth", 1024)) + engineSetting.setScreenHeight(self._setting.get("FIFE", "ScreenHeight", 768)) + engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL")) + engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", 0)) - try: - engineSetting.setWindowTitle(str(self._setting.readSetting("WindowTitle"))) - engineSetting.setWindowIcon(str(self._setting.readSetting("WindowIcon"))) - except: - pass - - try: - engineSetting.setImageChunkingSize(int(self._setting.readSetting("ImageChunkSize"))) - except: - pass + engineSetting.setWindowTitle(self._setting.get("FIFE", "WindowTitle", "No window title set")) + engineSetting.setWindowIcon(self._setting.get("FIFE", "WindowIcon", "")) + engineSetting.setImageChunkingSize(self._setting.get("FIFE", "ImageChunkSize", 256)) def initLogging(self): """ Initialize the LogManager. """ + + engineSetting = self.engine.getSettings() + logmodules = self._setting.get("FIFE", "LogModules", "controller") - #@todo: load this from settings - logmodules = ["controller", - "event channel", - "audio", - "model", - "metamodel", - "pool", - "vfs", - "video", - "view", - "camera", - "util", - "pool", - "xml", - "exception", - "structures", - "location", - "native loaders", - "loaders", - "gui", - "script"] + #log to both the console and log file + self._log = fifelog.LogManager(self.engine, + self._setting.get("FIFE", "LogToPrompt", "0"), + self._setting.get("FIFE", "LogToFile", "0")) + + self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG) - #log to both the console and log file - self._log = fifelog.LogManager(self.engine, 1, 1) - self._log.setLevelFilter(fife.LogManager.LEVEL_DEBUG) if logmodules: self._log.setVisibleModules(*logmodules) diff -r 5ff83f209333 -r 3dff106b945b demos/shooter/settings-dist.xml --- a/demos/shooter/settings-dist.xml Fri May 14 16:23:52 2010 +0000 +++ b/demos/shooter/settings-dist.xml Fri May 14 17:37:42 2010 +0000 @@ -1,24 +1,25 @@ + - 0 - 1 - OpenGL - 1024 - 768 - 0 - 5.0 - 1 - FIFE - Shooter Demo - - - maps/shrine.xml - fonts/FreeSans.ttf - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" - 16 - controller - False - 1 - 0 - False - False - 256 + + 0 + 1 + OpenGL + 1024 + 768 + 0 + 5.0 + 1 + FIFE - Shooter Demo + + fonts/FreeSans.ttf + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" + 16 + controller ; audio ; vfs ; script ; loaders ; pool ; view ; video ; model ; metamodel ; event_channel ; xml + False + 1 + 0 + + + 100 + diff -r 5ff83f209333 -r 3dff106b945b engine/python/fife/extensions/fife_settings.py --- a/engine/python/fife/extensions/fife_settings.py Fri May 14 16:23:52 2010 +0000 +++ b/engine/python/fife/extensions/fife_settings.py Fri May 14 17:37:42 2010 +0000 @@ -87,6 +87,7 @@ settings = Setting(app_name="myapp") screen_width = settings.readSetting("ScreenWidth") """ + def __init__(self, app_name="", settings_file="", settings_gui_xml=""): """ Initializes the Setting object. @@ -124,10 +125,212 @@ if not os.path.exists(os.path.join(self._appdata, self._settings_file)): shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file)) + self._tree = ET.parse(os.path.join(self._appdata, self._settings_file)) + self._root_element = self._tree.getroot() + self.validateTree() + + def validateTree(self): + """ Iterates the settings tree and prints warning when an invalid tag is found """ + for c in self._root_element.getchildren(): + if c.tag != "Module": + print "Invalid tag in settings.xml. Expected Module, got: ", c.tag + elif c.get("name", "") == "": + print "Invalid tag in settings.xml. Module name is empty." + else: + for e in c.getchildren(): + if e.tag != "Setting": + print "Invalid tag in settings.xml in module: ",c.tag, + print ". Expected Setting, got: ", e.tag + elif c.get("name", "") == "": + print "Invalid tag in settings.xml in module: ",c.tag, + print ". Setting name is empty", e.tag + + def getModuleTree(self, module): + """ + Returns a module element from the settings tree. If no module with the specified + name exists, a new element will be created. + + @param module: The module to get from the settings tree + @type module: C{string} + """ + if not isinstance(module, str) and not isinstance(module, unicode): + raise AttributeError("Settings:getModuleTree: Invalid type for module argument.") + + for c in self._root_element.getchildren(): + if c.tag == "Module" and c.get("name", "") == module: + return c + + # Create module + return ET.SubElement(self._root_element, "Module", {"name":module}) + + def get(self, module, name, defaultValue=None): + """ Gets the value of a specified setting + + @param module: Name of the module to get the setting from + @param name: Setting name + @param defaultValue: Specifies the default value to return if the setting is not found + @type defaultValue: C{str} or C{unicode} or C{int} or C{float} or C{bool} or C{list} or C{dict} + """ + if not isinstance(name, str) and not isinstance(name, unicode): + raise AttributeError("Settings:get: Invalid type for name argument.") + + moduleTree = self.getModuleTree(module) + element = None + for e in moduleTree.getchildren(): + if e.tag == "Setting" and e.get("name", "") == name: + element = e + break + else: + return defaultValue + + e_value = element.text + e_strip = element.get("strip", "1").strip().lower() + e_type = str(element.get("type", "str")).strip() + + if e_value is None: + return defaultValue + + # Strip value + if e_strip == "" or e_strip == "false" or e_strip == "no" or e_strip == "0": + e_strip = False + else: e_strip = True + + if e_type == "str" or e_type == "unicode": + if e_strip: e_value = e_value.strip() + else: + e_value = e_value.strip() + + # Return value + if e_type == 'int': + return int(e_value) + elif e_type == 'float': + return float(e_value) + elif e_type == 'bool': + e_value = e_value.lower() + if e_value == "" or e_value == "false" or e_value == "no" or e_value == "0": + return False + else: + return True + elif e_type == 'str': + return str(e_value) + elif e_type == 'unicode': + return unicode(e_value) + elif e_type == 'list': + return self._deserializeList(e_value) + elif e_type == 'dict': + return self._deserializeDict(e_value) + + def set(self, module, name, value, extra_attrs={}): + """ + Sets a setting to specified value. + + @param module: Module where the setting should be set + @param name: Name of setting + @param value: Value to assign to setting + @type value: C{str} or C{unicode} or C{int} or C{float} or C{bool} or C{list} or C{dict} + @param extra_attrs: Extra attributes to be stored in the XML-file + @type extra_attrs: C{dict} + """ + if not isinstance(name, str) and not isinstance(name, unicode): + raise AttributeError("Settings:set: Invalid type for name argument.") + + moduleTree = self.getModuleTree(module) + e_type = "str" + + if isinstance(value, bool): # This must be before int + e_type = "bool" + value = str(value) + elif isinstance(value, int): + e_type = "int" + value = str(value) + elif isinstance(value, float): + e_type = "float" + value = str(value) + elif isinstance(value, unicode): + e_type = "unicode" + value = unicode(value) + elif isinstance(value, list): + e_type = "list" + value = self._serializeList(value) + elif isinstance(value, dict): + e_type = "dict" + value = self._serializeDict(value) + else: + e_type = "str" + value = str(value) + + for e in moduleTree.getchildren(): + if e.tag != "Setting": continue + if e.get("name", "") == name: + e.text = value + break + else: + attrs = {"name":name, "type":e_type} + for k in extra_attrs: + if k not in attrs: + attrs[k] = extra_args[k] + elm = ET.SubElement(moduleTree, "Setting", attrs) + elm.text = value + + def saveSettings(self): + """ Writes the settings to the settings file """ + self._indent(self._root_element) + self._tree.write(os.path.join(self._appdata, self._settings_file), 'UTF-8') + + def _indent(self, elem, level=0): + """ + Adds whitespace, so the resulting XML-file is properly indented. + Shamelessly stolen from http://effbot.org/zone/element-lib.htm + """ + i = "\n" + level*" " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + self._indent(elem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + + # FIXME: + # These serialization functions are not reliable at all + # This will only serialize the first level of a dict or list + # It will not check the types nor the content for conflicts. + # Perhaps we should add a small serialization library? + def _serializeList(self, list): + """ Serializes a list, so it can be stored in a text file """ + return " ; ".join(list) + + def _deserializeList(self, string): + """ Deserializes a list back into a list object """ + return string.split(" ; ") + + def _serializeDict(self, dict): + """ Serializes a list, so it can be stored in a text file """ + serial = "" + for key in dict: + value = dict[key] + if serial != "": serial += " ; " + serial += str(key)+" : "+str(value) + + return serial + + def _deserializeDict(self, serial): + """ Deserializes a list back into a dict object """ + dict = {} + items = serial.split(" ; ") + for i in items: + kv_pair = i.split(" : ") + dict[kv_pair[0]] = kv_pair[1] + return dict def onOptionsPress(self): """ - Opends the options dialog box. Usually you would bind this to a button. + Opens the options dialog box. Usually you would bind this to a button. """ self.changesRequireRestart = False self.isSetToDefault = False @@ -141,18 +344,48 @@ 'render_backend' : ['OpenGL', 'SDL'] }) self.OptionsDlg.distributeData({ - 'screen_resolution' : self.Resolutions.index(str(self.readSetting("ScreenWidth")) + 'x' + str(self.readSetting("ScreenHeight"))), - 'render_backend' : 0 if str(self.readSetting("RenderBackend")) == "OpenGL" else 1, - 'enable_fullscreen' : int(self.readSetting("FullScreen")), - 'enable_sound' : int(self.readSetting("PlaySounds")) + 'screen_resolution' : self.Resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))), + 'render_backend' : 0 if self.get("FIFE", "RenderBackend") == "OpenGL" else 1, + 'enable_fullscreen' : self.get("FIFE", "FullScreen"), + 'enable_sound' : self.get("FIFE", "PlaySounds") }) self.OptionsDlg.mapEvents({ - 'okButton' : self.saveSettings, + 'okButton' : self.applySettings, 'cancelButton' : self.OptionsDlg.hide, 'defaultButton' : self.setDefaults }) self.OptionsDlg.show() + def applySettings(self): + """ + Writes the settings file. If a change requires a restart of the engine + it notifies you with a small dialog box. + """ + screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound') + render_backend = 'OpenGL' if render_backend is 0 else 'SDL' + if render_backend != self.get("FIFE", "RenderBackend"): + self.set("FIFE", 'RenderBackend', render_backend) + self.changesRequireRestart = True + if int(enable_fullscreen) != int(self.get("FIFE", "FullScreen")): + self.set("FIFE", 'FullScreen', int(enable_fullscreen)) + self.changesRequireRestart = True + if int(enable_sound) != int(self.get("FIFE", "PlaySounds")): + self.set("FIFE", 'PlaySounds', int(enable_sound)) + self.changesRequireRestart = True + if screen_resolution != self.Resolutions.index(str(self.get("FIFE", "ScreenWidth")) + 'x' + str(self.get("FIFE", "ScreenHeight"))): + self.set("FIFE", 'ScreenWidth', int(self.Resolutions[screen_resolution].partition('x')[0])) + self.set("FIFE", 'ScreenHeight', int(self.Resolutions[screen_resolution].partition('x')[2])) + self.changesRequireRestart = True + + if not self.isSetToDefault: + self.saveSettings() + + self.OptionsDlg.hide() + if self.changesRequireRestart: + RestartDlg = pychan.loadXML(StringIO(CHANGES_REQUIRE_RESTART)) + RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide }) + RestartDlg.show() + def setDefaults(self): """ Overwrites the setting file with the default settings-dist.xml file. @@ -160,71 +393,3 @@ shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file)) self.isSetToDefault = True self.changesRequireRestart = True - - def readSetting(self, name, type='int', strip=True, text=False): - if not hasattr(self, 'tree'): - self.tree = ET.parse(os.path.join(self._appdata, self._settings_file)) - self.root_element = self.tree.getroot() - element = self.root_element.find(name) - if element is not None: - element_value = element.text - if element_value is None: - if type == 'int': - return 0 - elif type == 'list': - list = [] - return list - else: - if type == 'int': - return element_value.strip() if strip else element_value - elif type == 'list': - list = [] - list_s = [] - list = str(element_value.strip()).split(";") - for item in list: - item = item.strip() - if text: - item = item.replace('\\n', '\n') - list_s.append(item) - return list_s - elif type == 'bool': - return False if element_value.strip() == 'False' else True - else: - print 'Setting,', name, 'does not exist!' - - def setSetting(self, name, value): - element = self.root_element.find(name) - if element is not None: - if value is not element.text: - element.text = str(value) - else: - print 'Setting,', name, 'does not exist!' - - def saveSettings(self): - """ - Writes the settings file. If a change requires a restart of the engine - it notifies you with a small dialog box. - """ - screen_resolution, render_backend, enable_fullscreen, enable_sound = self.OptionsDlg.collectData('screen_resolution', 'render_backend', 'enable_fullscreen', 'enable_sound') - render_backend = 'OpenGL' if render_backend is 0 else 'SDL' - if render_backend != str(self.readSetting("RenderBackend")): - self.setSetting('RenderBackend', render_backend) - self.changesRequireRestart = True - if int(enable_fullscreen) != int(self.readSetting("FullScreen")): - self.setSetting('FullScreen', int(enable_fullscreen)) - self.changesRequireRestart = True - if int(enable_sound) != int(self.readSetting("PlaySounds")): - self.setSetting('PlaySounds', int(enable_sound)) - self.changesRequireRestart = True - if screen_resolution != self.Resolutions.index(str(self.readSetting("ScreenWidth")) + 'x' + str(self.readSetting("ScreenHeight"))): - self.setSetting('ScreenWidth', int(self.Resolutions[screen_resolution].partition('x')[0])) - self.setSetting('ScreenHeight', int(self.Resolutions[screen_resolution].partition('x')[2])) - self.changesRequireRestart = True - - if not self.isSetToDefault: - self.tree.write(os.path.join(self._appdata, self._settings_file)) - self.OptionsDlg.hide() - if self.changesRequireRestart: - RestartDlg = pychan.loadXML(StringIO(CHANGES_REQUIRE_RESTART)) - RestartDlg.mapEvents({ 'closeButton' : RestartDlg.hide }) - RestartDlg.show() diff -r 5ff83f209333 -r 3dff106b945b tools/editor/scripts/editor.py --- a/tools/editor/scripts/editor.py Fri May 14 16:23:52 2010 +0000 +++ b/tools/editor/scripts/editor.py Fri May 14 17:37:42 2010 +0000 @@ -57,7 +57,7 @@ from gui.menubar import Menu, MenuBar from gui.error import ErrorDialog from mapview import MapView -from settings import Settings +from fife.extensions.fife_settings import Setting def getEditor(): """ Returns the Global editor instance """ @@ -109,7 +109,7 @@ Load the settings from a python file and load them into the engine. Called in the ApplicationBase constructor. """ - self._settings = Settings() + self._settings = Setting(app_name="editor") TDS = self._settings glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\\\"" diff -r 5ff83f209333 -r 3dff106b945b tools/editor/scripts/settings.py --- a/tools/editor/scripts/settings.py Fri May 14 16:23:52 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -# -*- coding: utf-8 -*- - -# #################################################################### -# Copyright (C) 2005-2009 by the FIFE team -# http://www.fifengine.de -# This file is part of FIFE. -# -# FIFE is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# #################################################################### - -import shutil -import os -from fife.extensions.fife_utils import getUserDataDirectory -try: - import xml.etree.cElementTree as ET -except: - import xml.etree.ElementTree as ET - -class Settings(object): - """ This class provides an interface for retrieving and putting settings - to an XML-file. - - Only one instance of this class may exist, or a RuntimeWarning exception - will be raised. Use Settings.instance or Editor.getSettings() to retrieve - an instance of this class. - """ - instance = None # Points to the first initialized instance of this class - def __init__(self, *args, **kwargs): - if Settings.instance is not None: - raise RuntimeWarning("Settings instance has already been initialized! Use Editor.getSettings instead") - - Settings.instance = self - - self._appdata = getUserDataDirectory("fife", "editor") - - if os.path.exists(self._appdata+'/settings.xml') is False: - shutil.copyfile('settings-dist.xml', self._appdata+'/settings.xml') - - self.tree = ET.parse(self._appdata+'/settings.xml') - self.root_element = self.tree.getroot() - self.validateTree() - - def validateTree(self): - """ Iterates the settings tree and prints warning when an invalid tag is found """ - for c in self.root_element.getchildren(): - if c.tag != "Module": - print "Invalid tag in settings.xml. Expected Module, got: ", c.tag - elif c.get("name", "") == "": - print "Invalid tag in settings.xml. Module name is empty." - else: - for e in c.getchildren(): - if e.tag != "Setting": - print "Invalid tag in settings.xml in module: ",c.tag, - print ". Expected Setting, got: ", e.tag - elif c.get("name", "") == "": - print "Invalid tag in settings.xml in module: ",c.tag, - print ". Setting name is empty", e.tag - - def getModuleTree(self, module): - """ Returns a module element from the settings tree. If no module with the specified - name exists, a new element will be created. """ - if not isinstance(module, str) and not isinstance(module, unicode): - raise AttributeError("Settings:getModuleTree: Invalid type for module argument.") - - for c in self.root_element.getchildren(): - if c.tag == "Module" and c.get("name", "") == module: - return c - - # Create module - return ET.SubElement(self.root_element, "Module", {"name":module}) - - def get(self, module, name, defaultValue=None): - """ Gets the value of a specified setting - - defaultValue is returned if the setting does not exist - """ - if not isinstance(name, str) and not isinstance(name, unicode): - raise AttributeError("Settings:get: Invalid type for name argument.") - - moduleTree = self.getModuleTree(module) - element = None - for e in moduleTree.getchildren(): - if e.tag == "Setting" and e.get("name", "") == name: - element = e - break - else: - return defaultValue - - e_value = element.text - e_strip = element.get("strip", "1").strip().lower() - e_type = str(element.get("type", "str")).strip() - - if e_value is None: - return defaultValue - - # Strip value - if e_strip == "" or e_strip == "false" or e_strip == "no" or e_strip == "0": - e_strip = False - else: e_strip = True - - if e_type == "str" or e_type == "unicode": - if e_strip: e_value = e_value.strip() - else: - e_value = e_value.strip() - - # Return value - if e_type == 'int': - return int(e_value) - elif e_type == 'float': - return float(e_value) - elif e_type == 'bool': - e_value = e_value.lower() - if e_value == "" or e_value == "false" or e_value == "no" or e_value == "0": - return False - else: - return True - elif e_type == 'str': - return str(e_value) - elif e_type == 'unicode': - return unicode(e_value) - elif e_type == 'list': - return self._deserializeList(e_value) - elif e_type == 'dict': - return self._deserializeDict(e_value) - - def set(self, module, name, value, extra_attrs={}): - """ - Sets a setting to specified value. - - Parameters: - module (str|unicode): Module where the setting should be set - name (str|unicode): Name of setting - value: Value to assign to setting - extra_attrs (dict): Extra attributes to be stored in the XML-file - """ - if not isinstance(name, str) and not isinstance(name, unicode): - raise AttributeError("Settings:set: Invalid type for name argument.") - - moduleTree = self.getModuleTree(module) - e_type = "str" - - if isinstance(value, bool): # This must be before int - e_type = "bool" - value = str(value) - elif isinstance(value, int): - e_type = "int" - value = str(value) - elif isinstance(value, float): - e_type = "float" - value = str(value) - elif isinstance(value, unicode): - e_type = "unicode" - value = unicode(value) - elif isinstance(value, list): - e_type = "list" - value = self._serializeList(value) - elif isinstance(value, dict): - e_type = "dict" - value = self._serializeDict(value) - else: - e_type = "str" - value = str(value) - - for e in moduleTree.getchildren(): - if e.tag != "Setting": continue - if e.get("name", "") == name: - e.text = value - break - else: - attrs = {"name":name, "type":e_type} - for k in extra_attrs: - if k not in attrs: - attrs[k] = extra_args[k] - elm = ET.SubElement(moduleTree, "Setting", attrs) - elm.text = value - - def saveSettings(self): - """ Save settings into settings.xml """ - self._indent(self.root_element) - self.tree.write(self._appdata+'/settings.xml', 'UTF-8') - - def _indent(self, elem, level=0): - """ - Adds whitespace, so the resulting XML-file is properly indented. - Shamelessly stolen from http://effbot.org/zone/element-lib.htm - """ - i = "\n" + level*" " - if len(elem): - if not elem.text or not elem.text.strip(): - elem.text = i + " " - if not elem.tail or not elem.tail.strip(): - elem.tail = i - for elem in elem: - self._indent(elem, level+1) - if not elem.tail or not elem.tail.strip(): - elem.tail = i - else: - if level and (not elem.tail or not elem.tail.strip()): - elem.tail = i - - # FIXME: - # These serialization functions are not reliable at all - # This will only serialize the first level of a dict or list - # It will not check the types nor the content for conflicts. - # Perhaps we should add a small serialization library? - def _serializeList(self, list): - """ Serializes a list, so it can be stored in a text file """ - return " ; ".join(list) - - def _deserializeList(self, string): - """ Deserializes a list back into a list object """ - return string.split(" ; ") - - def _serializeDict(self, dict): - """ Serializes a list, so it can be stored in a text file """ - serial = "" - for key in dict: - value = dict[key] - if serial != "": serial += " ; " - serial += str(key)+" : "+str(value) - - return serial - - def _deserializeDict(self, serial): - """ Deserializes a list back into a dict object """ - dict = {} - items = serial.split(" ; ") - for i in items: - kv_pair = i.split(" : ") - dict[kv_pair[0]] = kv_pair[1] - return dict -