##################################################################### # -*- coding: iso-8859-1 -*- # # # # Frets on Fire # # Copyright (C) 2006 Sami Kyöstilä # # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program 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 General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software # # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # # MA 02110-1301, USA. # ##################################################################### from OpenGL.GL import * from View import Layer import gc import threading import Log import Version import os import datetime import zipfile import Theme import Stage class DebugLayer(Layer): """A layer for showing some debug information.""" def __init__(self, engine): self.engine = engine #gc.set_debug(gc.DEBUG_LEAK) def className(self, instance): return str(instance.__class__).split(".")[1] def render(self, visibility, topMost): self.engine.view.setOrthogonalProjection(normalize = True) try: font = self.engine.data.font scale = 0.0008 glColor3f(.25, 1, .25) x, y = (.05, .05) h = font.getHeight() * scale font.render("Tasks:", (x, y), scale = scale) for task in self.engine.tasks + self.engine.frameTasks: font.render(self.className(task), (x + .1, y), scale = scale) y += h x, y = (.5, .05) font.render("Layers:", (x, y), scale = scale) for layer in self.engine.view.layers + self.engine.view.incoming + self.engine.view.outgoing + self.engine.view.visibility.keys(): font.render(self.className(layer), (x + .1, y), scale = scale) y += h x, y = (.05, .4) font.render("Scenes:", (x, y), scale = scale) if "world" in dir(self.engine.server): for scene in self.engine.server.world.scenes: font.render(self.className(scene), (x + .1, y), scale = scale) y += h x, y = (.5, .4) font.render("Loaders:", (x, y), scale = scale) for loader in self.engine.resource.loaders: font.render(str(loader), (x + .1, y), scale = scale) y += h x, y = (.5, .55) font.render("Input:", (x, y), scale = scale) for listener in self.engine.input.mouseListeners + \ self.engine.input.keyListeners + \ self.engine.input.systemListeners + \ self.engine.input.priorityKeyListeners: font.render(self.className(listener), (x + .1, y), scale = scale) y += h x, y = (.05, .55) font.render("System:", (x, y), scale = scale) font.render("%d threads" % threading.activeCount(), (x + .1, y), scale = scale) y += h font.render("%.2f fps" % self.engine.fpsEstimate, (x + .1, y), scale = scale) y += h font.render("%d sessions, server %s" % (len(self.engine.sessions), self.engine.server and "on" or "off"), (x + .1, y), scale = scale) #y += h #font.render("%d gc objects" % len(gc.get_objects()), (x + .1, y), scale = scale) #y += h #font.render("%d collected" % gc.collect(), (x + .1, y), scale = scale) finally: self.engine.view.resetProjection() def gcDump(self): import World before = len(gc.get_objects()) coll = gc.collect() after = len(gc.get_objects()) Log.debug("%d GC objects collected, total %d -> %d." % (coll, before, after)) fn = "gcdump.txt" f = open(fn, "w") n = 0 gc.collect() for obj in gc.garbage: try: print >>f, obj n += 1 except: pass f.close() Log.debug("Wrote a dump of %d GC garbage objects to %s." % (n, fn)) def debugOut(self, engine): try: f = open("debug.log", "w+") except IOError: # fallback for unix (games dir read-only) import Resource # evilynux - Under MacOS X, put the logs in ~/Library/Logs if( os.uname()[0] == "Darwin" ): logFile = open(os.path.join(Resource.getWritableResourcePath(), "..", "..", "Logs", Version.appName(), "debug.log"), "w+") else: # GNU/Linux et al. f = open(os.path.join(Resource.getWritableResourcePath(), 'debug.log'), "w+") version = Version.version() currentDir = os.getcwd() dataDir = Version.dataPath() translationDir = dataDir + "/translations" modsDir = dataDir + "/mods" f.write("Date = %s\n" % datetime.datetime.now()) f.write("\nVersion = %s\n" % version) f.write("\nOS = %s\n" % os.name) f.write("\nCurrent Directory = %s\n" % currentDir) self.directoryList(f, currentDir) f.write("\nData Directory = %s\n" % dataDir) self.directoryList(f, dataDir) zip_path = os.path.join(dataDir, 'library.zip') # no library.zip on regular unix installation if os.path.exists(zip_path): f.write("\nLibrary.zip\n") zip = zipfile.ZipFile(zip_path, 'r') for info in zip.infolist(): fileName = info.filename fileCSize = info.compress_size fileSize = info.file_size fileDate = datetime.datetime(*(info.date_time)) f.write("%s, %s, %s, %s\n" % (fileName, fileCSize, fileSize, fileDate)) f.write("\nTranslation Directory = %s\n" % translationDir) self.directoryList(f, translationDir) f.write("\nMods Directory = %s\n" % modsDir) self.directoryList(f, modsDir) mods = os.listdir(modsDir) for mod in mods: modDir = os.path.join(modsDir, mod) if os.path.isdir(modDir): f.write("\nMod Directory = %s\n" % modDir) self.directoryList(f, modDir) f.write("\nFretsonfire.ini\n") engine.config.config.write(f) # No write() in Theme #f.write("\nTheme.ini\n") #Theme.write(f, engine.config) f.write("\nStage.ini\n") stage = Stage.Stage(self, self.engine.resource.fileName("stage.ini")) stage.config.write(f) f.close() def directoryList(self, f, root): files = os.listdir(root) for fileName in files: fileSize = os.path.getsize(os.path.join(root, fileName)) mTime = datetime.datetime.utcfromtimestamp(os.path.getmtime(os.path.join(root, fileName))) cTime = datetime.datetime.utcfromtimestamp(os.path.getctime(os.path.join(root, fileName))) aTime = datetime.datetime.utcfromtimestamp(os.path.getatime(os.path.join(root, fileName))) f.write("%s, %s, %s, %s, %s\n" % (fileName, fileSize, mTime, cTime, aTime))