""" Map editor! We are building a big game world, yes we are... """ import sys # stdout and stderr go to BootstrapLog, until we've got a widget # built to show the text: TempLogFile = open("BootstrapLog.txt", "wb") sys.stdout = TempLogFile sys.stderr = TempLogFile import wx import os import types import traceback import UIMap import Global import GameMap import GameInfo RoomGridSize = 50 HalfRoomGridSize = RoomGridSize / 2 class MenuID: """ ID numbers for various menu entries, huzzah. """ LoadMap = 100 NewMap = 101 SaveMap = 102 SaveMapAs = 103 RecentFiles = 110 RecentFiles1 = 111 RecentFiles2 = 112 RecentFiles3 = 113 RecentFiles4 = 114 Exit = 104 Help = 300 About = 301 MapWildCard = "XML file (*.xml)|*.xml|" \ "All files (*.*)|*.*" \ class RoomSelectorClass: """ A box drawn around the currently-selected room. """ def __init__(self, RoomWidget, Canvas): self.RoomWidget = RoomWidget self.X = self.RoomWidget.X - 2 self.Y = self.RoomWidget.Y - 2 self.Canvas = Canvas self.Image = Global.ImageHandler.GetImage("RoomSelector.png") self.Width = self.Image.GetWidth() self.Height = self.Image.GetHeight() self.ShownFlag = 1 self.DrawFlag = 0 def Show(self): self.ShownFlag = 1 self.DrawFlag = 0 def Hide(self): self.ShownFlag = 0 self.DrawFlag = 0 def Draw(self, DeviceContext, op = wx.COPY): if self.ShownFlag and self.Image and self.Image.Ok(): MemoryDC = wx.MemoryDC() MemoryDC.SelectObject(self.Image) self.X = self.RoomWidget.X - 2 self.Y = self.RoomWidget.Y - 2 DeviceContext.Blit(self.X, self.Y, self.Width, self.Height, MemoryDC, 0, 0, op, True) if not self.DrawFlag: #self.Canvas.RefreshRect((self.X, self.Y, self.Width, self.Height)) self.DrawFlag = 1 return True else: return False def SetXY(self): self.X = self.RoomWidget.X - 2 self.Y = self.RoomWidget.Y - 2 class MapEditCanvas(UIMap.BaseUIMap): def __init__(self, Parent, App, ID): self.ThrobTick = 0 UIMap.BaseUIMap.__init__(self, Parent, App, ID) self.App = App self.SetBackgroundColour("red") # for debugging self.RoomWidgets = [] self.PathWidgets = [] self.Throbbers = [] self.RoomSelector = None Image = Global.ImageHandler.GetImage("MapBack.png") self.BackgroundImage = Image #BitmapFromImage(Image) self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.Bind(wx.EVT_RIGHT_DOWN, self.OnLeftDown) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightClick) self.Bind(wx.EVT_CHAR, self.OnKeyboardCharacter) #self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClick) #self.Bind(wx.EVT_TIMER, self.OnTimer) self.InitAnimation() NewMap = GameMap.MapClass() self.EnterMap(NewMap) def HandleDeleteKey(self): "Handle DELETE key (deletes the selected room)" if not self.SelectedRoom: return Global.RoomInfoPanel.SelectRoom(None) # Kill room widget: self.RoomWidgets.remove(self.SelectedRoom) # Kill path widgets: for PathWidget in self.PathWidgets[:]: if PathWidget.WidgetA == self.SelectedRoom: self.PathWidgets.remove(PathWidget) # Kill the room itself: self.Map.DeleteRoom(self.SelectedRoom.Room) self.RefreshRect(self.SelectedRoom.GetRect()) self.SelectedRoom = None self.RefreshRoomSelector() self.RoomSelector = None def OnKeyboardCharacter(self, Event): KeyCode = Event.GetKeyCode() print KeyCode if KeyCode == wx.WXK_DELETE: self.HandleDeleteKey() if KeyCode == ord("t"): # The key T cycles room types! if not self.SelectedRoom: return if self.SelectedRoom.Room.Type == GameMap.RoomTypes.Quest: self.SelectedRoom.Room.Type = GameMap.RoomTypes.Empty elif self.SelectedRoom.Room.Type == GameMap.RoomTypes.Empty: self.SelectedRoom.Room.Type = GameMap.RoomTypes.Treasure elif self.SelectedRoom.Room.Type == GameMap.RoomTypes.Treasure: self.SelectedRoom.Room.Type = GameMap.RoomTypes.Stairway elif self.SelectedRoom.Room.Type == GameMap.RoomTypes.Stairway: self.SelectedRoom.Room.Type = GameMap.RoomTypes.Teleporter else: self.SelectedRoom.Room.Type = GameMap.RoomTypes.Quest print "Room type:", self.SelectedRoom.Room.Type ImageStub = self.SelectedRoom.Room.GetImageName(0) self.SelectedRoom.Image = Global.ImageHandler.GetImage("%s.png"%ImageStub) self.RefreshRect(self.SelectedRoom.GetRect()) return if KeyCode >= ord('0') and KeyCode <= ord('5'): # This keycode sets the color of a room. if not self.SelectedRoom: return self.SelectedRoom.Room.Color = KeyCode - ord('0') ImageStub = self.SelectedRoom.Room.GetImageName(0) self.SelectedRoom.Image = Global.ImageHandler.GetImage("%s.png"%ImageStub) self.RefreshRect(self.SelectedRoom.GetRect()) def OnTimer(self, Event): #for Throbber in self.Throbbers: # Throbber.Update() self.ThrobTick += 1 if self.ThrobTick > 100: self.ThrobTick = 0 for Throbber in self.Throbbers: Throbber.Update() def OnPaint(self, Event): "Fired whenever a paint event occurs" DeviceContext = wx.PaintDC(self) self.PrepareDC(DeviceContext) self.DrawPaths(DeviceContext) self.DrawRooms(DeviceContext) self.DrawThrobbers(DeviceContext) self.DrawRoomSelector(DeviceContext) def DrawRoomSelector(self, DeviceContext): if self.RoomSelector and not self.DragRoom: self.RoomSelector.Draw(DeviceContext) def RefreshRoomSelector(self): if not self.RoomSelector: return self.RefreshRect((self.RoomSelector.X, self.RoomSelector.Y, self.RoomSelector.Width, self.RoomSelector.Height), True) def EnterMap(self, Map): self.Map = Map self.RoomSelector = None self.ConstructRoomWidgets() # base class self.ConstructPathWidgets() # base class self.SelectedRoom = None self.DragRoom = None self.DragImage = None self.DraggingFlag = 0 self.Refresh() #self.ConstructThrobbers() def OnLeftUp(self, Event): if not self.DragRoom or not self.DraggingFlag: self.DragRoom = None self.RefreshRoomSelector() self.Update() return # Put the dragged room in its new position: (EventX, EventY) = Event.GetPosition() print "%s, %s Alt: %s"%(EventX, EventY, Event.AltDown()) X = EventX - (self.DragRoom.Image.GetWidth() / 2) Y = EventY - (self.DragRoom.Image.GetHeight() / 2) self.RefreshRect(self.DragRoom.GetRect()) if (Event.AltDown()): Spillover = X % RoomGridSize if (Spillover < HalfRoomGridSize): X -= Spillover else: X += RoomGridSize - Spillover Spillover = Y % RoomGridSize if (Spillover < HalfRoomGridSize): Y -= Spillover else: Y += RoomGridSize - Spillover self.DragRoom.Room.X = X #- (self.DragRoom.Image.GetWidth() / 2) self.DragRoom.Room.Y = Y #- (self.DragRoom.Image.GetHeight() / 2) print "Now pos: %s, %s"%(self.DragRoom.Room.X, self.DragRoom.Room.Y) self.DragRoom.X = self.DragRoom.Room.X self.DragRoom.Y = self.DragRoom.Room.Y self.RefreshRect(self.DragRoom.GetRect()) if self.RoomSelector: self.RoomSelector.Show() self.RoomSelector.SetXY() self.RefreshRoomSelector() # Re-show paths: for Path in self.PathWidgets: if Path.WidgetA == self.DragRoom or Path.WidgetB == self.DragRoom: Path.ReviseCoords() Path.ShownFlag = 1 self.RefreshBetweenRooms(Path.WidgetA, Path.WidgetB) # Stop dragging: self.DragRoom = None self.DraggingFlag = 0 self.Update() def RefreshBetweenRooms(self, RoomA, RoomB): MinX = min(RoomA.X, RoomB.X) MinY = min(RoomA.Y, RoomB.Y) MaxX = max(RoomA.X + RoomA.Image.GetWidth(), RoomB.X + RoomB.Image.GetWidth()) MaxY = max(RoomA.Y + RoomA.Image.GetHeight(), RoomB.Y + RoomB.Image.GetHeight()) self.RefreshRect((MinX, MinY, MaxX - MinX, MaxY - MinY)) def RightClickAddRoom(self, Event): """ Helper for right-click event handler. If they right-click an empty area, we add a room! """ (EventX, EventY) = Event.GetPosition() Image = Global.ImageHandler.GetImage("Room.Gray.png") X = EventX - (Image.GetWidth() / 2) Y = EventY - (Image.GetHeight() / 2) # Alt-right-click adds a room in the GRID: if (Event.AltDown()): Spillover = X % RoomGridSize if (Spillover < HalfRoomGridSize): X -= Spillover else: X += RoomGridSize - Spillover Spillover = Y % RoomGridSize if (Spillover < HalfRoomGridSize): Y -= Spillover else: Y += RoomGridSize - Spillover Room = self.Map.AddRoom(X, Y) RoomWidget = UIMap.RoomWidget(Room, Image) self.RoomWidgets.append(RoomWidget) print "Refresh room rect:", RoomWidget.GetRect() self.RefreshRect(RoomWidget.GetRect()) def OnRightClick(self, Event): """ Right-click event handler. Add rooms, toggle paths, cycle door colors. """ RoomWidget = self.FindClickedRoom(Event.GetPosition()) if not RoomWidget: self.RightClickAddRoom(Event) return # Right click on a room: add/drop a path between two rooms! if not self.SelectedRoom: return RoomA = self.SelectedRoom RoomB = RoomWidget # If they re-clicked the selected room, don't try to add a path: if RoomA == RoomB: return # Find any OLD path between the rooms: OldPathWidget = None for PathWidget in self.PathWidgets[:]: if (PathWidget.WidgetA == RoomA and PathWidget.WidgetB == RoomB) or \ (PathWidget.WidgetB == RoomA and PathWidget.WidgetA == RoomB): OldPathWidget = PathWidget if Event.AltDown() and OldPathWidget: self.RightClickCycleDoors(OldPathWidget) return if OldPathWidget: # Purge the OLD path between the rooms: RoomA.Room.Paths.remove(OldPathWidget.Path) RoomB.Room.Paths.remove(OldPathWidget.Path) self.PathWidgets.remove(OldPathWidget) self.RefreshBetweenRooms(self.SelectedRoom, RoomWidget) return # Create the Path object and the PathWidget: Path = self.Map.AddPath(self.SelectedRoom.Room, RoomWidget.Room) PathWidget = UIMap.UIPath(self.SelectedRoom, RoomWidget, Path) self.PathWidgets.append(PathWidget) self.RefreshBetweenRooms(self.SelectedRoom, RoomWidget) self.Update() def RightClickCycleDoors(self, PathWidget): """ Alt-right-click adds a DOOR between rooms, and cycles door colors. """ if (PathWidget.Path.DoorColor == None): PathWidget.Path.DoorColor = 0 PathWidget.Path.DoorColor += 1 if (PathWidget.Path.DoorColor == GameMap.RoomColors.Count): PathWidget.Path.DoorColor = None PathWidget.GetImage() self.RefreshBetweenRooms(PathWidget.WidgetA, PathWidget.WidgetB) def OnLeftDown(self, Event): RoomWidget = self.FindClickedRoom(Event.GetPosition()) if not RoomWidget: Global.RoomInfoPanel.SelectRoom(None) self.RefreshRoomSelector() self.SelectedRoom = None self.RoomSelector = None Event.Skip() return if RoomWidget != self.SelectedRoom: Global.RoomInfoPanel.SelectRoom(RoomWidget.Room) self.RefreshRoomSelector() self.SelectedRoom = RoomWidget self.RoomSelector = RoomSelectorClass(self.SelectedRoom, self) self.DragRoom = RoomWidget self.DraggingFlag = 0 (self.DragStartX, self.DragStartY) = Event.GetPosition() def OnMotion(self, Event): # If we're not dragging, ignore the event: if not self.DragRoom or not Event.Dragging() or not Event.LeftIsDown(): return # If we've clicked a room, but haven't created the DragImage to # start the drag: (EventX, EventY) = Event.GetPosition() if self.DragRoom and not self.DraggingFlag: Tolerance = 3 DeltaX = abs(EventX - self.DragStartX) DeltaY = abs(EventY - self.DragStartY) if (DeltaX <= Tolerance and DeltaY <= Tolerance): return # Ok, we're dragging now! self.DraggingFlag = 1 self.DragRoom.ShownFlag = 0 if self.RoomSelector: self.RoomSelector.Hide() self.RefreshRoomSelector() self.Update() for Path in self.PathWidgets: if Path.WidgetA == self.DragRoom or Path.WidgetB == self.DragRoom: self.RefreshBetweenRooms(Path.WidgetA, Path.WidgetB) #Path.ShownFlag = 0 # TEMP: for Path in self.PathWidgets: if Path.WidgetA == self.DragRoom or Path.WidgetB == self.DragRoom: self.RefreshBetweenRooms(Path.WidgetA, Path.WidgetB) self.RefreshRect(self.DragRoom.GetRect(), True) self.DragRoom.X += (EventX - self.DragStartX) self.DragRoom.Y += (EventY - self.DragStartY) self.DragStartX = EventX self.DragStartY = EventY self.DragRoom.ShownFlag = 1 self.RefreshRect(self.DragRoom.GetRect()) # TEMP: for Path in self.PathWidgets: if Path.WidgetA == self.DragRoom or Path.WidgetB == self.DragRoom: Path.ReviseCoords() self.RefreshBetweenRooms(Path.WidgetA, Path.WidgetB) self.Update() #self.DragImage = wx.DragImage(self.DragRoom.Image) #self.DragRoom.Move(Event.GetPosition()) #self class RoomInfoPanelClass(wx.Panel): """ The RoomInfoPanel is displayed to the right of the map, and allows convenient editing of quest IDs and treasures and such. """ def __init__(self, Parent, App, ID = -1): wx.Panel.__init__(self, Parent, ID) self.App = App self.Room = None Global.RoomInfoPanel = self self.BuildWidgets() def SelectRoom(self, Room): """ Called when a new room (or NO room) is selected """ print "* SELECT ROOM:", Room, type(Room) self.Room = Room if Room == None: self.TextRoomID.SetValue("") self.TextQuestID.SetValue("") self.TextQuestName.SetValue("") self.TextQuestGameName.SetValue("") self.TextNotes.SetValue("") return self.TextRoomID.SetValue(str(Room.ID)) self.SetQuest(Room.QuestID) if Room.Notes == None: Room.Notes = "" self.TextNotes.SetValue(Room.Notes) def SetQuest(self, QuestID): self.TextQuestID.SetValue(str(QuestID)) if type(QuestID) == type(""): try: QuestID = int(QuestID) except: QuestID = None try: Quest = Global.Metagame.Quests[QuestID] self.TextQuestName.SetValue(Quest.Name) self.TextQuestGameName.SetValue(Quest.DriverName) except: self.TextQuestName.SetValue("???") self.TextQuestGameName.SetValue("???") def OnQuestIDChanged(self, Event): "Triggered when user types quest ID stuff!" if not self.Room: self.TextQuestID.SetValue("") Event.Skip() return try: ID = self.TextQuestID.GetValue() except: return # ignore non-int values self.Room.QuestID = ID self.SetQuest(ID) def OnNotesChanged(self, Event): if not self.Room: self.TextNotes.SetValue("") Event.Skip() return self.Room.Notes = Event.GetString() def BuildWidgets(self): self.SetBackgroundColour("gray") # Room ID: LabelRoomID = wx.StaticText(self, -1, "Room ID") self.TextRoomID = wx.TextCtrl(self, -1, "", style = wx.TE_READONLY) self.TextRoomID.SetBackgroundColour("gray") # QuestID: LabelQuestID = wx.StaticText(self, -1, "Quest ID") self.TextQuestID = wx.TextCtrl(self, -1, "") self.Bind(wx.EVT_TEXT, self.OnQuestIDChanged, self.TextQuestID) # Quest game name: LabelQuestGameName = wx.StaticText(self, -1, "GameName") self.TextQuestGameName = wx.TextCtrl(self, -1, "", style = wx.TE_READONLY) self.TextQuestGameName.SetBackgroundColour("gray") # Quest name: LabelQuestName = wx.StaticText(self, -1, "Name") self.TextQuestName = wx.TextCtrl(self, -1, "", style = wx.TE_READONLY) self.TextQuestName.SetBackgroundColour("gray") # Notes: LabelNotes = wx.StaticText(self, -1, "Notes") self.TextNotes = wx.TextCtrl(self, -1, "") self.Bind(wx.EVT_TEXT, self.OnNotesChanged, self.TextNotes) # Layout: Sizer = wx.FlexGridSizer(cols = 2, hgap = 4, vgap = 4) Sizer.AddMany([LabelRoomID, self.TextRoomID, LabelQuestID, self.TextQuestID, LabelQuestGameName, self.TextQuestGameName, LabelQuestName, self.TextQuestName, LabelNotes, self.TextNotes ]) Border = wx.BoxSizer(wx.VERTICAL) Border.Add(Sizer, 0, wx.ALL, 25) #self.SetSizer(Sizer) self.SetSizer(Border) self.SetAutoLayout(True) class MapEditorFrame(wx.Frame): def __init__(self, App, Parent, Title): self.App = App wx.Frame.__init__(self, Parent, -1, Title, size = (900, 600)) self.CurrentMapPath = None self.MapChangedFlag = 0 self.BuildWidgets() def BuildWidgets(self): self.BuildMenuWidgets() # Add a log window, for error messages to spew to: self.LogWindow = wx.TextCtrl(self, style = wx.TE_MULTILINE | wx.TE_READONLY) # Build the upper frame: self.UpperPanel = wx.Panel(self) self.MapCanvas = MapEditCanvas(self.UpperPanel, self.App, -1) self.MapCanvas.SetBackgroundColour("red") self.RoomInfoPanel = RoomInfoPanelClass(self.UpperPanel, self.App) UpperBox = wx.BoxSizer(wx.HORIZONTAL) UpperBox.Add(self.MapCanvas, 10, wx.EXPAND) UpperBox.Add(self.RoomInfoPanel, 3, wx.EXPAND) self.UpperPanel.SetAutoLayout(True) self.UpperPanel.SetSizer(UpperBox) self.UpperPanel.Layout() # LAYOUT: ...is fairly simple! Bottom is the log window. Top is # split between MAP CANVAS and ROOM WIDGETS. Box = wx.BoxSizer(wx.VERTICAL) Box.Add(self.UpperPanel, 10, wx.EXPAND) Box.Add(self.LogWindow, 3, wx.EXPAND) #box.Add(panel2, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(Box) self.Layout() def BuildMenuWidgets(self): MenuBar = wx.MenuBar() ############# Menu = wx.Menu() Menu.Append(MenuID.LoadMap, "&Open map...", "") Menu.Append(MenuID.NewMap, "&New map...", "") Menu.Append(MenuID.SaveMap, "&Save map...", "") Menu.Append(MenuID.SaveMapAs, "Save map &as...", "") Menu.AppendSeparator() Menu.Append(MenuID.Exit, "E&xit", "") Menu.AppendSeparator() for FileIndex in range(len(self.App.RecentFiles)): Path = self.App.RecentFiles[FileIndex] if len(Path) > 50: Path = "...%s"%Path[-47:] Menu.Append(MenuID.RecentFiles + FileIndex, "&%s %s"%(FileIndex + 1, Path), "") MenuBar.Append(Menu, "File") # Bind menu events: self.Bind(wx.EVT_MENU, self.MenuLoadMap, id = MenuID.LoadMap) self.Bind(wx.EVT_MENU, self.MenuNewMap, id = MenuID.NewMap) self.Bind(wx.EVT_MENU, self.MenuSaveMap, id = MenuID.SaveMap) self.Bind(wx.EVT_MENU, self.MenuSaveMapAs, id = MenuID.SaveMapAs) self.Bind(wx.EVT_MENU, self.MenuExit, id = MenuID.Exit) self.Bind(wx.EVT_MENU, lambda L=1: self.MenuOpenRecent(L), id = MenuID.RecentFiles) self.Bind(wx.EVT_MENU, self.MenuOpenRecent, id = MenuID.RecentFiles1) self.Bind(wx.EVT_MENU, self.MenuOpenRecent, id = MenuID.RecentFiles2) self.Bind(wx.EVT_MENU, self.MenuOpenRecent, id = MenuID.RecentFiles3) self.Bind(wx.EVT_MENU, self.MenuOpenRecent, id = MenuID.RecentFiles4) # self.SetMenuBar(MenuBar) def MenuOpenRecent(self, Path, Event = None): print "*** OPEN:", Path def MenuExit(self, Event): print "MenuExit!" self.Close() def MenuSaveMap(self, Event): if self.CurrentMapPath == None: self.MenuSaveMapAs(Event) else: self.MapCanvas.Map.SaveToFile(self.CurrentMapPath) def MenuLoadMap(self, Event): Dialog = wx.FileDialog(self, message="Choose a map file", defaultDir = os.getcwd(), defaultFile = "", wildcard = MapWildCard, style=wx.OPEN | wx.CHANGE_DIR) # Show the dialog and retrieve the user response. If it is the OK response, # process the data. if Dialog.ShowModal() == wx.ID_OK: # This returns a Python list of files that were selected. FilePath = Dialog.GetPath() try: Map = GameMap.MapClass() Map.ParseFromFile(FilePath) except: traceback.print_exc() return self.CurrentMapPath = FilePath self.MapCanvas.EnterMap(Map) def MenuSaveMapAs(self, Event): Dialog = wx.FileDialog(self, message="Save map as ...", defaultDir = os.getcwd(), defaultFile = "", wildcard = MapWildCard, style = wx.SAVE) if Dialog.ShowModal() == wx.ID_OK: self.CurrentMapPath = Dialog.GetPath() self.MapCanvas.Map.SaveToFile(self.CurrentMapPath) print "Map saved to %s"%self.CurrentMapPath def MenuNewMap(self, Event): if self.MapChangedFlag: Dialog = wx.MessageDialog(self, 'Are you sure?', 'Are you sure?', wx.YES_NO | wx.ICON_INFORMATION) Result = Dialog.ShowModal() print "RESULT:", Result Dialog.Destroy() if Result == wx.ID_OK: return Map = GameMap.MapClass() self.MapCanvas.EnterMap(Map) self.Refresh() class MapEditorApp(wx.App): def __init__(self, *args, **kw): wx.App.__init__(self, 0, *args, **kw) def LoadRecentFileList(self): self.RecentFiles = [] try: File = open("MapEditor.cfg", "rb") LineNumber = 0 for FileLine in File.xreadlines(): LineNumber += 1 Path = FileLine.strip() if os.path.exists(Path): self.RecentFiles.append(Path) if len(self.RecentFiles) >= 5 or LineNumber >= 10: break except: print "(unable to load recent-files list)" def OnInit(self): print ">>>>>>OnInit() called!" self.LoadRecentFileList() self.BuildWidgets() self.keepGoing = True return True def BuildWidgets(self): print "Building widgets..." self.Frame = MapEditorFrame(self, None, "NecroMap") self.Frame.Show(True) self.SetTopWindow(self.Frame) self.BuildIcon() def BuildIcon(self): import win32api exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None)) Icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO) self.Frame.SetIcon(Icon) def RedirectStdout(self): # Redirect LOGGING: sys.stdout = self.Frame.LogWindow sys.stderr = self.Frame.LogWindow if __name__ == "__main__": print "Load quests into memory..." FileName = os.path.join("Quests", "Games.xml") GameInfo.ParseGameInfoFromFile(FileName) Global.Metagame = GameMap.MetagameClass() ErrorCount = Global.Metagame.Load(os.path.join("Quests", "Demo", "MapDemo.qst")) print "Instantiate app:" Global.ImageHandler = Global.ImageHandlerClass() App = MapEditorApp() Global.App = App App.RedirectStdout() TempLogFile.close() App.MainLoop()