Mercurial > traipse_dev
view orpg/map/_canvas.py @ 21:fdd70f11bc7e traipse_dev
One too many deletes last time. This run tested on Linux and working
author | sirebral |
---|---|
date | Sat, 25 Jul 2009 19:28:21 -0500 |
parents | 4385a7d0efd1 |
children |
line wrap: on
line source
from threading import Lock import mimetypes import xml.dom.minidom as minidom import wx import orpg.dirpath from orpg.orpgCore import * from orpg.tools.rgbhex import RGBHex from _object import * from _circles import MapCircle from _text import MapText from _lines import MapLine from _grid import GridLayer from _fog import FogLayer USE_BUFFER = True if "wxMAC" in wx.PlatformInfo: USE_BUFFER = False class MapCanvas(wx.ScrolledWindow): def __init__(self, parent, openrpg): wx.ScrolledWindow.__init__(self, parent, wx.ID_ANY, style=wx.HSCROLL | wx.VSCROLL | wx.NO_FULL_REPAINT_ON_RESIZE | wx.SUNKEN_BORDER) self.openrpg = openrpg self.log = self.openrpg.get_component("log") self.xml = self.openrpg.get_component("xml") self.dir_struct = self.openrpg.get_component("dir_struct") self.validate = self.openrpg.get_component("validate") self.settings = self.openrpg.get_component("settings") self.session = self.openrpg.get_component("session") self.chat = self.openrpg.get_component("chat") self.lock = Lock() self.RGBHex = RGBHex() self.toolWnd = parent self.shift = False self.ctrl = False self.selectedObjects = [] self.overObjects = [] self._objectId = 0 self.gridLayer = GridLayer(self) self.circleLayer = MapCircle(self) self.textLayer = MapText(self) self.lineLayer = MapLine(self) self.fogLayer = FogLayer(self) self.zOrder = {} self.zOrder['tiles'] = [] self.zOrder["back"] = [] self.zOrder["front"] = [] self.bgImage = None self.bgType = 'Image' self.bgPath = None self.backgroundColor = '#008040' self.gridType = 'Square' self.gridLines = wx.SOLID self.gridSnap = True self.gridSize = 60 self.gridColor = "#000000" self.whiteboardColor = "#000000" self.zoomScale = 1.0 self.lastZoomTime = time.time() self.lastZoomScale = 1.0 self.useFog = False self.fogRegion = [] self.fogColor = "#000000" self.zoomScale = 1.0 self.lastZoomTime = time.time() self.lastZoomScale = 1.0 self.zoomTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnZoomTimer, self.zoomTimer) #self.zoomTimer.Start(1000) self.imageCache = {} self._SetSize((1000,1000)) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOUSEWHEEL, self.OnZoom) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_SCROLLWIN, self.OnScroll) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnBackground) self.Bind(wx.EVT_KEY_DOWN, self.OnKey) self.Bind(wx.EVT_KEY_UP, self.OnKey) self.Bind(EVT_ENTER_OBJECT, self.EnterObject) self.Bind(EVT_LEAVE_OBJECT, self.LeaveObject) self.Bind(EVT_SELECT_OBJECT, self.ObjectSelected) self.Bind(EVT_DESELECT_OBJECT, self.ObjectDeselected) self.roleTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnRoleTimer, self.roleTimer) wx.CallAfter(self.OnSize, None) #Public API def UpdateMap(self, send=True): cdc = wx.ClientDC(self) self.PrepareDC(cdc) cdc.SetBackgroundMode(wx.TRANSPARENT) if USE_BUFFER: bdc = wx.BufferedDC(cdc, self._buffer) bdc.Clear() dc = wx.GraphicsContext.Create(bdc) else: cdc.Clear() dc = wx.GraphicsContext.Create(cdc) dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(wx.TRANSPARENT_BRUSH) #Draw BG Color r,g,b = self.RGBHex.rgb_tuple(self.backgroundColor) brush = wx.Brush(wx.Color(r,g,b,255)) dc.SetBrush(brush) path = dc.CreatePath() dc.PushState() path.AddRectangle(0, 0, self.size[0]+2, self.size[1]+2) dc.DrawPath(path) dc.PopState() dc.SetBrush(wx.NullBrush) #Set the Zoom dc.Scale(self.zoomScale, self.zoomScale) #Draw BG Image if self.bgImage != None: if self.bgType == 'Image': dc.DrawBitmap(self.bgImage, self.offset[0], self.offset[1], self.bgImage.GetWidth(), self.bgImage.GetHeight()) else: bmpW = self.bgImage.GetWidth() bmpH = self.bgImage.GetHeight() pos = wx.Point(self.offset[0], self.offset[1]) while pos.x < self.size[0]: dc.DrawBitmap(self.bgImage, pos.x, pos.y, self.bgImage.GetWidth(), self.bgImage.GetHeight()) while pos.y < self.size[1]: pos.y += bmpH dc.DrawBitmap(self.bgImage, pos.x, pos.y, self.bgImage.GetWidth(), self.bgImage.GetHeight()) pos.y = 0 pos.x += bmpW #Draw Tiles for tile in self.zOrder['tiles']: tile.Draw(dc) #Draw Grid self.gridLayer.Draw(dc) #Draw Objects for object in self.zOrder['back']: object.Draw(dc) zl = self.zOrder.keys() zl.remove('back') zl.remove('front') zl.remove('tiles') zl.sort() for layer in zl: for object in self.zOrder[layer]: object.Draw(dc) for object in self.zOrder['front']: object.Draw(dc) #Draw Fog if self.useFog: self.fogLayer.Draw(dc) dc.SetBrush(wx.NullBrush) dc.Scale(1/self.zoomScale, 1/self.zoomScale) if self.zoomScale != 1.0: pos = self.GetViewStart() unit = self.GetScrollPixelsPerUnit() pos = [pos[0]*unit[0],pos[1]*unit[1]] font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL) dc.SetFont(font, wx.BLACK) dc.DrawText("Zoom Factor: " + str(self.zoomScale), pos[0], pos[1], dc.CreateBrush(wx.WHITE_BRUSH)) def Clear(self): self._SetSize((1000,1000)) self.selectedObjects = [] self.overObjects = [] self._objectId = 0 self.bgImage = None self.bgType = 'Image' self.bgPath = None self.backgroundColor = '#008040' r, g, b = self.RGBHex.rgb_tuple(self.backgroundColor) self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.BGColorBtn) self.gridType = 'Square' self.gridLines = wx.SOLID self.gridSnap = True self.gridSize = 60 self.gridColor = "#000000" self.whiteboardColor = "#000000" r, g, b = self.RGBHex.rgb_tuple(self.whiteboardColor) self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.ColorBtn) self.zoomScale = 1.0 self.lastZoomTime = time.time() self.lastZoomScale = 1.0 self.useFog = False self.fogRegion = [] self.fogColor = "#000000" self.OnRemoveAllObjects(None) self.toolWnd.Freeze() for btn in self.toolWnd.exclusiveToolList: self.toolWnd.exclusiveToolList[btn].SetToggled(False) self.toolWnd.FogBtn.SetToggled(False) self.toolWnd.SelectorBtn.SetToggled(True) self.toolWnd.Thaw() def GetNewObjectId(self): return str(self._objectId+1) #Map Events def OnBackground(self, event): #Dont do it pass def OnPaint(self, event): if USE_BUFFER: dc = wx.PaintDC(self) self.PrepareDC(dc) dc.DrawBitmap(self._buffer, 0, 0) else: event.Skip() def OnSize(self, event): self._buffer = wx.EmptyBitmap(self.size[0], self.size[1]) self._FixScroll() wx.CallAfter(self.UpdateMap) def OnZoom(self, event): if event.GetWheelRotation() < 0: self.zoomScale -= .1 if self.zoomScale < .5: self.zoomScale = .5 else: self.lastZoomTime = time.time() self._FixScroll() self.UpdateMap() else: self.zoomScale += .1 if self.zoomScale > 1.5: self.zoomScale = 1.5 else: self.lastZoomTime = time.time() self._FixScroll() self.UpdateMap() def OnKey(self, event): self.shift = False self.ctrl = False if event.ShiftDown(): self.shift = True elif event.ControlDown(): self.ctrl = True def EnterObject(self, event): obj = event.GetObject() self.overObjects.append(obj) obj.Highlight() def LeaveObject(self, event): obj = event.GetObject() try: self.overObjects.remove(obj) except: pass obj.UnHighlight() def ObjectSelected(self, event): obj = event.GetObject() self.selectedObjects.append(obj) try: self.overObjects.remove(obj) except: pass obj.UnHighlight() def ObjectDeselected(self, event): obj = event.GetObject() try: self.selectedObjects.remove(obj) except: pass obj.Update() def OnLeftDown(self, event): dc = wx.ClientDC(self) self.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos.x /= self.zoomScale pos.y /= self.zoomScale if self.toolWnd.AddShapeBtn.GetToggled() and self.toolWnd.currentShape == 'Circle': self.circleLayer.OnLeftDown(pos) elif self.toolWnd.AddTextBtn.GetToggled(): self.textLayer.OnLeftDown(pos) elif self.toolWnd.DrawBtn.GetToggled(): self.lineLayer.OnLeftDown(pos) elif self.toolWnd.SelectorBtn.GetToggled() and (self.selectedObjects == [] or self.ctrl or self.shift) and not (self.useFog and self.fogLayer.region.Contains(pos.x, pos.y) and not self.toolWnd.gmToolBar.IsShown()): self.initiatPos = pos self.lxd = 0 self.lyd = 0 if len(self.overObjects) == 0: return elif len(self.overObjects) == 1: self.overObjects[0].Select() else: if not self.shift: menu = wx.Menu("Object Selection") id = 0 for obj in self.overObjects: menu.Append(id, obj.GetName()) id += 1 def selectmenu(event): id = event.GetId() self.overObjects[id].Select() self.Unbind(wx.EVT_MENU) self.Bind(wx.EVT_MENU, selectmenu) self.PopupMenu(menu) else: for i in xrange(len(self.overObjects)): self.overObjects[0].Select() elif self.toolWnd.SelectorBtn.GetToggled() and not self.selectedObjects == []: xd = (self.initiatPos.x+pos.x)*(self.initiatPos.x+pos.x) yd = (self.initiatPos.y+pos.y)*(self.initiatPos.y+pos.y) for i in xrange(len(self.selectedObjects)): self.selectedObjects[0].Deselect() elif self.toolWnd.FogToolBtn.GetToggled(): self.fogLayer.OnLeftDown(pos) def OnLeftDClick(self, event): dc = wx.ClientDC(self) self.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos.x /= self.zoomScale pos.y /= self.zoomScale if self.toolWnd.DrawBtn.GetToggled(): self.lineLayer.OnLeftDClick(pos) def OnLeftUp(self, event): dc = wx.ClientDC(self) self.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos.x /= self.zoomScale pos.y /= self.zoomScale if self.toolWnd.AddShapeBtn.GetToggled() and self.toolWnd.currentShape == 'Circle': self.circleLayer.OnLeftUp(pos) elif self.toolWnd.FogToolBtn.GetToggled(): self.fogLayer.OnLeftUp(pos) elif self.toolWnd.DrawBtn.GetToggled(): self.lineLayer.OnLeftUp(pos) elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects == []: rgn = wx.Region(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) for object in self.zOrder['back']: if rgn.Contains(object.start.x, object.start.y): object.Select() zl = self.zOrder.keys() zl.remove('back') zl.remove('front') zl.remove('tiles') zl.sort() for layer in zl: for object in self.zOrder[layer]: if rgn.Contains(object.start.x, object.start.y): object.Select() for object in self.zOrder['front']: if rgn.Contains(object.start.x, object.start.y): object.Select() self.lxd = 0 self.lyd = 0 self.initiatPos = pos self.Refresh() def OnMotion(self, event): dc = wx.ClientDC(self) self.PrepareDC(dc) pos = event.GetLogicalPosition(dc) pos.x /= self.zoomScale pos.y /= self.zoomScale #HitTest for object in self.zOrder['back']: object.HitTest(pos) zl = self.zOrder.keys() zl.remove('back') zl.remove('front') zl.remove('tiles') zl.sort() for layer in zl: for object in self.zOrder[layer]: object.HitTest(pos) for object in self.zOrder['front']: object.HitTest(pos) if self.toolWnd.AddShapeBtn.GetToggled() and event.m_leftDown and self.toolWnd.currentShape == 'Circle': self.circleLayer.OnMotion(pos) elif self.toolWnd.DrawBtn.GetToggled() and self.lineLayer.start != wx.Point(0,0): self.lineLayer.OnMotion(pos) elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects != [] and not (self.ctrl or self.shift): xd = (pos.x-self.initiatPos.x) yd = (pos.y-self.initiatPos.y) for obj in self.selectedObjects: obj.start.x += xd obj.start.y += yd obj.Update() self.initiatPos = pos elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects == [] and event.m_leftDown: dc.SetBrush(wx.TRANSPARENT_BRUSH) pen = wx.Pen(wx.BLACK, 3, wx.DOT) dc.SetPen(pen) dc.SetLogicalFunction(wx.INVERT) xd = (pos.x-self.initiatPos.x) yd = (pos.y-self.initiatPos.y) if self.lxd != 0 and self.lyd != 0: r = wx.Rect(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) dc.DrawRectangleRect(r) self.lxd = xd self.lyd = yd r = wx.Rect(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) dc.DrawRectangleRect(r) elif (self.toolWnd.FogToolBtn.GetToggled()) and event.m_leftDown: self.fogLayer.OnMotion(pos) def OnRightDown(self, event): mapmenu = wx.Menu() item = wx.MenuItem(mapmenu, wx.ID_ANY, "Load Map", "Load Map") #self.Bind(wx.EVT_MENU, self.OnOpenBtn, item) mapmenu.AppendItem(item) item = wx.MenuItem(mapmenu, wx.ID_ANY, "Save Map", "Save Map") #self.Bind(wx.EVT_MENU, self.OnSaveBtn, item) mapmenu.AppendItem(item) item = wx.MenuItem(mapmenu, wx.ID_ANY, "Default Map", "Default Map") self.Bind(wx.EVT_MENU, self.OnDefaultBtn, item) mapmenu.AppendItem(item) item = wx.MenuItem(mapmenu, wx.ID_ANY, "Map Properties", "Map Properties") #self.Bind(wx.EVT_MENU, OnMapPropsBtn, item) mapmenu.AppendItem(item) bgmenu = wx.Menu() item = wx.MenuItem(bgmenu, wx.ID_ANY, "Change Background Image", "Change Background Image") self.Bind(wx.EVT_MENU, self.OnBGBtn, item) bgmenu.AppendItem(item) item = wx.MenuItem(bgmenu, wx.ID_ANY, "Change Background Color", "Change Background Color") self.Bind(wx.EVT_MENU, self.OnBGColorBtn, item) bgmenu.AppendItem(item) item = wx.MenuItem(bgmenu, wx.ID_ANY, "Grid Properties", "Grid Properties") #self.Bind(wx.EVT_MENU, self.OnGridBtn, item) bgmenu.AppendItem(item) fogmenu = wx.Menu() item = wx.MenuItem(fogmenu, wx.ID_ANY, "Toggle Fog", "Toggle Fog") self.Bind(wx.EVT_MENU, self.OnFogBtn, item) fogmenu.AppendItem(item) item = wx.MenuItem(fogmenu, wx.ID_ANY, "Fog Color", "Fog Color") self.Bind(wx.EVT_MENU, self.OnFogColorBtn, item) fogmenu.AppendItem(item) menu = wx.Menu() if self.toolWnd.gmToolBar.IsShown(): menu.AppendMenu(wx.ID_ANY, "Map", mapmenu) menu.AppendMenu(wx.ID_ANY, "Background", bgmenu) menu.AppendMenu(wx.ID_ANY, "Fog", fogmenu) menu.AppendSeparator() item = wx.MenuItem(menu, wx.ID_ANY, "Miniture Properties", "Miniture Properties") #self.Bind(wx.EVT_MENU, self.OnColorBtn, item) menu.AppendItem(item) menu.AppendSeparator() item = wx.MenuItem(menu, wx.ID_ANY, "Whiteboard Color", "Whiteboard Color") self.Bind(wx.EVT_MENU, self.OnColorBtn, item) menu.AppendItem(item) def ObjectMenu(event): id = event.GetId() objid = int(menu.GetHelpString(id)) menuname = menu.GetLabel(id) obj = self.overObjects[objid] if menuname == "Move To Back": self.MoveToBack(obj) elif menuname == "Move Back": self.MoveBack(obj) elif menuname == "Move Forward": self.MoveForward(obj) elif menuname == "Move To Front": self.MoveToFront(obj) elif menuname == "Remove": self.zOrder[obj.zOrder].remove(obj) obj.Update() self.Unbind(wx.EVT_MENU) self.overObjects.remove(obj) if len(self.overObjects): menu.AppendSeparator() id = 0 for obj in self.overObjects: if obj.IsShown() or self.toolWnd.gmToolBar.IsShown(): objmenu = wx.Menu() item = wx.MenuItem(objmenu, wx.ID_ANY, "Move To Back", str(id)) self.Bind(wx.EVT_MENU, ObjectMenu, item) objmenu.AppendItem(item) item = wx.MenuItem(objmenu, wx.ID_ANY, "Move Back", str(id)) self.Bind(wx.EVT_MENU, ObjectMenu, item) objmenu.AppendItem(item) item = wx.MenuItem(objmenu, wx.ID_ANY, "Move Forward", str(id)) self.Bind(wx.EVT_MENU, ObjectMenu, item) objmenu.AppendItem(item) item = wx.MenuItem(objmenu, wx.ID_ANY, "Move To Front", str(id)) self.Bind(wx.EVT_MENU, ObjectMenu, item) objmenu.AppendItem(item) objmenu.AppendSeparator() if obj.IsShown(): item = wx.MenuItem(objmenu, wx.ID_ANY, "Hide", str(id)) self.Bind(wx.EVT_MENU, obj.Hide, item) objmenu.AppendItem(item) objmenu.AppendSeparator() elif self.toolWnd.gmToolBar.IsShown(): item = wx.MenuItem(objmenu, wx.ID_ANY, "Show", str(id)) self.Bind(wx.EVT_MENU, obj.Show, item) objmenu.AppendItem(item) objmenu.AppendSeparator() item = wx.MenuItem(objmenu, wx.ID_ANY, "Remove", str(id)) self.Bind(wx.EVT_MENU, ObjectMenu, item) objmenu.AppendItem(item) item = wx.MenuItem(objmenu, wx.ID_ANY, "Properties", str(id)) self.Bind(wx.EVT_MENU, obj.ShowProperties, item) objmenu.AppendItem(item) menu.AppendMenu(wx.ID_ANY, obj.GetName(), objmenu) menu.AppendSeparator() item = wx.MenuItem(menu, wx.ID_ANY, "Remove All Objects", "Remove All Whiteboard Items") self.Bind(wx.EVT_MENU, self.OnRemoveAllObjects, item) menu.AppendItem(item) self.PopupMenu(menu) def OnRemoveAllObjects(self, event): for layer in self.zOrder: for i in xrange(len(self.zOrder[layer])): del self.zOrder[layer][0] self.zOrder = {} self.zOrder['tiles'] = [] self.zOrder["back"] = [] self.zOrder["front"] = [] if event != None: self.UpdateMap() def MoveToBack(self, object): self.zOrder[object.zOrder].remove(object) self.zOrder['back'].append(object) object.zOrder = 'back' self.UpdateMap() def MoveToFront(self, object): self.zOrder[object.zOrder].remove(object) self.zOrder['front'].append(object) object.zOrder = 'front' self.UpdateMap() def MoveBack(self, object): self.zOrder[object.zOrder].remove(object) zl = self.zOrder.keys() zl.remove('back') zl.remove('front') zl.remove('tiles') zl.sort() lzo = 1 if len(zl): lzo = zl.pop() if object.zOrder == 'back' or object.zOrder == 1: self.zOrder['back'].append(object) object.zOrder = 'back' elif object.zOrder == 'front': if not self.zOrder.has_key(lzo): self.zOrder[lzo] = [] self.zOrder[lzo].append(object) object.zOrder = lzo else: object.zOrder -= 1 if not self.zOrder.has_key(object.zOrder): self.zOrder[object.zOrder] = [] self.zOrder[object.zOrder].append(object) self.UpdateMap() def MoveForward(self, object): self.zOrder[object.zOrder].remove(object) zl = self.zOrder.keys() zl.remove('back') zl.remove('front') zl.remove('tiles') zl.sort() lzo = 1 if len(zl): lzo = zl.pop() if object.zOrder == 'back': if not self.zOrder.has_key(1): self.zOrder[1] = [] self.zOrder[1].append(object) object.zOrder = 1 elif z == 'front': self.zOrder['front'].append(object) object.zOrder = 'front' else: object.zOrder += 1 if not self.zOrder.has_key(object.zOrder): self.zOrder[object.zOrder] = [] self.zOrder[object.zOrder].append(object) self.UpdateMap() def OnScroll(self, event): event.Skip() self.Refresh() def OnZoomTimer(self, event): if (time.time() - self.lastZoomTime) >= 3 and self.lastZoomScale != self.zoomScale: #Send Zoome Notice to other clients self.lastZoomTime = time.time() self.lastZoomScale = self.zoomScale def OnRoleTimer(self, event): #Figure out the users role if self.session.my_role() == self.session.ROLE_GM: self.role = 'GM' elif self.session.my_role() == self.session.ROLE_PLAYER: self.role = 'Player' else: self.role = 'Lurker' if self.role == 'GM' and not self.toolWnd.gmToolBar.IsShown() and not (str(self.session.group_id) == '0' and str(self.session.status) == '1'): self.toolWnd.Freeze() self.toolWnd.gmToolBar.Show() self.toolWnd.Thaw() elif self.role == 'Player' and not (str(self.session.group_id) == '0' and str(self.session.status) == '1'): if self.toolWnd.gmToolBar.IsShown(): self.toolWnd.Freeze() self.toolWnd.gmToolBar.Hide() self.toolWnd.Thaw() if not self.toolWnd.playerToolBar.IsShown(): self.toolWnd.Freeze() self.toolWnd.playerToolBar.Show() self.toolWnd.Thaw() elif self.role == 'Lurker' or (str(self.session.group_id) == '0' and str(self.session.status) == '1'): if self.toolWnd.playerToolBar.IsShown(): self.toolWnd.Freeze() self.toolWnd.gmToolBar.Hide() self.toolWnd.playerToolBar.Hide() self.toolWnd.Thaw() try: self.toolWnd.Layout() except: pass def OnClose(self, event): self.zoomTimer.Stop() self.roleTimer.Stop() event.Skip() #Toolbar Events def OnDefaultBtn(self, event): self.Clear() wx.CallAfter(self.UpdateMap) def OnColorBtn(self, event): newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) if newcolor == None: return self.whiteboardColor = newcolor r, g, b = self.RGBHex.rgb_tuple(self.whiteboardColor) self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.ColorBtn) def OnBGColorBtn(self, event): newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) if newcolor == None: return self.backgroundColor = newcolor r, g, b = self.RGBHex.rgb_tuple(self.backgroundColor) self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.BGColorBtn) self.UpdateMap() def OnFogColorBtn(self, event): newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) if newcolor == None: return self.fogColor = newcolor r, g, b = self.RGBHex.rgb_tuple(self.fogColor) self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.FogColorBtn) self.UpdateMap() def OnExlusiveBtn(self, event): id = event.GetId() #This is backwards because the Toggle Switch does not get set until AFTER The mouse gets released if not self.toolWnd.exclusiveToolList[id].GetToggled(): self.toolWnd.Freeze() #Disable all mutualy exclusive tools for btn in self.toolWnd.exclusiveToolList: if self.toolWnd.exclusiveToolList[btn].GetId() != id: self.toolWnd.exclusiveToolList[btn].SetToggled(False) self.toolWnd.Thaw() else: wx.CallAfter(self.toolWnd.SelectorBtn.SetToggled, True) def OnFogBtn(self, event): if not self.toolWnd.FogBtn.GetToggled(): self.useFog = True else: self.useFog = False self.toolWnd.Freeze() self.toolWnd.SelectorBtn.SetToggled(True) self.toolWnd.FogToolBtn.SetToggled(False) self.toolWnd.Thaw() self.fogRegion = [] self.UpdateMap() def OnBGBtn(self, event): dlg = wx.Dialog(self.toolWnd, wx.ID_ANY, title="Background Properties") sizer = wx.BoxSizer(wx.HORIZONTAL) filename = wx.TextCtrl(dlg, wx.ID_ANY) filename.Hide() bgpath = wx.TextCtrl(dlg, wx.ID_ANY) if self.bgPath != None: bgpath.SetValue(self.bgPath) bgtype = wx.Choice(dlg, wx.ID_ANY, choices=['Image', 'Texture']) bgtype.SetStringSelection(self.bgType) browsebtn = wx.Button(dlg, wx.ID_ANY, "Browse") okbtn = wx.Button(dlg, wx.ID_OK) cancelbtn = wx.Button(dlg, wx.ID_CANCEL) sizer.Add(wx.StaticText(dlg, wx.ID_ANY, "Image Path"), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2) sizer.Add(bgpath, 0, wx.EXPAND|wx.ALL, 3) sizer.Add(wx.StaticText(dlg, wx.ID_ANY, "Image Type"), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2) sizer.Add(bgtype, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 3) sizer.Add(browsebtn, 0, wx.EXPAND|wx.ALL, 2) sizer.Add(okbtn, 0, wx.EXPAND|wx.ALL, 3) sizer.Add(cancelbtn, 0, wx.EXPAND|wx.ALL, 2) dlg.SetSizer(sizer) dlg.SetAutoLayout(True) dlg.Fit() def OnBrowse(event): filedlg = wx.FileDialog(self, "Select an Image File", self.dir_struct["user"], wildcard="Image files (*.bmp, *.gif, *.jpg, *.png)|*.bmp;*.gif;*.jpg;*.png", style=wx.HIDE_READONLY|wx.OPEN) if filedlg.ShowModal() != wx.ID_OK: filedlg.Destroy() return bgpath.SetValue(filedlg.GetPath()) filename.SetValue(filedlg.GetFilename()) dlg.Bind(wx.EVT_BUTTON, OnBrowse, browsebtn) dlg.Show() if not dlg.ShowModal() == wx.ID_OK: dlg.Destroy() return self.bgType = bgtype.GetStringSelection() if bgpath.GetValue().lower().find('http:') == -1: file = open(bgpath.GetValue(), "rb") imgdata = file.read() file.close() (imgtype,j) = mimetypes.guess_type(filename.GetValue()) postdata = urllib.urlencode({'filename':filename.GetValue(), 'imgdata':imgdata, 'imgtype':imgtype}) thread.start_new_thread(self.__Upload, (postdata, bgpath.GetValue(), "Background")) else: self.bgImage = self._LoadImage(bgpath.GetValue()) self.UpdateMap() #Private Methods def _SetSize(self, size): if size[0] == -1: size[0] = self.size[0] if size[1] == -1: size[1] = self.size[1] if size[0] < 300: size = (300, size[1]) if size[1] < 300: size = (size[0], 300) size1 = self.GetClientSizeTuple() if size[0] < size1[0]: size = (size1[0], size[1]) if size[1] < size1[1]: size = (size[0], size1[1]) self.sizeChanged = 1 self.size = size self._FixScroll() def _FixScroll(self): scale = self.zoomScale pos = self.GetViewStart() unit = self.GetScrollPixelsPerUnit() pos = [pos[0]*unit[0],pos[1]*unit[1]] size = self.GetClientSize() unit = [10*scale,10*scale] if (unit[0] == 0 or unit[1] == 0): return pos[0] /= unit[0] pos[1] /= unit[1] mx = [int(self.size[0]*scale/unit[0])+1, int(self.size[1]*scale/unit[1]+1)] self.SetScrollbars(unit[0], unit[1], mx[0], mx[1], pos[0], pos[1]) def _LoadImage(self, path, miniId=None): if self.imageCache.has_key(path): return self.imageCache[path] while len(self.imageCache) > int(self.settings.get_setting("ImageCacheSize")): keys = self.imageCache.keys() del self.imageCache[keys[0]] thread.start_new_thread(self.__DownloadImage, (path, miniId)) return wx.Bitmap(orpg.dirpath.dir_struct["icon"] + "fetching.png", wx.BITMAP_TYPE_PNG) def _ClearCache(self): for key in self.imageCache: del self.imageCache[key] #Threads def __Upload(self, postdata, filename, type="Background"): self.lock.acquire() url = self.settings.get_setting('ImageServerBaseURL') file = urllib.urlopen(url, postdata) recvdata = file.read() file.close() try: xml_dom = minidom.parseString(recvdata)._get_documentElement() if xml_dom.nodeName == 'path': path = xml_dom.getAttribute('url') path = urllib.unquote(path) if type == 'Background': self.bgImage = self._LoadImage(path) self.bgPath = path else: self.minis.append(self.mapLayer.AddMiniture(path)) self.UpdateMap() else: self.chat.InfoPost(xml_dom.getAttribute('msg')) except Exception, e: print e print recvdata self.lock.release() def __DownloadImage(self, path, miniId): self.lock.acquire() uriPath = urllib.unquote(path) try: data = urllib.urlretrieve(uriPath) if data[0] and data[1].getmaintype() == "image": imageType = data[1].gettype() img = wx.ImageFromMime(data[0], imageType).ConvertToBitmap() self.imageCache[path] = img if miniId == None: self.bgImage = img if self.bgType == 'Image': self._SetSize((img.GetHeight(), img.GetWidth())) else: mini = self.GetMiniById(miniId) mini.image = img self.UpdateMap() except Exception, e: self.chat.InfoPost("Unable to resolve/open the specified URI; image was NOT laoded:" + path) urllib.urlcleanup() self.lock.release()