# HG changeset patch # User sirebral # Date 1254885394 18000 # Node ID 2f2bebe9c77f3d0c1d38211f3c8c60ea846f2f11 # Parent 15e32ec131cb82ec19ba5880a8b055fd857c9e19 Traipse Alpha 'OpenRPG' {091006-03} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary: 00: Adds Bookmarks (Alpha) with cool Smiley Star and Plus Symbol images! 01: Forgot the default_server_bookmarks.xml; added. 02: Bookmarks working with no errors now! Sweet! 03: Changes made to the map for increased portability. SnowDog has changes planned in Core, though. Added an initial push to the BCG. Not much to see, just shows off how it is re-writing Main code. diff -r 15e32ec131cb -r 2f2bebe9c77f orpg/mapper/map.py --- a/orpg/mapper/map.py Tue Oct 06 06:22:23 2009 -0500 +++ b/orpg/mapper/map.py Tue Oct 06 22:16:34 2009 -0500 @@ -108,6 +108,15 @@ # miniatures drag self.drag = None + #self.Bind(wx.EVT_MOUSEWHEEL, self.MouseWheel) + + def MouseWheel(self, evt): + if evt.CmdDown(): + print evt.GetWheelRotation() + if evt.GetWheelRotation() > 0: self.on_zoom_in(None) + elif evt.GetWheelRotation() < 0: self.on_zoom_out(None) + else: pass + def better_refresh(self, event=None): self.Refresh(True) @@ -118,41 +127,41 @@ self.session = component.get("session") if self.session.my_role() == self.session.ROLE_LURKER or (str(self.session.group_id) == '0' and str(self.session.status) == '1'): cidx = self.parent.get_tab_index("Background") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Grid") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Miniatures") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Whiteboard") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Fog") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("General") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) else: cidx = self.parent.get_tab_index("Background") - if not self.parent.layer_tabs.GetEnabled(cidx): + if not self.parent.tabs.GetEnabled(cidx): cidx = self.parent.get_tab_index("Miniatures") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) cidx = self.parent.get_tab_index("Whiteboard") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) cidx = self.parent.get_tab_index("Background") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Grid") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("Fog") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) cidx = self.parent.get_tab_index("General") - self.parent.layer_tabs.EnableTab(cidx, False) + self.parent.tabs.EnableTab(cidx, False) if self.session.my_role() == self.session.ROLE_GM: cidx = self.parent.get_tab_index("Background") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) cidx = self.parent.get_tab_index("Grid") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) cidx = self.parent.get_tab_index("Fog") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) cidx = self.parent.get_tab_index("General") - self.parent.layer_tabs.EnableTab(cidx, True) + self.parent.tabs.EnableTab(cidx, True) if not self.cacheSizeSet: self.cacheSizeSet = True cacheSize = component.get('settings').get_setting("ImageCacheSize") @@ -172,7 +181,6 @@ except: pass # Flag that we now need to refresh! self.requireRefresh += 1 - """ Randomly purge an item from the cache, while this is lamo, it does keep the cache from growing without bounds, which is pretty important!""" if len(ImageHandler.Cache) >= self.cacheSize: @@ -191,6 +199,7 @@ else: self.lastRefreshValue = self.requireRefresh def on_scroll(self, evt): + print 'scrolling' if self.drag: self.drag.Hide() if component.get('settings').get_setting("AlwaysShowMapScale") == "1": self.printscale() evt.Skip() @@ -721,30 +730,35 @@ self.top_frame = component.get('frame') self.root_dir = os.getcwd() self.current_layer = 2 - self.layer_tabs = orpgTabberWnd(self, style=FNB.FNB_NO_X_BUTTON|FNB.FNB_BOTTOM|FNB.FNB_NO_NAV_BUTTONS) - self.layer_handlers = [] - self.layer_handlers.append(background_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[0],"Background") - self.layer_handlers.append(grid_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[1],"Grid") - self.layer_handlers.append(miniatures_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[2],"Miniatures", True) - self.layer_handlers.append(whiteboard_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[3],"Whiteboard") - self.layer_handlers.append(fog_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[4],"Fog") - self.layer_handlers.append(map_handler(self.layer_tabs,-1,self.canvas)) - self.layer_tabs.AddPage(self.layer_handlers[5],"General") - self.layer_tabs.SetSelection(2) + self.tabs = orpgTabberWnd(self, style=FNB.FNB_NO_X_BUTTON|FNB.FNB_BOTTOM|FNB.FNB_NO_NAV_BUTTONS) + self.handlers = {} + self.handlers[0]=(background_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[0],"Background") + self.handlers[1]=(grid_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[1],"Grid") + self.handlers[2]=(miniatures_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[2],"Miniatures", True) + self.handlers[3]=(whiteboard_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[3],"Whiteboard") + self.handlers[4]=(fog_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[4],"Fog") + self.handlers[5]=(map_handler(self.tabs,-1,self.canvas)) + self.tabs.AddPage(self.handlers[5],"General") + self.tabs.SetSelection(2) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.EXPAND) - self.sizer.Add(self.layer_tabs, 0, wx.EXPAND) + self.sizer.Add(self.tabs, 0, wx.EXPAND) self.SetSizer(self.sizer) self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.on_layer_change) #self.Bind(wx.EVT_SIZE, self.on_size) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) self.load_default() + ## Components for making Map Based plugins that create new tabs. + component.add('map_tabs', self.tabs) + component.add('map_layers', self.handlers) + component.add('map_wnd', self) + def OnLeave(self, evt): if "__WXGTK__" in wx.PlatformInfo: wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) @@ -798,41 +812,41 @@ os.chdir(self.root_dir) def get_current_layer_handler(self): - return self.layer_handlers[self.current_layer] + return self.handlers[self.current_layer] def get_tab_index(self, layer): """Return the index of a chatpanel in the wxNotebook.""" - for i in xrange(self.layer_tabs.GetPageCount()): - if (self.layer_tabs.GetPageText(i) == layer): + for i in xrange(self.tabs.GetPageCount()): + if (self.tabs.GetPageText(i) == layer): return i return 0 def on_layer_change(self, evt): - layer = self.layer_tabs.GetPage(evt.GetSelection()) - for i in xrange(0, len(self.layer_handlers)): - if layer == self.layer_handlers[i]: self.current_layer = i + layer = self.tabs.GetPage(evt.GetSelection()) + for i in xrange(0, len(self.handlers)): + if layer == self.handlers[i]: self.current_layer = i if self.current_layer == 0: - bg = self.layer_handlers[0] + bg = self.handlers[0] if (self.session.my_role() != self.session.ROLE_GM): bg.url_path.Show(False) else: bg.url_path.Show(True) self.canvas.Refresh(False) evt.Skip() def on_left_down(self, evt): - self.layer_handlers[self.current_layer].on_left_down(evt) + self.handlers[self.current_layer].on_left_down(evt) #double click handler added by Snowdog 5/03 def on_left_dclick(self, evt): - self.layer_handlers[self.current_layer].on_left_dclick(evt) + self.handlers[self.current_layer].on_left_dclick(evt) def on_right_down(self, evt): - self.layer_handlers[self.current_layer].on_right_down(evt) + self.handlers[self.current_layer].on_right_down(evt) def on_left_up(self, evt): - self.layer_handlers[self.current_layer].on_left_up(evt) + self.handlers[self.current_layer].on_left_up(evt) def on_motion(self, evt): - self.layer_handlers[self.current_layer].on_motion(evt) + self.handlers[self.current_layer].on_motion(evt) def MapBar(self, id, data): self.canvas.MAP_MODE = data @@ -849,8 +863,8 @@ except: pass def update_tools(self): - for h in self.layer_handlers: - h.update_info() + for h in self.handlers: + self.handlers[h].update_info() def on_hk_map_layer(self, evt): id = self.top_frame.mainmenu.GetHelpString(evt.GetId()) @@ -860,7 +874,7 @@ elif id == "Whiteboard Layer": self.current_layer = self.get_tab_index("Whiteboard") elif id == "Fog Layer": self.current_layer = self.get_tab_index("Fog") elif id == "General Properties": self.current_layer = self.get_tab_index("General") - self.layer_tabs.SetSelection(self.current_layer) + self.tabs.SetSelection(self.current_layer) def on_flush_cache(self, evt): ImageHandler.flushCache() diff -r 15e32ec131cb -r 2f2bebe9c77f orpg/orpg_version.py --- a/orpg/orpg_version.py Tue Oct 06 06:22:23 2009 -0500 +++ b/orpg/orpg_version.py Tue Oct 06 22:16:34 2009 -0500 @@ -4,7 +4,7 @@ #BUILD NUMBER FORMAT: "YYMMDD-##" where ## is the incremental daily build index (if needed) DISTRO = "Traipse Alpha" DIS_VER = "Ornery Orc" -BUILD = "091006-02" +BUILD = "091006-03" # This version is for network capability. PROTOCOL_VERSION = "1.2" diff -r 15e32ec131cb -r 2f2bebe9c77f plugins/bcg/__init__.py diff -r 15e32ec131cb -r 2f2bebe9c77f plugins/bcg/tok_dialogs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/bcg/tok_dialogs.py Tue Oct 06 22:16:34 2009 -0500 @@ -0,0 +1,531 @@ +# Copyright (C) 2000-2001 The OpenRPG Project +# +# openrpg-dev@lists.sourceforge.net +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# -- +# +# File: mapper/min_dialogs.py +# Author: Chris Davis +# Maintainer: +# Version: +# $Id: min_dialogs.py,v 1.27 2006/11/13 02:23:16 digitalxero Exp $ +# +# Description: This file contains some of the basic definitions for the chat +# utilities in the orpg project. + +##----------------------------- +## token List Panel +##----------------------------- + +from tokens import * + +class min_list_panel(wx.Dialog): + + def __init__(self, parent,layers, log, pos =(-1,-1)): + wx.Dialog.__init__(self, parent,-1, log,pos = (-1,-1), size = (785,175), style=wx.RESIZE_BORDER) + listID = wx.NewId() + self.parent = parent + self.min = layers['tokens'].tokens + self.grid = layers['grid'] + self.layers = layers + self.listID = listID + list_sizer = wx.BoxSizer(wx.VERTICAL) + self.list_sizer = list_sizer + listctrl = wx.ListCtrl(self, listID, style=wx.LC_REPORT | wx.SUNKEN_BORDER) + self.listctrl = listctrl + self.Centre(wx.BOTH) + self.log = log + self.list_sizer.Add(self.listctrl,1,wx.EXPAND) + self.listctrl.InsertColumn(0,"POS ") + self.listctrl.InsertColumn(0,"LOCKED") + self.listctrl.InsertColumn(0,"HEADING") + self.listctrl.InsertColumn(0,"FACING") + self.listctrl.InsertColumn(0,"LABEL") + self.listctrl.InsertColumn(0,"PATH") + self.listctrl.SetColumnWidth(1, wx.LIST_AUTOSIZE_USEHEADER) + self.listctrl.SetColumnWidth(2, wx.LIST_AUTOSIZE_USEHEADER) + self.listctrl.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER) + self.listctrl.SetColumnWidth(4, wx.LIST_AUTOSIZE_USEHEADER) + self.listctrl.SetColumnWidth(5, wx.LIST_AUTOSIZE_USEHEADER) + self.list_sizer.Add(wx.Button(self, wx.ID_OK, "DONE"),0,wx.ALIGN_CENTER) + self.refresh() + self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK) + self.listctrl.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightClick, id=listID) + self.listctrl.Bind(wx.EVT_RIGHT_UP, self.OnRightClick) + self.listctrl.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) + self.SetSizer(self.list_sizer) + self.SetAutoLayout(True) + self.Fit() + + def OnRightClick(self,event): + if self.listctrl.GetSelectedItemCount() > 0: + menu = wx.Menu() + lPopupID1 = wx.NewId() + lPopupID2 = wx.NewId() + lPopupID3 = wx.NewId() + menu.Append(lPopupID1, "&Edit") + menu.Append(lPopupID2, "&Delete") + menu.Append(lPopupID3, "To &Gametree") + self.Bind(wx.EVT_MENU, self.onEdit, id=lPopupID1) + self.Bind(wx.EVT_MENU, self.onDelete, id=lPopupID2) + self.Bind(wx.EVT_MENU, self.onToGametree, id=lPopupID3) + self.PopupMenu(menu, cmpPoint(self.x, self.y)) + menu.Destroy() + event.Skip() + + def refresh(self): + self.SetMinSize((600,175)); + for m in self.min: + self.listctrl.InsertStringItem(self.min.index(m),self.min[self.min.index(m)].path) + self.listctrl.SetStringItem(self.min.index(m),1,self.min[self.min.index(m)].label) + self.listctrl.SetStringItem(self.min.index(m),2,`self.min[self.min.index(m)].heading`) + #self.listctrl.SetStringItem(self.min.index(m),3,`self.min[self.min.index(m)].face`) + self.listctrl.SetStringItem(self.min.index(m),4,`self.min[self.min.index(m)].locked`) + self.listctrl.SetStringItem(self.min.index(m),5,`self.min[self.min.index(m)].pos`) + oldcolumnwidth = self.listctrl.GetColumnWidth(0) + self.listctrl.SetColumnWidth(0, wx.LIST_AUTOSIZE) + if oldcolumnwidth < self.listctrl.GetColumnWidth(0): self.listctrl.SetColumnWidth(0, wx.LIST_AUTOSIZE) + else: self.listctrl.SetColumnWidth(0, oldcolumnwidth) + self.list_sizer=self.list_sizer + + def onEdit(self,event): + min_list = [] + min_index = [] + loop_count = 0 + item =-1 + while True: + loop_count += 1 + item = self.listctrl.GetNextItem(item,wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) + if item == -1: break + min_list.append(self.min[item]) + min_index.append(item-loop_count+1) + if len(min_list) > 0: dlg = min_list_edit_dialog(self.parent,min_index, min_list,self.layers) + if dlg.ShowModal() == wx.ID_OK: pass + self.listctrl.DeleteAllItems() + self.refresh() + event.Skip() + + def onDelete(self,event): + loop_count = 0 + item = -1 + while True: + loop_count += 1 + item = self.listctrl.GetNextItem(item,wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) + if item == -1: break + self.layers["tokens"].del_token(self.min[item-loop_count+1]) + self.listctrl.DeleteAllItems() + self.refresh() + event.Skip() + + def onToGametree(self,event): + min_list = [] + min_index = [] + loop_count = 0 + item =-1 + while True: + loop_count += 1 + item = self.listctrl.GetNextItem(item,wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) + if item == -1: break + min_list.append(self.min[item]) + min_index.append(item-loop_count+1) + if len(min_list) > 0: + for sel_rmin in min_list: + ############# + min_xml = sel_rmin.toxml(action="new") + node_begin = "' + print "Sending this XML to insert_xml:" + node_xml + gametree.insert_xml(node_xml) + ############# + self.listctrl.DeleteAllItems() + self.refresh() + event.Skip() + + def OnRightDown(self,event): + self.x = event.GetX() + self.y = event.GetY() + event.Skip() + + def on_ok(self,evt): + self.EndModal(wx.ID_OK) + +class min_list_edit_dialog(wx.Dialog): + def __init__(self,parent,min_index, min_list, layers): + wx.Dialog.__init__(self,parent,-1,"token List",wx.DefaultPosition,wx.Size(600,530)) + self.layers = layers + grid = layers['grid'] + min = layers['tokens'] + self.min_list = min_list + self.min_index = min_index + self.min = min + sizer1 = wx.BoxSizer(wx.VERTICAL) + sizer = wx.BoxSizer(wx.HORIZONTAL) + self.grid = grid + editor = min_list_edit_panel(self, min_index, min_list,layers) + sizer1.Add(editor, 1, wx.EXPAND) + sizer.Add(wx.Button(self, wx.ID_OK, "OK"), 1, wx.EXPAND) + sizer.Add(wx.Size(10,10)) + sizer.Add(wx.Size(10,10)) + sizer.Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), 1, wx.EXPAND) + sizer1.Add(sizer, 0, wx.EXPAND) + self.editor = editor + self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK) + self.SetSizer(sizer1) + self.SetAutoLayout(True) + self.Fit() + + def on_revert(self,evt): + pass + + def on_ok(self,evt): + self.editor.on_ok(self.layers) + self.EndModal(wx.ID_OK) + +class min_list_edit_panel(wx.Panel): + def __init__(self, parent, min_index, min_list,layers): + LABEL_COMBO = wx.NewId() + PATH_COMBO = wx.NewId() + POS_COMB = wx.NewId() + MIN_POS = wx.NewId() + POS_SPIN = wx.NewId() + self.grid = layers['grid'] + self.min = layers['tokens'].tokens + self.min_list = min_list + self.min_index = min_index + self.layers = layers + wx.Panel.__init__(self, parent, -1) + self.min=min + listsizer = wx.StaticBoxSizer(wx.StaticBox(self,-1,"Token list properties"), wx.VERTICAL) + labelsizer = wx.BoxSizer(wx.HORIZONTAL) + self.labelcheck = wx.CheckBox(self,-1,"Serialize") + labelsizer.Add(wx.StaticText(self, -1, "Label: "), 0, wx.EXPAND) + labelsizer.Add(self.labelcheck,wx.ALIGN_RIGHT,wx.EXPAND) + listsizer.Add(labelsizer,0, wx.EXPAND) + self.labelcombo = wx.ComboBox(self, LABEL_COMBO,"no change",style=wx.CB_DROPDOWN) + listsizer.Add(self.labelcombo,0, wx.EXPAND) + self.pathcombo = wx.ComboBox(self, PATH_COMBO, "no change",style=wx.CB_DROPDOWN) + self.positioncombo = wx.ComboBox(self, POS_COMB, "no change", choices=["no change"], style=wx.CB_READONLY) + #self.positioncombo.SetValue(`min_list[0].pos`) + self.labelcombo.Append("no change") + self.pathcombo.Append("no change") + for m in min_list: + self.labelcombo.Append(min_list[min_list.index(m)].label) + self.pathcombo.Append(min_list[min_list.index(m)].path) + self.positioncombo.Append(`min_list[min_list.index(m)].pos`) + listsizer.Add(wx.StaticText(self, -1, "Path:"), 0, wx.EXPAND) + listsizer.Add(self.pathcombo, 0, wx.EXPAND) + listsizer.Add(wx.Size(10,10)) + self.heading = wx.RadioBox(self, MIN_HEADING, "Heading", + choices=["None","N","NE","E","SE","S","SW","W","NW","no change"], majorDimension=5, style=wx.RA_SPECIFY_COLS) + self.heading.SetSelection( 9 ) + listsizer.Add( self.heading, 0, wx.EXPAND ) + listsizer.Add(wx.Size(10,10)) + + ## Remove + #self.face = wx.RadioBox(self, MIN_FACE, "Facing", + # choices=["None","N","NE","E","SE","S","SW","W","NW","no change"], majorDimension=5, style=wx.RA_SPECIFY_COLS) + #self.face.SetSelection(9) + #listsizer.Add(self.face, 0, wx.EXPAND) + + ### + ###Group together locked, Hide, and snap radioboxes in group2 box + ### + group2 = wx.BoxSizer(wx.HORIZONTAL) + self.locked = wx.RadioBox(self, MIN_LOCK, "Lock", + choices=["Don't lock","Lock","no change"],majorDimension=1,style=wx.RA_SPECIFY_COLS) + self.locked.SetSelection(2) + self.hide = wx.RadioBox(self, MIN_HIDE, "Hide", + choices=["Don't hide", "Hide", "no change"],majorDimension=1,style=wx.RA_SPECIFY_COLS) + self.hide.SetSelection(2) + self.snap = wx.RadioBox(self,MIN_ALIGN,"Snap", + choices=["Center","Top left","no change"],majorDimension=1,style=wx.RA_SPECIFY_COLS) + self.snap.SetSelection(2) + group2.Add(self.locked, 0, wx.EXPAND) + group2.Add(wx.Size(10,0)) + group2.Add(self.hide, 0, wx.EXPAND) + group2.Add(wx.Size(10,0)) + group2.Add(self.snap, 0, wx.EXPAND) + group2.Add(wx.Size(10,0)) + listsizer.Add(group2,0,0) + ### + ###Group together the postion radiobox and the and its selection elements + ### + xpos = int(min_list[0].pos[0]) + #xpos = int(`min_list[0].pos`[1:`min_list[0].pos`.index(',')]) + ypos = int(min_list[0].pos[1]) + #ypos = int(`min_list[0].pos`[`min_list[0].pos`.rfind(',')+1:len(`min_list[0].pos`)-1]) + self.scx = wx.SpinCtrl(self, POS_SPIN, "", (-1,-1), wx.Size(75,25)) + self.scx.SetRange(0,self.grid.return_grid()[0]) + self.scx.SetValue(xpos) + self.scy = wx.SpinCtrl(self, POS_SPIN, "", (-1,-1), wx.Size(75,25)) + self.scy.SetRange(0,self.grid.return_grid()[1]) + self.scy.SetValue(1) + self.scy.SetValue(ypos) + positionbox = wx.BoxSizer(wx.HORIZONTAL) + self.poschoice = wx.RadioBox(self,MIN_POS,"Position", + choices=["Manual", "Existing", "no change"],majorDimension=1,style=wx.RA_SPECIFY_COLS) + self.poschoice.SetSelection(2) + positionbox.Add(self.poschoice,0,0) + ### + ### group together choices under position choice boxsizer + ### + poschoicebox = wx.BoxSizer(wx.VERTICAL) + ### + ### spinbox contains the x and y spinctrls + ### + spinbox = wx.BoxSizer(wx.HORIZONTAL) + group2.Add(positionbox,0, wx.EXPAND) + xpos = wx.StaticText(self, -1,"XPOS: ") + spinbox.Add(xpos,0, 0) + spinbox.Add(self.scx, 0, 0) + ypos = wx.StaticText(self, -1,"YPOS: ") + spinbox.Add(ypos,0, 0) + spinbox.Add(self.scy, 0, 0) + poschoicebox.Add(wx.Size(0,15)) + poschoicebox.Add(spinbox,0,0) + ### + ### kludge is just a way to horizontaly position text. .Add doesn't seem to work. + ### + kluge = wx.BoxSizer(wx.HORIZONTAL) + klugetext = wx.StaticText(self, -1, " ") + kluge.Add(klugetext,0,0) + kluge.Add(self.positioncombo,0,0) + poschoicebox.Add(wx.Size(0,1)) + poschoicebox.Add(kluge,0,0) + positionbox.Add(poschoicebox,0,0) + listsizer.Add(positionbox,0, 0) + self.listsizer = listsizer + #self.outline = wx.StaticBox(self,-1,"token list properties") + #listsizer.Add(self.outline,0, wx.EXPAND) + self.SetSizer(listsizer) + self.SetAutoLayout(True) + self.Fit() + self.Bind(wx.EVT_SPINCTRL, self.on_spin, id=POS_SPIN) + self.Bind(wx.EVT_TEXT, self.on_combo_box, id=POS_COMB) + #self.Bind(wx.EVT_SIZE, self.on_size) + self.Bind(wx.EVT_TEXT, self.on_text, id=MIN_LABEL) + self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=MIN_HEADING) + self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=MIN_FACE) + + def on_ok(self,min): + self.min = min + for m in self.min_list: + if self.hide.GetSelection() !=2: m.hide = self.hide.GetSelection() + if self.heading.GetSelection() !=9: m.heading = self.heading.GetSelection() + #if self.face.GetSelection() !=9: m.face = self.face.GetSelection() + if self.locked.GetSelection() !=2: m.locked = self.locked.GetSelection() + if self.snap.GetSelection() !=2: m.snap_to_align = self.snap.GetSelection() + if self.labelcombo.GetValue() != "no change": + m.label = self.labelcombo.GetValue() + if self.labelcheck.GetValue(): m.label += " " + `self.layers['tokens'].next_serial()` + if self.pathcombo.GetValue() != "no change": + path = self.pathcombo.GetValue() + image = self.evaluate(path) + if str(image[1]) != '-1': + m.path = image[0] + m.bmp = image[1] + else: + image[-1] = -1 + while image[1] == -1: + image = 0 + self.dlg = wx.TextEntryDialog(self, + 'You entered an invalid URL for the image path. Please Enter a valid URL or cancel to leave the old url unchanged') + if self.dlg.ShowModal() == wx.ID_OK: + path = self.dlg.GetValue() + image = self.evaluate(path) + if image[1] != -1: + m.path = image[0] + m.bmp = image[1] + self.dlg.Destroy() + else: break + if self.poschoice.GetSelection() !=2: + if self.poschoice.GetSelection() == 0: m.pos = cmpPoint(self.scx.GetValue(),self.scy.GetValue()) + else: + pos = self.positioncombo.GetValue() + m.pos = cmpPoint(int(`pos`[2:`pos`.index(",")]),int(`pos`[`pos`.rfind(',')+1:len(`pos`)-2])) + self.layers["tokens"].canvas.send_map_data() + + def evaluate(self, ckpath): + path = [] + if ckpath[:7] != "http://": ckpath = "http://" + ckpath + path = self.check_path(ckpath) + return [ckpath, path] + + def check_path(self, path): + if ImageHandler.Cache.has_key(path): return ImageHandler.Cache[path] + img = ImageHandler.directLoad(path) + if img is None: return -1 + return img + + def on_text(self,evt): + id=evt.GetId() + + def on_spin(self,evt): + self.poschoice.SetSelection(0) + + def on_combo_box(self,evt): + self.poschoice.SetSelection(1) + + def on_radio_box(self,evt): + id=evt.GetId() + index = evt.GetInt() + + def on_size(self,evt): + s = self.GetClientSizeTuple() + self.listsizer.SetDimension(20,20,s[0]-40,s[1]-40) + self.outline.SetDimensions(5,5,s[0]-10,s[1]-10) + +##----------------------------- +## token Prop Panel +##----------------------------- + +MIN_LABEL = wx.NewId() +MIN_HEADING = wx.NewId() +MIN_FACE = wx.NewId() +MIN_HIDE = wx.NewId() +MIN_LOCK = wx.NewId() +MIN_ALIGN = wx.NewId() +wxID_MIN_WIDTH = wx.NewId() +wxID_MIN_HEIGHT = wx.NewId() +wxID_MIN_SCALING = wx.NewId() + +class min_edit_panel(wx.Panel): + def __init__(self, parent, min): + wx.Panel.__init__(self, parent, -1) + self.min = min + sizer = wx.StaticBoxSizer(wx.StaticBox(self,-1,"token"), wx.VERTICAL) + sizerSize = wx.BoxSizer(wx.HORIZONTAL) + hSizer = wx.BoxSizer(wx.HORIZONTAL) + self.label = wx.TextCtrl(self, MIN_LABEL, min.label) + sizer.Add(wx.StaticText(self, -1, "Label:"), 0, wx.EXPAND) + sizer.Add(self.label, 0, wx.EXPAND) + sizer.Add(wx.Size(10,10)) + self.heading = wx.RadioBox(self, MIN_HEADING, "Heading", + choices=["None","N","NE", + "E","SE","S", + "SW","W","NW"],majorDimension=5,style=wx.RA_SPECIFY_COLS) + self.heading.SetSelection(min.heading) + #self.face = wx.RadioBox(self, MIN_FACE, "Facing", + # choices=["None","N","NE", + # "E","SE","S", + # "SW","W","NW"],majorDimension=5,style=wx.RA_SPECIFY_COLS) + #self.face.SetSelection(min.face) + self.locked = wx.CheckBox(self, MIN_LOCK, " Lock") + self.locked.SetValue(min.locked) + self.hide = wx.CheckBox(self, MIN_HIDE, " Hide") + self.hide.SetValue(min.hide) + sizer.Add(self.heading, 0, wx.EXPAND) + sizer.Add(wx.Size(10,10)) + #sizer.Add(self.face, 0, wx.EXPAND) + sizer.Add(wx.Size(10,10)) + # + #image resizing + # + self.min_width_old_value = str(self.min.bmp.GetWidth()) + self.min_width = wx.TextCtrl(self, wxID_MIN_WIDTH, self.min_width_old_value) + sizerSize.Add(wx.StaticText(self, -1, "Width: "), 0, wx.ALIGN_CENTER) + sizerSize.Add(self.min_width, 1, wx.EXPAND) + sizerSize.Add(wx.Size(20, 25)) + + #TODO:keep in mind that self.min is a local copy??? + self.min_height_old_value = str(self.min.bmp.GetHeight()) + self.min_height = wx.TextCtrl(self, wxID_MIN_HEIGHT, self.min_height_old_value) + sizerSize.Add(wx.StaticText(self, -1, "Height: "),0,wx.ALIGN_CENTER) + sizerSize.Add(self.min_height, 1, wx.EXPAND) + self.min_scaling = wx.CheckBox(self, wxID_MIN_SCALING, "Lock scaling") + self.min_scaling.SetValue(True) + sizerSize.Add(self.min_scaling, 1, wx.EXPAND) + sizer.Add(sizerSize, 0, wx.EXPAND) + sizer.Add(wx.Size(10, 10)) + + # Now, add the last items on in their own sizer + hSizer.Add(self.locked, 0, wx.EXPAND) + hSizer.Add(wx.Size(10,10)) + hSizer.Add(self.hide, 0, wx.EXPAND) + + # Add the hSizer to the main sizer + sizer.Add( hSizer ) + self.sizer = sizer + self.SetSizer(self.sizer) + self.SetAutoLayout(True) + self.Fit() + + #self.Bind(wx.EVT_SIZE, self.on_size) + self.Bind(wx.EVT_TEXT, self.on_text, id=MIN_LABEL) + self.Bind(wx.EVT_TEXT, self.on_scaling, id=wxID_MIN_WIDTH) + self.Bind(wx.EVT_TEXT, self.on_scaling, id=wxID_MIN_HEIGHT) + self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=MIN_HEADING) + #self.Bind(wx.EVT_RADIOBOX, self.on_radio_box, id=MIN_FACE) + + def on_scaling(self, evt): + if self.min_scaling.GetValue() == False: return + elif self.min_width.GetValue() and wxID_MIN_WIDTH == evt.GetId() and self.min_width.GetInsertionPoint(): + self.min_height.SetValue(str(int((float(self.min_width.GetValue()) / float(self.min_width_old_value)) * float(self.min_height_old_value))) ) + elif self.min_height.GetValue() and wxID_MIN_HEIGHT == evt.GetId() and self.min_height.GetInsertionPoint(): + self.min_width.SetValue(str(int((float(self.min_height.GetValue()) / float(self.min_height_old_value)) * float(self.min_width_old_value))) ) + + def update_min(self): + self.min.set_min_props(self.heading.GetSelection(), + #self.face.GetSelection(), + self.label.GetValue(), + self.locked.GetValue(), + self.hide.GetValue(), + self.min_width.GetValue(), + self.min_height.GetValue()) + + def on_radio_box(self,evt): + id = evt.GetId() + index = evt.GetInt() + + def on_text(self,evt): + id = evt.GetId() + + def on_size(self,evt): + s = self.GetClientSizeTuple() + self.sizer.SetDimension(20,20,s[0]-40,s[1]-40) + self.outline.SetDimensions(5,5,s[0]-10,s[1]-10) + +class min_edit_dialog(wx.Dialog): + def __init__(self,parent,min): + #520,265 + wx.Dialog.__init__(self,parent,-1,"token",wx.DefaultPosition,wx.Size(520,350)) + (w,h) = self.GetClientSizeTuple() + mastersizer = wx.BoxSizer(wx.VERTICAL) + editor = min_edit_panel(self,min) + #editor.SetDimensions(0,0,w,h-25) + self.editor = editor + mastersizer.Add(editor, 1, wx.EXPAND) + mastersizer.Add(wx.Size(10,10)) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(wx.Button(self, wx.ID_OK, "OK"), 1, wx.EXPAND) + sizer.Add(wx.Size(10,10)) + sizer.Add(wx.Button(self, wx.ID_CANCEL, "Cancel"), 1, wx.EXPAND) + #sizer.SetDimension(0,h-25,w,25) + mastersizer.Add(sizer, 0, wx.EXPAND) + self.SetSizer(mastersizer) + self.SetAutoLayout(True) + self.Fit() + self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.ID_OK) + + def on_ok(self,evt): + self.editor.update_min() + self.EndModal(wx.ID_OK) diff -r 15e32ec131cb -r 2f2bebe9c77f plugins/bcg/token_handler.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/bcg/token_handler.py Tue Oct 06 22:16:34 2009 -0500 @@ -0,0 +1,883 @@ +# Copyright (C) 2000-2001 The OpenRPG Project +# +# openrpg-dev@lists.sourceforge.net +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# -- +# +# File: mapper/whiteboard_hander.py +# Author: OpenRPG Team +# Maintainer: +# Version: +# $Id: token_handler.py,v 1.43 2007/12/07 20:39:50 digitalxero Exp $ +# +# Description: Token layer handler; derived from token Layer handler +# +__version__ = "$Id: token_handler.py,v 1.43 2007/12/07 20:39:50 madmathlabs Exp $" + +from orpg.mapper.base_handler import * +from tok_dialogs import * +import thread +import time +import mimetypes +import urllib +import xml.dom.minidom as minidom +import wx + +## rewrite Grid +from orpg.mapper.grid import GRID_RECTANGLE +from orpg.mapper.grid import GRID_HEXAGON +from orpg.mapper.grid import GRID_ISOMETRIC +import os + +from orpg.tools.orpg_settings import settings + +## Jesus H! No Face, rotate! +TOK_ROT_LEFT = wx.NewId() +ROT_LEFT_45 = wx.NewId() +LABEL_TOOL = wx.NewId() +LAYER_TOOL = wx.NewId() +TOK_LIST_TOOL = wx.NewId() +TOK_TOOL = wx.NewId() +TOK_URL = wx.NewId() +SERIAL_TOOL = wx.NewId() +TOK_MOVE = wx.NewId() +TOK_REMOVE = wx.NewId() +TOK_PROP_DLG = wx.NewId() +TOK_FACING_NONE = wx.NewId() +TOK_FACING_MATCH = wx.NewId() +TOK_FACING_EAST = wx.NewId() +TOK_FACING_WEST = wx.NewId() +TOK_FACING_NORTH = wx.NewId() +TOK_FACING_SOUTH = wx.NewId() +TOK_FACING_NORTHEAST = wx.NewId() +TOK_FACING_SOUTHEAST = wx.NewId() +TOK_FACING_SOUTHWEST = wx.NewId() +TOK_FACING_NORTHWEST = wx.NewId() +TOK_HEADING_NONE = wx.NewId() +TOK_HEADING_MATCH = wx.NewId() +TOK_HEADING_EAST = wx.NewId() +TOK_HEADING_WEST = wx.NewId() +TOK_HEADING_NORTH = wx.NewId() +TOK_HEADING_SOUTH = wx.NewId() +TOK_HEADING_NORTHEAST = wx.NewId() +TOK_HEADING_SOUTHEAST = wx.NewId() +TOK_HEADING_SOUTHWEST = wx.NewId() +TOK_HEADING_NORTHWEST = wx.NewId() +TOK_HEADING_SUBMENU = wx.NewId() +TOK_FACING_SUBMENU = wx.NewId() +TOK_ALIGN_SUBMENU = wx.NewId() +TOK_ALIGN_GRID_CENTER = wx.NewId() +TOK_ALIGN_GRID_TL = wx.NewId() +TOK_TITLE_HACK = wx.NewId() +TOK_TO_GAMETREE = wx.NewId() +TOK_BACK_ONE = wx.NewId() +TOK_FORWARD_ONE = wx.NewId() +TOK_TO_BACK = wx.NewId() +TOK_TO_FRONT = wx.NewId() +TOK_LOCK_BACK = wx.NewId() +TOK_LOCK_FRONT = wx.NewId() +TOK_FRONTBACK_UNLOCK = wx.NewId() +TOK_ZORDER_SUBMENU = wx.NewId() +TOK_SHOW_HIDE = wx.NewId() +TOK_LOCK_UNLOCK = wx.NewId() +MAP_REFRESH_MINI_URLS = wx.NewId() + +class myFileDropTarget(wx.FileDropTarget): + def __init__(self, handler): + wx.FileDropTarget.__init__(self) + self.m_handler = handler + def OnDropFiles(self, x, y, filenames): + self.m_handler.on_drop_files(x, y, filenames) + +class token_handler(base_layer_handler): + + def __init__(self, parent, id, canvas): + self.sel_min = None + self.auto_label = 1 + self.use_serial = 1 + self.auto_label_cb = None + self.canvas = canvas + self.settings = settings + self.mini_rclick_menu_extra_items = {} + self.background_rclick_menu_extra_items = {} + base_layer_handler.__init__(self, parent, id, canvas) + # id is the index of the last good menu choice or 'None' + # if the last menu was left without making a choice + # should be -1 at other times to prevent events overlapping + self.lastMenuChoice = None + self.drag_mini = None + self.tooltip_delay_miliseconds = 500 + self.tooltip_timer = wx.CallLater(self.tooltip_delay_miliseconds, self.on_tooltip_timer) + self.tooltip_timer.Stop() + dt = myFileDropTarget(self) + self.canvas.SetDropTarget(dt) + #wxInitAllImageHandlers() + + def build_ctrls(self): + base_layer_handler.build_ctrls(self) + # add controls in reverse order! (unless you want them after the default tools) + self.auto_label_cb = wx.CheckBox(self, wx.ID_ANY, ' Auto Label ', (-1,-1),(-1,-1)) + self.auto_label_cb.SetValue(self.auto_label) + self.min_url = wx.ComboBox(self, wx.ID_ANY, "http://", style=wx.CB_DROPDOWN | wx.CB_SORT) + self.localBrowse = wx.Button(self, wx.ID_ANY, 'Browse', style=wx.BU_EXACTFIT) + minilist = createMaskedButton( self, dir_struct["icon"]+'questionhead.gif', 'Edit token properties', wx.ID_ANY) + miniadd = wx.Button(self, wx.ID_OK, "Add Token", style=wx.BU_EXACTFIT) + self.sizer.Add(self.auto_label_cb,0,wx.ALIGN_CENTER) + self.sizer.Add((6, 0)) + self.sizer.Add(self.min_url, 1, wx.ALIGN_CENTER) + self.sizer.Add((6, 0)) + self.sizer.Add(miniadd, 0, wx.ALIGN_CENTER) + self.sizer.Add((6, 0)) + self.sizer.Add(self.localBrowse, 0, wx.ALIGN_CENTER) + self.sizer.Add((6, 0)) + self.sizer.Add(minilist, 0, wx.ALIGN_CENTER) + self.Bind(wx.EVT_BUTTON, self.on_min_list, minilist) + self.Bind(wx.EVT_BUTTON, self.on_token, miniadd) + self.Bind(wx.EVT_BUTTON, self.on_browse, self.localBrowse) + self.Bind(wx.EVT_CHECKBOX, self.on_label, self.auto_label_cb) + + def on_browse(self, evt): + if not self.role_is_gm_or_player(): return + dlg = wx.FileDialog(None, "Select a Token to load", dir_struct["user"]+'webfiles/', + wildcard="Image files (*.bmp, *.gif, *.jpg, *.png)|*.bmp;*.gif;*.jpg;*.png", style=wx.OPEN) + if not dlg.ShowModal() == wx.ID_OK: + dlg.Destroy() + return + file = open(dlg.GetPath(), "rb") + imgdata = file.read() + file.close() + filename = dlg.GetFilename() + (imgtype,j) = mimetypes.guess_type(filename) + postdata = urllib.urlencode({'filename':filename, 'imgdata':imgdata, 'imgtype':imgtype}) + + ## Removal of Remote Server? + if self.settings.get_setting('LocalorRemote') == 'Remote': + # make the new mini appear in top left of current viewable map + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + x = dc.DeviceToLogicalX(0) + y = dc.DeviceToLogicalY(0) + thread.start_new_thread(self.canvas.layers['token'].upload, + (postdata, dlg.GetPath()), {'pos':cmpPoint(x,y)}) + else: + try: min_url = component.get("cherrypy") + filename + except: return #chat.InfoPost('CherryPy is not started!') + min_url = dlg.GetDirectory().replace(dir_struct["user"]+'webfiles' + os.sep, + component.get("cherrypy")) + '/' + filename + # build url + if min_url == "" or min_url == "http://": return + if min_url[:7] != "http://": min_url = "http://" + min_url + # make label + if self.auto_label and min_url[-4:-3] == '.': + start = min_url.rfind("/") + 1 + min_label = min_url[start:len(min_url)-4] + if self.use_serial: min_label = '%s %d' % ( min_label, self.canvas.layers['token'].next_serial() ) + else: min_label = "" + if self.min_url.FindString(min_url) == -1: self.min_url.Append(min_url) + try: + id = 'mini-' + self.canvas.frame.session.get_next_id() + # make the new mini appear in top left of current viewable map + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + x = dc.DeviceToLogicalX(0) + y = dc.DeviceToLogicalY(0) + self.canvas.layers['token'].add_token(id, min_url, pos=cmpPoint(x,y), label=min_label) + except: + # When there is an exception here, we should be decrementing the serial_number for reuse!! + unablemsg= "Unable to load/resolve URL: " + min_url + " on resource \"" + min_label + "\"!!!\n\n" + dlg = wx.MessageDialog(self,unablemsg, 'Url not found',wx.ICON_EXCLAMATION) + dlg.ShowModal() + dlg.Destroy() + self.canvas.layers['token'].rollback_serial() + self.canvas.send_map_data() + self.canvas.Refresh(False) + + + def build_menu(self,label = "Token"): + ## Menu Changes: Rotate + ## Menu into Component + ## Remove To GameTree option + base_layer_handler.build_menu(self,label) + self.main_menu.AppendSeparator() + self.main_menu.Append(LABEL_TOOL,"&Auto label","",1) + self.main_menu.Check(LABEL_TOOL,self.auto_label) + self.main_menu.Append(SERIAL_TOOL,"&Number minis","",1) + self.main_menu.Check(SERIAL_TOOL, self.use_serial) + self.main_menu.Append(MAP_REFRESH_MINI_URLS,"&Refresh tokens") # Add the menu item + self.main_menu.AppendSeparator() + self.main_menu.Append(TOK_MOVE, "Move") + self.canvas.Bind(wx.EVT_MENU, self.on_map_board_menu_item, id=MAP_REFRESH_MINI_URLS) # Set the handler + self.canvas.Bind(wx.EVT_MENU, self.on_label, id=LABEL_TOOL) + self.canvas.Bind(wx.EVT_MENU, self.on_serial, id=SERIAL_TOOL) + # build token menu + self.min_menu = wx.Menu() + # Rectangles and hexagons require slightly different menus because of + # facing and heading possibilities. + + rot_left = wx.Menu() + rot_left_45 = rot_left.Append(-1, '45*') + self.canvas.Bind(wx.EVT_MENU, self.rot_left_45, rot_left_45) + rot_right = wx.Menu() + + rot_right_45 = rot_right.Append(-1, '45*') + self.canvas.Bind(wx.EVT_MENU, self.rot_right_45, rot_right_45) + ## Replace with Rotate. Left - Right, 45 - 90 degress. + """ + face_menu = wx.Menu() + face_menu.Append(TOK_FACING_NONE,"&None") + face_menu.Append(TOK_FACING_NORTH,"&North") + face_menu.Append(TOK_FACING_NORTHEAST,"Northeast") + face_menu.Append(TOK_FACING_EAST,"East") + face_menu.Append(TOK_FACING_SOUTHEAST,"Southeast") + face_menu.Append(TOK_FACING_SOUTH,"&South") + face_menu.Append(TOK_FACING_SOUTHWEST,"Southwest") + face_menu.Append(TOK_FACING_WEST,"West") + face_menu.Append(TOK_FACING_NORTHWEST,"Northwest") + """ + ### + + heading_menu = wx.Menu() + heading_menu.Append(TOK_HEADING_NONE,"&None") + heading_menu.Append(TOK_HEADING_NORTH,"&North") + heading_menu.Append(TOK_HEADING_NORTHEAST,"Northeast") + heading_menu.Append(TOK_HEADING_EAST,"East") + heading_menu.Append(TOK_HEADING_SOUTHEAST,"Southeast") + heading_menu.Append(TOK_HEADING_SOUTH,"&South") + heading_menu.Append(TOK_HEADING_SOUTHWEST,"Southwest") + heading_menu.Append(TOK_HEADING_WEST,"West") + heading_menu.Append(TOK_HEADING_NORTHWEST,"Northwest") + + align_menu = wx.Menu() + align_menu.Append(TOK_ALIGN_GRID_CENTER,"&Center") + align_menu.Append(TOK_ALIGN_GRID_TL,"&Top-Left") + # This is a hack to simulate a menu title, due to problem in Linux + if wx.Platform == '__WXMSW__': self.min_menu.SetTitle(label) + else: + self.min_menu.Append(TOK_TITLE_HACK,label) + self.min_menu.AppendSeparator() + self.min_menu.Append(TOK_SHOW_HIDE,"Show / Hide") + self.min_menu.Append(TOK_LOCK_UNLOCK, "Lock / Unlock") + self.min_menu.Append(TOK_REMOVE,"&Remove") + + ##Remove + #self.min_menu.Append(TOK_TO_GAMETREE,"To &Gametree") + ### + + self.min_menu.AppendMenu(TOK_HEADING_SUBMENU,"Set &Heading",heading_menu) + + ##Remove + self.min_menu.AppendMenu(TOK_ROT_LEFT,"&Rotate Left",rot_left) + self.min_menu.AppendMenu(wx.ID_ANY,"&Rotate Right",rot_right) + ### + + self.min_menu.AppendMenu(TOK_ALIGN_SUBMENU,"Snap-to &Alignment",align_menu) + self.min_menu.AppendSeparator() + zorder_menu = wx.Menu() + zorder_menu.Append(TOK_BACK_ONE,"Back one") + zorder_menu.Append(TOK_FORWARD_ONE,"Forward one") + zorder_menu.Append(TOK_TO_BACK,"To back") + zorder_menu.Append(TOK_TO_FRONT,"To front") + zorder_menu.AppendSeparator() + zorder_menu.Append(TOK_LOCK_BACK,"Lock to back") + zorder_menu.Append(TOK_LOCK_FRONT,"Lock to front") + zorder_menu.Append(TOK_FRONTBACK_UNLOCK,"Unlock Front/Back") + self.min_menu.AppendMenu(TOK_ZORDER_SUBMENU, "Token Z-Order",zorder_menu) + #self.min_menu.Append(TOK_LOCK,"&Lock") + self.min_menu.AppendSeparator() + self.min_menu.Append(TOK_PROP_DLG,"&Properties") + + + #self.min_menu.AppendSeparator() + #self.min_menu.Append(TOK_MOVE, "Move") + + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_MOVE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_SHOW_HIDE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_LOCK_UNLOCK) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_REMOVE) + + ##Remove + #self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_TO_GAMETREE) + ### + + #self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_LOCK) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_PROP_DLG) + + ##Remove + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_NONE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_EAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_WEST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_NORTH) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_SOUTH) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_NORTHEAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_SOUTHEAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_SOUTHWEST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FACING_NORTHWEST) + ### + + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_NONE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_EAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_WEST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_NORTH) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_SOUTH) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_NORTHEAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_SOUTHEAST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_SOUTHWEST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_HEADING_NORTHWEST) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_ALIGN_GRID_CENTER) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_ALIGN_GRID_TL) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_BACK_ONE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FORWARD_ONE) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_TO_BACK) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_TO_FRONT) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_LOCK_BACK) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_LOCK_FRONT) + self.canvas.Bind(wx.EVT_MENU, self.on_min_menu_item, id=TOK_FRONTBACK_UNLOCK) + ######### add plugin added menu items ######### + if len(self.mini_rclick_menu_extra_items)>0: + self.min_menu.AppendSeparator() + for item in self.mini_rclick_menu_extra_items.items(): self.min_menu.Append(item[1], item[0]) + if len(self.background_rclick_menu_extra_items)>0: + self.main_menu.AppendSeparator() + for item in self.background_rclick_menu_extra_items.items(): + self.main_menu.Append(item[1], item[0]) + + def do_min_menu(self,pos): + self.canvas.PopupMenu(self.min_menu,pos) + + def rot_left_45(self, evt): + #self.sel_rmin.rotate += 0.785 + self.sel_rmin.rotate += 1.046 + #component.get('drawn')[self.sel_rmin] = False + + def rot_right_45(self, evt): + #self.sel_rmin.rotate -= 0.785 + self.sel_rmin.rotate -= 1.046 + + def do_min_select_menu(self, min_list, pos): + # to prevent another event being processed + self.lastMenuChoice = None + self.min_select_menu = wx.Menu() + self.min_select_menu.SetTitle("Select Token") + loop_count = 1 + try: + for m in min_list: + # Either use the token label for the selection list + if m.label: self.min_select_menu.Append(loop_count, m.label) + # Or use part of the images filename as an identifier + else: + string_split = string.split(m.path,"/",) + last_string = string_split[len(string_split)-1] + self.min_select_menu.Append(loop_count, 'Unlabeled - ' + last_string[:len(last_string)-4]) + self.canvas.Bind(wx.EVT_MENU, self.min_selected, id=loop_count) + loop_count += 1 + self.canvas.PopupMenu(self.min_select_menu,pos) + except: pass + + def min_selected(self,evt): + # this is the callback function for the menu that is used to choose + # between minis when you right click, left click or left double click + # on a stack of two or more + self.canvas.Refresh(False) + self.canvas.send_map_data() + self.lastMenuChoice = evt.GetId()-1 + + def on_min_menu_item(self,evt): + id = evt.GetId() + if id == TOK_MOVE: + if self.sel_min: + self.moveSelectedMini(self.last_rclick_pos) + self.deselectAndRefresh() + return + elif id == TOK_REMOVE: self.canvas.layers['token'].del_token(self.sel_rmin) + + ##Remove + elif id == TOK_TO_GAMETREE: + min_xml = self.sel_rmin.toxml(action="new") + node_begin = "' + #print "Sending this XML to insert_xml:" + node_xml + gametree.insert_xml(str(node_xml)) + + elif id == TOK_SHOW_HIDE: + if self.sel_rmin.hide: self.sel_rmin.hide = 0 + else: self.sel_rmin.hide = 1 + elif id == TOK_LOCK_UNLOCK: + if self.sel_rmin.locked: self.sel_rmin.locked = False + else: self.sel_rmin.locked = True + if self.sel_rmin == self.sel_min: + # when we lock / unlock the selected mini make sure it isn't still selected + # or it might easily get moved by accident and be hard to move back + self.sel_min.selected = False + self.sel_min.isUpdated = True + self.sel_min = None + recycle_bin = {TOK_HEADING_NONE: FACE_NONE, TOK_HEADING_NORTH: FACE_NORTH, + TOK_HEADING_NORTHWEST: FACE_NORTHWEST, TOK_HEADING_NORTHEAST: FACE_NORTHEAST, + TOK_HEADING_EAST: FACE_EAST, TOK_HEADING_SOUTHEAST: FACE_SOUTHEAST, TOK_HEADING_SOUTHWEST: FACE_SOUTHWEST, + TOK_HEADING_SOUTH: FACE_SOUTH, TOK_HEADING_WEST: FACE_WEST} + if recycle_bin.has_key(id): + self.sel_rmin.heading = recycle_bin[id] + del recycle_bin + recycle_bin = {TOK_FACING_NONE: FACE_NONE, TOK_FACING_NORTH: FACE_NORTH, + TOK_FACING_NORTHWEST: FACE_NORTHWEST, TOK_FACING_NORTHEAST: FACE_NORTHEAST, + TOK_FACING_EAST: FACE_EAST, TOK_FACING_SOUTHEAST: FACE_SOUTHEAST, TOK_FACING_SOUTHWEST: FACE_SOUTHWEST, + TOK_FACING_SOUTH: FACE_SOUTH, TOK_FACING_WEST: FACE_WEST} + if recycle_bin.has_key(id): + self.sel_rmin.face = recycle_bin[id] + del recycle_bin + elif id == TOK_ALIGN_GRID_CENTER: self.sel_rmin.snap_to_align = SNAPTO_ALIGN_CENTER + elif id == TOK_ALIGN_GRID_TL: self.sel_rmin.snap_to_align = SNAPTO_ALIGN_TL + elif id == TOK_PROP_DLG: + old_lock_value = self.sel_rmin.locked + dlg = min_edit_dialog(self.canvas.frame.GetParent(),self.sel_rmin) + if dlg.ShowModal() == wx.ID_OK: + if self.sel_rmin == self.sel_min and self.sel_rmin.locked != old_lock_value: + # when we lock / unlock the selected mini make sure it isn't still selected + # or it might easily get moved by accident and be hard to move back + self.sel_min.selected = False + self.sel_min.isUpdated = True + self.sel_min = None + self.canvas.Refresh(False) + self.canvas.send_map_data() + return + + elif id == TOK_BACK_ONE: + # This assumes that we always start out with a z-order + # that starts at 0 and goes up to the number of + # minis - 1. If this isn't the case, then execute + # a self.canvas.layers['token'].collapse_zorder() + # before getting the oldz to test + # Save the selected minis current z-order + oldz = self.sel_rmin.zorder + # Make sure the mini isn't sticky front or back + if (oldz != TOK_STICKY_BACK) and (oldz != TOK_STICKY_FRONT): + ## print "old z-order = " + str(oldz) + self.sel_rmin.zorder -= 1 + # Re-collapse to normalize + # Note: only one update (with the final values) will be sent + self.canvas.layers['token'].collapse_zorder() + + elif id == TOK_FORWARD_ONE: + # This assumes that we always start out with a z-order + # that starts at 0 and goes up to the number of + # minis - 1. If this isn't the case, then execute + # a self.canvas.layers['token'].collapse_zorder() + # before getting the oldz to test + # Save the selected minis current z-order + oldz = self.sel_rmin.zorder + ## print "old z-order = " + str(oldz) + self.sel_rmin.zorder += 1 + + # Re-collapse to normalize + # Note: only one update (with the final values) will be sent + self.canvas.layers['token'].collapse_zorder() + + elif id == TOK_TO_FRONT: + # This assumes that we always start out with a z-order + # that starts at 0 and goes up to the number of + # minis - 1. If this isn't the case, then execute + # a self.canvas.layers['token'].collapse_zorder() + # before getting the oldz to test + # Save the selected minis current z-order + oldz = self.sel_rmin.zorder + + # Make sure the mini isn't sticky front or back + if (oldz != TOK_STICKY_BACK) and (oldz != TOK_STICKY_FRONT): + ## print "old z-order = " + str(oldz) + # The new z-order will be one more than the last index + newz = len(self.canvas.layers['token'].token) + ## print "new z-order = " + str(newz) + self.sel_rmin.zorder = newz + # Re-collapse to normalize + # Note: only one update (with the final values) will be sent + self.canvas.layers['token'].collapse_zorder() + + elif id == TOK_TO_BACK: + # This assumes that we always start out with a z-order + # that starts at 0 and goes up to the number of + # minis - 1. If this isn't the case, then execute + # a self.canvas.layers['token'].collapse_zorder() + # before getting the oldz to test + # Save the selected minis current z-order + oldz = self.sel_rmin.zorder + # Make sure the mini isn't sticky front or back + if (oldz != TOK_STICKY_BACK) and (oldz != TOK_STICKY_FRONT): + ## print "old z-order = " + str(oldz) + + # Since 0 is the lowest in a normalized order, be one less + newz = -1 + ## print "new z-order = " + str(newz) + self.sel_rmin.zorder = newz + # Re-collapse to normalize + # Note: only one update (with the final values) will be sent + self.canvas.layers['token'].collapse_zorder() + + elif id == TOK_FRONTBACK_UNLOCK: + #print "Unlocked/ unstickified..." + if self.sel_rmin.zorder == TOK_STICKY_BACK: self.sel_rmin.zorder = TOK_STICKY_BACK + 1 + elif self.sel_rmin.zorder == TOK_STICKY_FRONT: self.sel_rmin.zorder = TOK_STICKY_FRONT - 1 + elif id == TOK_LOCK_BACK: self.sel_rmin.zorder = TOK_STICKY_BACK + elif id == TOK_LOCK_FRONT: self.sel_rmin.zorder = TOK_STICKY_FRONT + # Pretty much, we always want to refresh when we go through here + # This helps us remove the redundant self.Refresh() on EVERY menu event + # that we process above. + self.sel_rmin.isUpdated = True + self.canvas.Refresh(False) + self.canvas.send_map_data() + + def on_token(self, evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role() != session.ROLE_PLAYER) and (session.use_roles()): + self.infoPost("You must be either a player or GM to use the token Layer") + return + min_url = self.min_url.GetValue() + # build url + if min_url == "" or min_url == "http://": return + if min_url[:7] != "http://" : min_url = "http://" + min_url + # make label + if self.auto_label and min_url[-4:-3] == '.': + start = min_url.rfind("/") + 1 + min_label = min_url[start:len(min_url)-4] + if self.use_serial: + min_label = '%s %d' % ( min_label, self.canvas.layers['token'].next_serial() ) + else: min_label = "" + if self.min_url.FindString(min_url) == -1: self.min_url.Append(min_url) + try: + id = 'mini-' + self.canvas.frame.session.get_next_id() + # make the new mini appear in top left of current viewable map + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + x = dc.DeviceToLogicalX(0) + y = dc.DeviceToLogicalY(0) + self.canvas.layers['token'].add_token(id, min_url, pos=cmpPoint(x,y), label=min_label) + except: + # When there is an exception here, we should be decrementing the serial_number for reuse!! + unablemsg= "Unable to load/resolve URL: " + min_url + " on resource \"" + min_label + "\"!!!\n\n" + #print unablemsg + dlg = wx.MessageDialog(self,unablemsg, 'Url not found',wx.ICON_EXCLAMATION) + dlg.ShowModal() + dlg.Destroy() + self.canvas.layers['token'].rollback_serial() + self.canvas.send_map_data() + self.canvas.Refresh(False) + #except Exception, e: + #wx.MessageBox(str(e),"token Error") + + def on_label(self,evt): + self.auto_label = not self.auto_label + self.auto_label_cb.SetValue(self.auto_label) + #self.send_map_data() + #self.Refresh() + + def on_min_list(self,evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM): + self.infoPost("You must be a GM to use this feature") + return + #d = min_list_panel(self.frame.GetParent(),self.canvas.layers,"token list") + d = min_list_panel(self.canvas.frame,self.canvas.layers,"token list") + if d.ShowModal() == wx.ID_OK: d.Destroy() + self.canvas.Refresh(False) + + def on_serial(self, evt): + self.use_serial = not self.use_serial + + def on_map_board_menu_item(self,evt): + id = evt.GetId() + if id == MAP_REFRESH_MINI_URLS: # Note: this doesn't change the mini, so no need to update the map + for mini in self.canvas.layers['token'].tokens: # For all minis + mini.set_bmp(ImageHandler.load(mini.path, 'token', mini.id)) # Reload their bmp member + self.canvas.Refresh(False) + +#################################################################### + ## old functions, changed an awful lot + + def on_left_down(self, evt): + if not self.role_is_gm_or_player() or self.alreadyDealingWithMenu(): return + mini = self.find_mini(evt, evt.CmdDown() and self.role_is_gm()) + if mini: + deselecting_selected_mini = (mini == self.sel_min) #clicked on the selected mini + self.deselectAndRefresh() + self.drag_mini = mini + if deselecting_selected_mini: return + self.sel_min = mini + self.sel_min.selected = True + self.canvas.Refresh() + else: + self.drag_mini = None + pos = self.getLogicalPosition(evt) + self.moveSelectedMini(pos) + self.deselectAndRefresh() + + def on_right_down(self, evt): + if not self.role_is_gm_or_player() or self.alreadyDealingWithMenu(): return + self.last_rclick_pos = self.getLogicalPosition(evt) + mini = self.find_mini(evt, evt.CmdDown() and self.role_is_gm()) + if mini: + self.sel_rmin = mini + if self.sel_min: self.min_menu.Enable(TOK_MOVE, True) + else: self.min_menu.Enable(TOK_MOVE, False) + self.prepare_mini_rclick_menu(evt) + self.do_min_menu(evt.GetPosition()) + else:# pass it on + if self.sel_min: self.main_menu.Enable(TOK_MOVE, True) + else: self.main_menu.Enable(TOK_MOVE, False) + self.prepare_background_rclick_menu(evt) + base_layer_handler.on_right_down(self, evt) + +#################################################################### + ## new functions + + def on_drop_files(self, x, y, filepaths): + # currently we ignore multiple files + filepath = filepaths[0] + start1 = filepath.rfind("\\") + 1 # check for both slashes in path to be on the safe side + start2 = filepath.rfind("/") + 1 + if start1 < start2: start1 = start2 + filename = filepath[start1:] + pos = filename.rfind('.') + ext = filename[pos:].lower() + #ext = filename[-4:].lower() + if(ext != ".bmp" and ext != ".gif" and ext != ".jpg" and ext != ".jpeg" and ext != ".png"): + self.infoPost("Supported file extensions are: *.bmp, *.gif, *.jpg, *.jpeg, *.png") + return + file = open(filepath, "rb") + imgdata = file.read() + file.close() + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + x = dc.DeviceToLogicalX(x) + y = dc.DeviceToLogicalY(y) + (imgtype,j) = mimetypes.guess_type(filename) + postdata = urllib.urlencode({'filename':filename, 'imgdata':imgdata, 'imgtype':imgtype}) + thread.start_new_thread(self.canvas.layers['token'].upload, (postdata, filepath), {'pos':cmpPoint(x,y)}) + + def on_tooltip_timer(self, *args): + pos = args[0] + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + pos = wx.Point(dc.DeviceToLogicalX(pos.x), dc.DeviceToLogicalY(pos.y)) + mini_list = self.getMiniListOrSelectedMini(pos) + if len(mini_list) > 0: + print mini_list + tooltip = self.get_mini_tooltip(mini_list); print tooltip + self.canvas.SetToolTipString(tooltip) + else: self.canvas.SetToolTipString("") + + def on_motion(self,evt): + if evt.Dragging() and evt.LeftIsDown(): + if self.canvas.drag is None and self.drag_mini is not None: + drag_bmp = self.drag_mini.bmp + if self.drag_mini.width and self.drag_mini.height: + tmp_image = drag_bmp.ConvertToImage() + tmp_image.Rescale(int(self.drag_mini.width * self.canvas.layers['grid'].mapscale), + int(self.drag_mini.height * self.canvas.layers['grid'].mapscale)) + tmp_image.ConvertAlphaToMask() + + ### Should show rotated image when dragging. + if self.drag_mini.rotate != 0 : + tmp_image = tmp_image.Rotate(self.drag_mini.rotate, + (self.drag_mini.width/2, self.drag_mini.height/2)) + + drag_bmp = tmp_image.ConvertToBitmap() + mask = wx.Mask(drag_bmp, wx.Colour(tmp_image.GetMaskRed(), + tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) + drag_bmp.SetMask(mask) + tmp_image = tmp_image.ConvertToGreyscale() + self.drag_mini.gray = True + self.drag_mini.isUpdated = True + def refresh(): + self.canvas.drag.Hide() + self.canvas.Refresh(False) + wx.CallAfter(refresh) + self.canvas.drag = wx.DragImage(drag_bmp) + self.drag_offset = self.getLogicalPosition(evt)- self.drag_mini.pos + self.canvas.drag.BeginDrag((int(self.drag_offset.x * self.canvas.layers['grid'].mapscale), + int(self.drag_offset.y * self.canvas.layers['grid'].mapscale)), self.canvas, False) + elif self.canvas.drag is not None: + self.canvas.drag.Move(evt.GetPosition()) + self.canvas.drag.Show() + # reset tool tip timer + self.canvas.SetToolTipString("") + self.tooltip_timer.Restart(self.tooltip_delay_miliseconds, evt.GetPosition()) + + def on_left_up(self,evt): + if self.canvas.drag: + self.canvas.drag.Hide() + self.canvas.drag.EndDrag() + self.canvas.drag = None + pos = self.getLogicalPosition(evt) + pos = pos - self.drag_offset + if self.canvas.layers['grid'].snap: + nudge = int(self.canvas.layers['grid'].unit_size/2) + if self.canvas.layers['grid'].mode != GRID_ISOMETRIC: + if self.drag_mini.snap_to_align == SNAPTO_ALIGN_CENTER: + pos = pos + (int(self.drag_mini.bmp.GetWidth()/2),int(self.drag_mini.bmp.GetHeight()/2)) + else: pos = pos + (nudge, nudge) + else:# GRID_ISOMETRIC + if self.drag_mini.snap_to_align == SNAPTO_ALIGN_CENTER: + pos = pos + (int(self.drag_mini.bmp.GetWidth()/2), self.drag_mini.bmp.GetHeight()) + else: pass # no nudge for the isomorphic / top-left + self.sel_min = self.drag_mini + # check to see if the mouse is inside the window still + w = self.canvas.GetClientSizeTuple() # this is the window size, minus any scrollbars + p = evt.GetPosition() # compare the window size, w with the non-logical position + c = self.canvas.size # this is the grid size, compare with the logical position, pos + # both are [width, height] + if p.x>=0 and pos.x=0 and pos.y session.ROLE_GM) and (session.my_role() <> session.ROLE_PLAYER) and (session.use_roles()): + self.infoPost("You must be either a player or GM to use the token Layer") + return False + return True + + def role_is_gm(self): + session = self.canvas.frame.session + if (session.my_role() <> session.ROLE_GM) and (session.use_roles()): return False + return True + + def alreadyDealingWithMenu(self): + return self.lastMenuChoice is not None + + def getLastMenuChoice(self): + choice = self.lastMenuChoice + self.lastMenuChoice = None + return choice + + def getLogicalPosition(self, evt): + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(self.canvas.layers['grid'].mapscale,self.canvas.layers['grid'].mapscale) + pos = evt.GetLogicalPosition(dc) + return pos + + def getMiniListOrSelectedMini(self, pos, include_locked=False): + if self.sel_min and self.sel_min.hit_test(pos): + # clicked on the selected mini - assume that is the intended target + # and don't give a choice of it and any other minis stacked with it + mini_list = [] + mini_list.append(self.sel_min) + return mini_list + mini_list = self.canvas.layers['token'].find_token(pos, (not include_locked)) + if mini_list: return mini_list + mini_list = [] + return mini_list + + def deselectAndRefresh(self): + if self.sel_min: + self.sel_min.selected = False + self.sel_min.isUpdated = True + self.canvas.Refresh(False) + self.canvas.send_map_data() + self.sel_min = None + + def moveSelectedMini(self, pos): + if self.sel_min: self.moveMini(pos, self.sel_min) + + def moveMini(self, pos, mini): + grid = self.canvas.layers['grid'] + mini.pos = grid.get_snapped_to_pos(pos, mini.snap_to_align, mini.bmp.GetWidth(), mini.bmp.GetHeight()) + + def find_mini(self, evt, include_locked): + if not self.role_is_gm_or_player() or self.alreadyDealingWithMenu(): return + pos = self.getLogicalPosition(evt) + mini_list = self.getMiniListOrSelectedMini(pos, include_locked) + mini = None + if len(mini_list) > 1: + try: self.do_min_select_menu(mini_list, evt.GetPosition()) + except: pass + choice = self.getLastMenuChoice() + if choice == None: return None # left menu without making a choice, eg by clicking outside menu + mini = mini_list[choice] + elif len(mini_list) == 1: mini = mini_list[0] + return mini + diff -r 15e32ec131cb -r 2f2bebe9c77f plugins/bcg/tokens.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/bcg/tokens.py Tue Oct 06 22:16:34 2009 -0500 @@ -0,0 +1,600 @@ +# Copyright (C) 2000-2001 The OpenRPG Project +# +# openrpg-dev@lists.sourceforge.net +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# -- +# +# File: mapper/tokens.py +# Author: Chris Davis +# Maintainer: +# Version: +# $Id: tokens.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $ +# +# Description: This file contains some of the basic definitions for the chat +# utilities in the orpg project. +# +__version__ = "$Id: tokens.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $" + +from orpg.mapper.base import * +import thread +import time +import urllib +import os.path + +from orpg.tools.orpg_settings import settings + +MIN_STICKY_BACK = -0XFFFFFF +MIN_STICKY_FRONT = 0xFFFFFF + +##---------------------------------------- +## token object +##---------------------------------------- + +FACE_NONE = 0 +FACE_NORTH = 1 +FACE_NORTHEAST = 2 +FACE_EAST = 3 +FACE_SOUTHEAST = 4 +FACE_SOUTH = 5 +FACE_SOUTHWEST = 6 +FACE_WEST = 7 +FACE_NORTHWEST = 8 +SNAPTO_ALIGN_CENTER = 0 +SNAPTO_ALIGN_TL = 1 + +def cmp_zorder(first,second): + f = first.zorder + s = second.zorder + if f == None: f = 0 + if s == None: s = 0 + if f == s: value = 0 + elif f < s: value = -1 + else: value = 1 + return value + +class BmpToken: + def __init__(self, id,path, bmp, pos=cmpPoint(0,0), + heading=FACE_NONE, rotate=0, label="", + locked=False, hide=False, snap_to_align=SNAPTO_ALIGN_CENTER, + zorder=0, width=0, height=0, log=None, local=False, localPath='', localTime=-1): + self.heading = heading + self.rotate = rotate + self.label = label + self.path = path + self.bmp = bmp + self.pos = pos + self.selected = False + self.locked = locked + self.snap_to_align = snap_to_align + self.hide = hide + self.id = id + self.zorder = zorder + self.left = 0 + self.local = local + self.localPath = localPath + self.localTime = localTime + if not width: self.width = 0 + else: self.width = width + if not height: self.height = 0 + else: self.height = height + self.right = bmp.GetWidth() + self.top = 0 + self.bottom = bmp.GetHeight() + self.isUpdated = False + self.gray = False + self.drawn = {} + + def __del__(self): + del self.bmp + self.bmp = None + + def set_bmp(self, bmp): + self.bmp = bmp + + def set_min_props(self, heading=FACE_NONE, rotate=0, label="", locked=False, hide=False, width=0, height=0): + self.heading = heading + self.rotate = rotate + self.label = label + if locked: self.locked = True + else: self.locked = False + if hide: self.hide = True + else: self.hide = False + self.width = int(width) + self.height = int(height) + self.isUpdated = True + + def hit_test(self, pt): + rect = self.get_rect() + result = None + result = rect.InsideXY(pt.x, pt.y) + return result + + def get_rect(self): + ret = wx.Rect(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) + return ret + + def draw(self, dc, mini_layer, op=wx.COPY): + if isinstance(self.bmp, tuple): + self.bmp = wx.ImageFromMime(self.bmp[1], self.bmp[2]).ConvertToBitmap() + if self.bmp != None and self.bmp.Ok(): + # check if hidden and GM: we outline the mini in grey (little bit smaller than the actual size) + # and write the label in the center of the mini + if self.hide and mini_layer.canvas.frame.session.my_role() == mini_layer.canvas.frame.session.ROLE_GM: + # set the width and height of the image + if self.width and self.height: + tmp_image = self.bmp.ConvertToImage() + tmp_image.Rescale(int(self.width), int(self.height)) + tmp_image.ConvertAlphaToMask() + self.bmp = tmp_image.ConvertToBitmap() + mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), + tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) + self.bmp.SetMask(mask) + del tmp_image + del mask + self.left = 0 + self.right = self.bmp.GetWidth() + self.top = 0 + self.bottom = self.bmp.GetHeight() + # grey outline + graypen = wx.Pen("gray", 1, wx.DOT) + dc.SetPen(graypen) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + #if width or height < 20 then offset = 1 + if self.bmp.GetWidth() <= 20: xoffset = 1 + else: xoffset = 5 + if self.bmp.GetHeight() <= 20: yoffset = 1 + else: yoffset = 5 + dc.DrawRectangle(self.pos.x + xoffset, + self.pos.y + yoffset, self.bmp.GetWidth() - (xoffset * 2), + self.bmp.GetHeight() - (yoffset * 2)) + dc.SetBrush(wx.NullBrush) + dc.SetPen(wx.NullPen) + ## draw label in the center of the mini + label = mini_layer.get_mini_label(self) + if len(label): + dc.SetTextForeground(wx.RED) + (textWidth,textHeight) = dc.GetTextExtent(label) + x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 + y = self.pos.y + (self.bmp.GetHeight() / 2) + dc.SetPen(wx.GREY_PEN) + dc.SetBrush(wx.LIGHT_GREY_BRUSH) + dc.DrawRectangle(x, y, textWidth+2, textHeight+2) + if (textWidth+2 > self.right): + self.right += int((textWidth+2-self.right)/2)+1 + self.left -= int((textWidth+2-self.right)/2)+1 + self.bottom = y+textHeight+2-self.pos.y + dc.SetPen(wx.NullPen) + dc.SetBrush(wx.NullBrush) + dc.DrawText(label, x+1, y+1) + + #selected outline + if self.selected: + dc.SetPen(wx.RED_PEN) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) + dc.SetBrush(wx.NullBrush) + dc.SetPen(wx.NullPen) + return True + elif self.hide: return True + + else: + # set the width and height of the image + bmp = self.bmp + if self.width and self.height: + tmp_image = self.bmp.ConvertToImage() + tmp_image.Rescale(int(self.width), int(self.height)) + tmp_image.ConvertAlphaToMask() + self.bmp = tmp_image.ConvertToBitmap() + mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), + tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) + self.bmp.SetMask(mask) + if self.gray: + tmp_image = tmp_image.ConvertToGreyscale() + bmp = tmp_image.ConvertToBitmap() + else: bmp = self.bmp + + if self.rotate != 0: + x = bmp.GetWidth(); print x + y = bmp.GetHeight(); print y + img = bmp.ConvertToImage() + img = img.Rotate(self.rotate, (3, 80), True) + img.ConvertAlphaToMask() + + bmp = img.ConvertToBitmap() + mask = wx.Mask(bmp, wx.Colour(img.GetMaskRed(), + img.GetMaskGreen(), img.GetMaskBlue())) + bmp.SetMask(mask) + + dc.DrawBitmap(bmp, self.pos.x, self.pos.y, True) + component.get('drawn')[bmp] = True + self.left = 0 + self.right = self.bmp.GetWidth() + self.top = 0 + self.bottom = self.bmp.GetHeight() + + # Draw the heading if needed + if self.heading: + x_adjust = 0 + y_adjust = 4 + x_half = self.bmp.GetWidth()/2 + y_half = self.bmp.GetHeight()/2 + x_quarter = self.bmp.GetWidth()/4 + y_quarter = self.bmp.GetHeight()/4 + x_3quarter = x_quarter*3 + y_3quarter = y_quarter*3 + x_full = self.bmp.GetWidth() + y_full = self.bmp.GetHeight() + x_center = self.pos.x + x_half + y_center = self.pos.y + y_half + # Remember, the pen/brush must be a different color than the + # facing marker!!!! We'll use black/cyan for starters. + # Also notice that we will draw the heading on top of the + # larger facing marker. + dc.SetPen(wx.BLACK_PEN) + dc.SetBrush(wx.CYAN_BRUSH) + triangle = [] + + # Figure out which direction to draw the marker!! + if self.heading == FACE_NORTH: + triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) + triangle.append(cmpPoint(x_center, y_center - y_3quarter )) + triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) + elif self.heading == FACE_SOUTH: + triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) + triangle.append(cmpPoint(x_center, y_center + y_3quarter )) + triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) + elif self.heading == FACE_NORTHEAST: + triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) + triangle.append(cmpPoint(x_center + x_3quarter, y_center - y_3quarter )) + triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) + elif self.heading == FACE_EAST: + triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) + triangle.append(cmpPoint(x_center + x_3quarter, y_center )) + triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) + elif self.heading == FACE_SOUTHEAST: + triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) + triangle.append(cmpPoint(x_center + x_3quarter, y_center + y_3quarter )) + triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) + elif self.heading == FACE_SOUTHWEST: + triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) + triangle.append(cmpPoint(x_center - x_3quarter, y_center + y_3quarter )) + triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) + elif self.heading == FACE_WEST: + triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) + triangle.append(cmpPoint(x_center - x_3quarter, y_center )) + triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) + elif self.heading == FACE_NORTHWEST: + triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) + triangle.append(cmpPoint(x_center - x_3quarter, y_center - y_3quarter )) + triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) + dc.DrawPolygon(triangle) + dc.SetBrush(wx.NullBrush) + dc.SetPen(wx.NullPen) + #selected outline + if self.selected: + dc.SetPen(wx.RED_PEN) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) + dc.SetBrush(wx.NullBrush) + dc.SetPen(wx.NullPen) + # draw label + label = mini_layer.get_mini_label(self) + if len(label): + dc.SetTextForeground(wx.RED) + (textWidth,textHeight) = dc.GetTextExtent(label) + x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 + y = self.pos.y + self.bmp.GetHeight() + 6 + dc.SetPen(wx.WHITE_PEN) + dc.SetBrush(wx.WHITE_BRUSH) + dc.DrawRectangle(x,y,textWidth+2,textHeight+2) + if (textWidth+2 > self.right): + self.right += int((textWidth+2-self.right)/2)+1 + self.left -= int((textWidth+2-self.right)/2)+1 + self.bottom = y+textHeight+2-self.pos.y + dc.SetPen(wx.NullPen) + dc.SetBrush(wx.NullBrush) + dc.DrawText(label,x+1,y+1) + self.top-=5 + self.bottom+=5 + self.left-=5 + self.right+=5 + return True + else: return False + + def toxml(self, action="update"): + if action == "del": + xml_str = "" + return xml_str + xml_str = "= 10): font_size -= 2 + self.label_font = wx.Font(font_size, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, + False, settings.get_setting('defaultfont')) + + def next_serial(self): + self.serial_number += 1 + return self.serial_number + + def get_next_highest_z(self): + z = len(self.tokens)+1 + return z + + def cleanly_collapse_zorder(self): + # lock the zorder stuff + sorted_tokens = self.tokens[:] + sorted_tokens.sort(cmp_zorder) + i = 0 + for mini in sorted_tokens: + mini.zorder = i + i = i + 1 + # unlock the zorder stuff + + def collapse_zorder(self): + # lock the zorder stuff + sorted_tokens = self.tokens[:] + sorted_tokens.sort(cmp_zorder) + i = 0 + for mini in sorted_tokens: + if (mini.zorder != MIN_STICKY_BACK) and (mini.zorder != MIN_STICKY_FRONT): mini.zorder = i + else: pass + i = i + 1 + # unlock the zorder stuff + + def rollback_serial(self): + self.serial_number -= 1 + + def add_token(self, id, path, pos=cmpPoint(0,0), label="", heading=FACE_NONE, + rotate=0, width=0, height=0, local=False, localPath='', localTime=-1): + bmp = ImageHandler.load(path, 'token', id) + if bmp: + mini = BmpToken(id, path, bmp, pos, heading, rotate, label, + zorder=self. get_next_highest_z(), width=width, + height=height, local=local, localPath=localPath, localTime=localTime) + self.tokens.append(mini) + self.drawn[mini.bmp] = False + xml_str = "" + xml_str += mini.toxml("new") + xml_str += "" + component.get('session').send(xml_str) + + def get_token_by_id(self, id): + for mini in self.tokens: + if str(mini.id) == str(id): + return mini + return None + + def del_token(self, min): + xml_str = "" + xml_str += min.toxml("del") + xml_str += "" + self.canvas.frame.session.send(xml_str) + self.tokens.remove(min) + del min + self.collapse_zorder() + + def del_all_tokens(self): + while len(self.tokens): + min = self.tokens.pop() + del min + self.collapse_zorder() + + def layerDraw(self, dc, topleft, size): + dc.SetFont(self.label_font) + sorted_tokens = self.tokens[:] + sorted_tokens.sort(cmp_zorder) + for m in sorted_tokens: + if (m.pos.x>topleft[0]-m.right and + m.pos.y>topleft[1]-m.bottom and + m.pos.x 0: + return min_list + else: return None + + def layerToXML(self, action="update"): + """ format """ + minis_string = "" + if self.tokens: + for m in self.tokens: minis_string += m.toxml(action) + if minis_string != '': + s = "