Mercurial > traipse_dev
comparison orpg/mapper/map.py @ 0:4385a7d0efd1 grumpy-goblin
Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author | sirebral |
---|---|
date | Tue, 14 Jul 2009 16:41:58 -0500 |
parents | |
children | 0b8b7e3ed78d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4385a7d0efd1 |
---|---|
1 # Copyright (C) 2000-2001 The OpenRPG Project | |
2 # | |
3 # openrpg-dev@lists.sourceforge.net | |
4 # | |
5 # This program is free software; you can redistribute it and/or modify | |
6 # it under the terms of the GNU General Public License as published by | |
7 # the Free Software Foundation; either version 2 of the License, or | |
8 # (at your option) any later version. | |
9 # | |
10 # This program is distributed in the hope that it will be useful, | |
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 # GNU General Public License for more details. | |
14 # | |
15 # You should have received a copy of the GNU General Public License | |
16 # along with this program; if not, write to the Free Software | |
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 # -- | |
19 # | |
20 # File: mapper/map.py | |
21 # Author: OpenRPG | |
22 # Maintainer: | |
23 # Version: | |
24 # $Id: map.py,v 1.73 2007/12/07 20:39:49 digitalxero Exp $ | |
25 # | |
26 # Description: | |
27 # | |
28 __version__ = "$Id: map.py,v 1.73 2007/12/07 20:39:49 digitalxero Exp $" | |
29 | |
30 from map_version import MAP_VERSION | |
31 from map_msg import * | |
32 from min_dialogs import * | |
33 from map_prop_dialog import * | |
34 import orpg.dirpath | |
35 import random | |
36 import os | |
37 import thread | |
38 import gc | |
39 import traceback | |
40 from miniatures_handler import * | |
41 from whiteboard_handler import * | |
42 from background_handler import * | |
43 from fog_handler import * | |
44 from images import ImageHandler | |
45 from grid_handler import * | |
46 from map_handler import * | |
47 from orpg.orpgCore import open_rpg | |
48 | |
49 # Various marker modes for player tools on the map | |
50 MARKER_MODE_NONE = 0 | |
51 MARKER_MODE_MEASURE = 1 | |
52 MARKER_MODE_TARGET = 2 | |
53 MARKER_MODE_AREA_TARGET = 3 | |
54 | |
55 class MapCanvas(wx.ScrolledWindow): | |
56 def __init__(self, parent, ID, isEditor=0): | |
57 self.parent = parent | |
58 self.log = open_rpg.get_component("log") | |
59 self.log.log("Enter MapCanvas", ORPG_DEBUG) | |
60 self.settings = open_rpg.get_component("settings") | |
61 self.session = open_rpg.get_component("session") | |
62 wx.ScrolledWindow.__init__(self, parent, ID, style=wx.HSCROLL | wx.VSCROLL | wx.FULL_REPAINT_ON_RESIZE | wx.SUNKEN_BORDER ) | |
63 self.frame = parent | |
64 self.MAP_MODE = 1 #Mode 1 = MINI, 2 = DRAW, 3 = TAPE MEASURE | |
65 self.layers = {} | |
66 self.layers['bg'] = layer_back_ground(self) | |
67 self.layers['grid'] = grid_layer(self) | |
68 self.layers['whiteboard'] = whiteboard_layer(self) | |
69 self.layers['miniatures'] = miniature_layer(self) | |
70 self.layers['fog'] = fog_layer(self) | |
71 self.Bind(wx.EVT_ERASE_BACKGROUND, self.on_erase_background) | |
72 self.Bind(wx.EVT_PAINT, self.on_paint) | |
73 self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down) | |
74 self.Bind(wx.EVT_LEFT_DCLICK, self.on_left_dclick) | |
75 self.Bind(wx.EVT_LEFT_UP, self.on_left_up) | |
76 self.Bind(wx.EVT_RIGHT_DOWN, self.on_right_down) | |
77 self.Bind(wx.EVT_MOTION, self.on_motion) | |
78 self.Bind(wx.EVT_SCROLLWIN, self.on_scroll) | |
79 self.Bind(wx.EVT_CHAR, self.on_char) | |
80 self.Bind(wx.EVT_SIZE, self.on_resize) | |
81 self.set_size((1000,1000)) | |
82 self.root_dir = os.getcwd() | |
83 self.size_change = 0 | |
84 self.isEditor = isEditor | |
85 self.map_version = MAP_VERSION | |
86 self.cacheSize = 32 | |
87 # Create the marker mode attributes for the map | |
88 self.markerMode = MARKER_MODE_NONE | |
89 self.markerStart = wx.Point( -1, -1 ) | |
90 self.markerStop = wx.Point( -1, -1 ) | |
91 self.markerMidpoint = wx.Point( -1, -1 ) | |
92 self.markerAngle = 0.0 | |
93 # Optimization of map refreshing during busy map load | |
94 self.lastRefreshValue = 0 | |
95 self.requireRefresh = 0 | |
96 self.lastRefreshTime = 0 | |
97 self.zoom_display_timer = wx.Timer(self, wx.NewId()) | |
98 self.Bind(wx.EVT_TIMER, self.better_refresh, self.zoom_display_timer) | |
99 random.seed( time.time() ) | |
100 self.image_timer = wx.Timer(self, wx.NewId()) | |
101 self.Bind(wx.EVT_TIMER, self.processImages, self.image_timer) | |
102 self.image_timer.Start(100) | |
103 # Used to check if we've used the user cache size value | |
104 self.cacheSizeSet = False | |
105 self.inside = 0 | |
106 # miniatures drag | |
107 self.drag = None | |
108 self.log.log("Exit MapCanvas", ORPG_DEBUG) | |
109 | |
110 def better_refresh(self, event=None): | |
111 self.log.log("Enter MapCanvas->better_refresh(self)", ORPG_DEBUG) | |
112 self.Refresh(True) | |
113 self.log.log("Eexit MapCanvas->better_refresh(self)", ORPG_DEBUG) | |
114 | |
115 def pre_destory_cleanup(self): | |
116 self.log.log("Enter MapCanvas->pre_destory_cleanup(self)", ORPG_DEBUG) | |
117 self.layers["miniatures"].del_all_miniatures() | |
118 self.log.log("Exit MapCanvas->pre_destory_cleanup(self)", ORPG_DEBUG) | |
119 | |
120 def processImages(self, evt=None): | |
121 self.log.log("Enter MapCanvas->processImages(self)", ORPG_DEBUG) | |
122 self.session = open_rpg.get_component("session") | |
123 if self.session.my_role() == self.session.ROLE_LURKER or (str(self.session.group_id) == '0' and str(self.session.status) == '1'): | |
124 cidx = self.parent.get_tab_index("Background") | |
125 self.parent.layer_tabs.EnableTab(cidx, False) | |
126 cidx = self.parent.get_tab_index("Grid") | |
127 self.parent.layer_tabs.EnableTab(cidx, False) | |
128 cidx = self.parent.get_tab_index("Miniatures") | |
129 self.parent.layer_tabs.EnableTab(cidx, False) | |
130 cidx = self.parent.get_tab_index("Whiteboard") | |
131 self.parent.layer_tabs.EnableTab(cidx, False) | |
132 cidx = self.parent.get_tab_index("Fog") | |
133 self.parent.layer_tabs.EnableTab(cidx, False) | |
134 cidx = self.parent.get_tab_index("General") | |
135 self.parent.layer_tabs.EnableTab(cidx, False) | |
136 else: | |
137 cidx = self.parent.get_tab_index("Background") | |
138 if not self.parent.layer_tabs.GetEnabled(cidx): | |
139 cidx = self.parent.get_tab_index("Miniatures") | |
140 self.parent.layer_tabs.EnableTab(cidx, True) | |
141 cidx = self.parent.get_tab_index("Whiteboard") | |
142 self.parent.layer_tabs.EnableTab(cidx, True) | |
143 cidx = self.parent.get_tab_index("Background") | |
144 self.parent.layer_tabs.EnableTab(cidx, False) | |
145 cidx = self.parent.get_tab_index("Grid") | |
146 self.parent.layer_tabs.EnableTab(cidx, False) | |
147 cidx = self.parent.get_tab_index("Fog") | |
148 self.parent.layer_tabs.EnableTab(cidx, False) | |
149 cidx = self.parent.get_tab_index("General") | |
150 self.parent.layer_tabs.EnableTab(cidx, False) | |
151 if self.session.my_role() == self.session.ROLE_GM: | |
152 cidx = self.parent.get_tab_index("Background") | |
153 self.parent.layer_tabs.EnableTab(cidx, True) | |
154 cidx = self.parent.get_tab_index("Grid") | |
155 self.parent.layer_tabs.EnableTab(cidx, True) | |
156 cidx = self.parent.get_tab_index("Fog") | |
157 self.parent.layer_tabs.EnableTab(cidx, True) | |
158 cidx = self.parent.get_tab_index("General") | |
159 self.parent.layer_tabs.EnableTab(cidx, True) | |
160 if not self.cacheSizeSet: | |
161 self.cacheSizeSet = True | |
162 cacheSize = self.settings.get_setting("ImageCacheSize") | |
163 if len(cacheSize): | |
164 self.cacheSize = int(cacheSize) | |
165 else: | |
166 self.log.log("Default cache size being used.", ORPG_GENERAL) | |
167 self.log.log("Current image cache size is set at " + str(self.cacheSize) + " images, using random purge.", ORPG_GENERAL) | |
168 if not ImageHandler.Queue.empty(): | |
169 (path, image_type, imageId) = ImageHandler.Queue.get() | |
170 img = wx.ImageFromMime(path[1], path[2]).ConvertToBitmap() | |
171 try: | |
172 # Now, apply the image to the proper object | |
173 if image_type == "miniature": | |
174 min = self.layers['miniatures'].get_miniature_by_id(imageId) | |
175 min.set_bmp(img) | |
176 elif image_type == "background" or image_type == "texture": | |
177 self.layers['bg'].bg_bmp = img | |
178 if image_type == "background": | |
179 self.set_size([img.GetWidth(), img.GetHeight()]) | |
180 except: | |
181 pass | |
182 # Flag that we now need to refresh! | |
183 self.requireRefresh += 1 | |
184 | |
185 # Randomly purge an item from the cache, while this is lamo, it does | |
186 # keep the cache from growing without bounds, which is pretty important! | |
187 if len(ImageHandler.Cache) >= self.cacheSize: | |
188 ImageHandler.cleanCache() | |
189 else: | |
190 # Now, make sure not only that we require a refresh, but that enough time has | |
191 # gone by since our last refresh. This keeps back to back refreshing occuring during | |
192 # large map loads. Of course, we are now trying to pack as many image refreshes as | |
193 # we can into a single cycle. | |
194 if self.requireRefresh and (self.requireRefresh == self.lastRefreshValue): | |
195 if (self.lastRefreshTime) < time.time(): | |
196 self.requireRefresh = 0 | |
197 self.lastRefreshValue = 0 | |
198 self.lastRefreshTime = time.time() | |
199 self.Refresh(True) | |
200 else: | |
201 self.lastRefreshValue = self.requireRefresh | |
202 self.log.log("Exit MapCanvas->processImages(self)", ORPG_DEBUG) | |
203 | |
204 def on_scroll(self, evt): | |
205 self.log.log("Enter MapCanvas->on_scroll(self, evt)", ORPG_DEBUG) | |
206 if self.drag: | |
207 self.drag.Hide() | |
208 if self.settings.get_setting("AlwaysShowMapScale") == "1": | |
209 self.printscale() | |
210 evt.Skip() | |
211 self.log.log("Exit MapCanvas->on_scroll(self, evt)", ORPG_DEBUG) | |
212 | |
213 def on_char(self, evt): | |
214 self.log.log("Enter MapCanvas->on_char(self, evt)", ORPG_DEBUG) | |
215 if self.settings.get_setting("AlwaysShowMapScale") == "1": | |
216 self.printscale() | |
217 evt.Skip() | |
218 self.log.log("Exit MapCanvas->on_char(self, evt)", ORPG_DEBUG) | |
219 | |
220 def printscale(self): | |
221 self.log.log("Enter MapCanvas->printscale(self)", ORPG_DEBUG) | |
222 wx.BeginBusyCursor() | |
223 dc = wx.ClientDC(self) | |
224 self.PrepareDC(dc) | |
225 self.showmapscale(dc) | |
226 self.Refresh(True) | |
227 wx.EndBusyCursor() | |
228 self.log.log("Exit MapCanvas->printscale(self)", ORPG_DEBUG) | |
229 | |
230 def send_map_data(self, action="update"): | |
231 self.log.log("Enter MapCanvas->send_map_data(self, " + action +")", ORPG_DEBUG) | |
232 wx.BeginBusyCursor() | |
233 send_text = self.toxml(action) | |
234 if send_text: | |
235 if not self.isEditor: | |
236 self.frame.session.send(send_text) | |
237 wx.EndBusyCursor() | |
238 self.log.log("Exit MapCanvas->send_map_data(self, " + action +")", ORPG_DEBUG) | |
239 | |
240 def get_size(self): | |
241 self.log.log("Enter MapCanvas->get_size(self)", ORPG_DEBUG) | |
242 self.log.log("Exit MapCanvas->get_size(self) return " + str(self.size), ORPG_DEBUG) | |
243 return self.size | |
244 | |
245 def set_size(self, size): | |
246 self.log.log("Enter MapCanvas->set_size(self, size)", ORPG_DEBUG) | |
247 if size[0] < 300: | |
248 size = (300, size[1]) | |
249 if size[1] < 300: | |
250 size = (size[0], 300) | |
251 self.size_changed = 1 | |
252 self.size = size | |
253 self.fix_scroll() | |
254 self.layers['fog'].resize(size) | |
255 self.log.log("Exit MapCanvas->set_size(self, size)", ORPG_DEBUG) | |
256 | |
257 def fix_scroll(self): | |
258 self.log.log("Enter MapCanvas->fix_scroll(self)", ORPG_DEBUG) | |
259 scale = self.layers['grid'].mapscale | |
260 pos = self.GetViewStart() | |
261 unit = self.GetScrollPixelsPerUnit() | |
262 pos = [pos[0]*unit[0],pos[1]*unit[1]] | |
263 size = self.GetClientSize() | |
264 unit = [10*scale,10*scale] | |
265 if (unit[0] == 0 or unit[1] == 0): | |
266 self.log.log("Exit MapCanvas->fix_scroll(self)", ORPG_DEBUG) | |
267 return | |
268 pos[0] /= unit[0] | |
269 pos[1] /= unit[1] | |
270 mx = [int(self.size[0]*scale/unit[0])+1, int(self.size[1]*scale/unit[1]+1)] | |
271 self.SetScrollbars(unit[0], unit[1], mx[0], mx[1], pos[0], pos[1]) | |
272 self.log.log("Exit MapCanvas->fix_scroll(self)", ORPG_DEBUG) | |
273 | |
274 def on_resize(self, evt): | |
275 self.log.log("Enter MapCanvas->on_resize(self, evt)", ORPG_DEBUG) | |
276 self.fix_scroll() | |
277 wx.CallAfter(self.Refresh, True) | |
278 evt.Skip() | |
279 self.log.log("Exit MapCanvas->on_resize(self, evt)", ORPG_DEBUG) | |
280 | |
281 def on_erase_background(self, evt): | |
282 self.log.log("Enter MapCanvas->on_erase_background(self, evt)", ORPG_DEBUG) | |
283 evt.Skip() | |
284 self.log.log("Exit MapCanvas->on_erase_background(self, evt)", ORPG_DEBUG) | |
285 | |
286 def on_paint(self, evt): | |
287 self.log.log("Enter MapCanvas->on_paint(self, evt)", ORPG_DEBUG) | |
288 scale = self.layers['grid'].mapscale | |
289 scrollsize = self.GetScrollPixelsPerUnit() | |
290 clientsize = self.GetClientSize() | |
291 topleft1 = self.GetViewStart() | |
292 topleft = [topleft1[0]*scrollsize[0], topleft1[1]*scrollsize[1]] | |
293 if (clientsize[0] > 1) and (clientsize[1] > 1): | |
294 dc = wx.MemoryDC() | |
295 bmp = wx.EmptyBitmap(clientsize[0]+1, clientsize[1]+1) | |
296 dc.SelectObject(bmp) | |
297 dc.SetPen(wx.TRANSPARENT_PEN) | |
298 dc.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID)) | |
299 dc.DrawRectangle(0,0,clientsize[0]+1,clientsize[1]+1) | |
300 dc.SetDeviceOrigin(-topleft[0], -topleft[1]) | |
301 dc.SetUserScale(scale, scale) | |
302 self.layers['bg'].layerDraw(dc, scale, topleft, clientsize) | |
303 self.layers['grid'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], [clientsize[0]/scale, clientsize[1]/scale]) | |
304 self.layers['miniatures'].layerDraw(dc, [topleft[0]/scale, topleft[1]/scale], [clientsize[0]/scale, clientsize[1]/scale]) | |
305 self.layers['whiteboard'].layerDraw(dc) | |
306 self.layers['fog'].layerDraw(dc, topleft, clientsize) | |
307 dc.SetPen(wx.NullPen) | |
308 dc.SetBrush(wx.NullBrush) | |
309 dc.SelectObject(wx.NullBitmap) | |
310 del dc | |
311 wdc = self.preppaint() | |
312 wdc.DrawBitmap(bmp, topleft[0], topleft[1]) | |
313 if self.frame.settings.get_setting("AlwaysShowMapScale") == "1": | |
314 self.showmapscale(wdc) | |
315 try: | |
316 evt.Skip() | |
317 except: | |
318 pass | |
319 self.log.log("Exit MapCanvas->on_paint(self, evt)", ORPG_DEBUG) | |
320 | |
321 def preppaint(self): | |
322 self.log.log("Enter MapCanvas->preppaint(self)", ORPG_DEBUG) | |
323 dc = wx.PaintDC(self) | |
324 self.PrepareDC(dc) | |
325 self.log.log("Exit MapCanvas->preppaint(self)", ORPG_DEBUG) | |
326 return (dc) | |
327 | |
328 def showmapscale(self, dc): | |
329 self.log.log("Enter MapCanvas->showmapscale(self, dc)", ORPG_DEBUG) | |
330 scalestring = "Scale x" + `self.layers['grid'].mapscale`[:3] | |
331 (textWidth, textHeight) = dc.GetTextExtent(scalestring) | |
332 dc.SetUserScale(1, 1) | |
333 dc.SetPen(wx.LIGHT_GREY_PEN) | |
334 dc.SetBrush(wx.LIGHT_GREY_BRUSH) | |
335 x = dc.DeviceToLogicalX(0) | |
336 y = dc.DeviceToLogicalY(0) | |
337 dc.DrawRectangle(x, y, textWidth+2, textHeight+2) | |
338 dc.SetPen(wx.RED_PEN) | |
339 dc.DrawText(scalestring, x+1, y+1) | |
340 dc.SetPen(wx.NullPen) | |
341 dc.SetBrush(wx.NullBrush) | |
342 self.log.log("Exit MapCanvas->showmapscale(self, dc)", ORPG_DEBUG) | |
343 | |
344 def snapMarker(self, snapPoint): | |
345 """Based on the position and unit size, figure out where we need to snap to. As is, on | |
346 a square grid, there are four possible places to snap. On a hex gid, there are 6 or 12 snap | |
347 points.""" | |
348 self.log.log("Enter MapCanvas->snapMarker(self, snapPoint)", ORPG_DEBUG) | |
349 | |
350 # If snap to grid is disabled, simply return snapPoint unmodified | |
351 if self.layers['grid'].snap: | |
352 # This means we need to determine where to snap our line. We will support | |
353 # snapping to four different snapPoints per square for now. | |
354 # TODO!!! | |
355 if self.layers['grid'].mode == GRID_HEXAGON: | |
356 size = self.layers['grid'].unit_size_y | |
357 else: | |
358 size = int(self.layers['grid'].unit_size) | |
359 # Find the uppper left hand corner of the grid we are to snap to | |
360 offsetX = (snapPoint.x / size) * size | |
361 offsetY = (snapPoint.y / size) * size | |
362 # Calculate the delta value between where we clicked and the square it is near | |
363 deltaX = snapPoint.x - offsetX | |
364 deltaY = snapPoint.y - offsetY | |
365 # Now, figure our what quadrant (x, y) we need to snap to | |
366 snapSize = size / 2 | |
367 # Figure out the X snap placement | |
368 if deltaX <= snapSize: | |
369 quadXPos = offsetX | |
370 else: | |
371 quadXPos = offsetX + size | |
372 # Now, figure out the Y snap placement | |
373 if deltaY <= snapSize: | |
374 quadYPos = offsetY | |
375 else: | |
376 quadYPos = offsetY + size | |
377 # Create our snap snapPoint and return it | |
378 snapPoint = wx.Point( quadXPos, quadYPos ) | |
379 self.log.log("Exit MapCanvas->snapMarker(self, snapPoint)", ORPG_DEBUG) | |
380 return snapPoint | |
381 | |
382 # Bunch of math stuff for marking and measuring | |
383 def calcSlope(self, start, stop): | |
384 """Calculates the slop of a line and returns it.""" | |
385 self.log.log("Enter MapCanvas->calcSlope(self, start, stop)", ORPG_DEBUG) | |
386 if start.x == stop.x: | |
387 s = 0.0001 | |
388 else: | |
389 s = float((stop.y - start.y)) / float((stop.x - start.x)) | |
390 self.log.log("Exit MapCanvas->calcSlope(self, start, stop)", ORPG_DEBUG) | |
391 return s | |
392 | |
393 def calcSlopeToAngle(self, slope): | |
394 """Based on the input slope, the angle (in degrees) will be returned.""" | |
395 self.log.log("Enter MapCanvas->calcSlopeToAngle(self, slope)", ORPG_DEBUG) | |
396 # See if the slope is neg or positive | |
397 if slope == abs(slope): | |
398 # Slope is positive, so make sure it's not zero | |
399 if slope == 0: | |
400 a = 0 | |
401 else: | |
402 # We are positive and NOT zero | |
403 a = 360 - atan(slope) * (180.0/pi) | |
404 else: | |
405 # Slope is negative so work on the abs of it | |
406 a = atan(abs(slope)) * (180.0/pi) | |
407 self.log.log("Exit MapCanvas->calcSlopeToAngle(self, slope)", ORPG_DEBUG) | |
408 return a | |
409 | |
410 def calcLineAngle(self, start, stop): | |
411 """Based on two points that are on a line, return the angle of that line.""" | |
412 self.log.log("Enter MapCanvas->calcLineAngle(self, start, stop)", ORPG_DEBUG) | |
413 a = self.calcSlopeToAngle( self.calcSlope( start, stop ) ) | |
414 self.log.log("Exit MapCanvas->calcLineAngle(self, start, stop)", ORPG_DEBUG) | |
415 return a | |
416 | |
417 def calcPixelDistance(self, start, stop): | |
418 """Calculate the distance between two pixels and returns it. The calculated | |
419 distance is the Euclidean Distance, which is: | |
420 d = sqrt( (x2 - x1)**2 + (y2 - y1)**2 )""" | |
421 self.log.log("Enter MapCanvas->calcPixelDistance(self, start, stop)", ORPG_DEBUG) | |
422 d = sqrt( abs((stop.x - start.x)**2 - (stop.y - start.y)**2) ) | |
423 self.log.log("Exit MapCanvas->calcPixelDistance(self, start, stop)", ORPG_DEBUG) | |
424 return d | |
425 | |
426 def calcUnitDistance(self, start, stop, lineAngle): | |
427 self.log.log("Enter MapCanvas->calcUnitDistance(self, start, stop, lineAngle)", ORPG_DEBUG) | |
428 distance = self.calcPixelDistance( start, stop ) | |
429 ln = "%0.2f" % lineAngle | |
430 if self.layers['grid'].mode == GRID_HEXAGON: | |
431 if ln == "0.00" or ln == "359.99": | |
432 ud = distance / self.layers['grid'].unit_size_y | |
433 else: | |
434 ud = (sqrt(abs((stop.x - start.x)**2 + (stop.y - start.y)**2))) / self.layers['grid'].unit_size_y | |
435 else: | |
436 if ln == "0.00" or ln == "359.99": | |
437 ud = distance / self.layers['grid'].unit_size | |
438 else: | |
439 ud = (sqrt(abs((stop.x - start.x)**2 + (stop.y - start.y)**2))) / self.layers['grid'].unit_size | |
440 #ud = sqrt( abs((stop.x - start.x)**2 - (stop.y - start.y)**2) ) | |
441 self.log.log("Exit MapCanvas->calcUnitDistance(self, start, stop, lineAngle)", ORPG_DEBUG) | |
442 return ud | |
443 | |
444 def on_tape_motion(self, evt): | |
445 """Track mouse motion so we can update the marker visual every time it's moved""" | |
446 self.log.log("Enter MapCanvas->on_tape_motion(self, evt)", ORPG_DEBUG) | |
447 # Make sure we have a mode to do anything, otherwise, we ignore this | |
448 if self.markerMode: | |
449 # Grap the current DC for all of the marker modes | |
450 dc = wx.ClientDC( self ) | |
451 self.PrepareDC( dc ) | |
452 dc.SetUserScale(self.layers['grid'].mapscale,self.layers['grid'].mapscale) | |
453 # Grab the current map position | |
454 pos = self.snapMarker( evt.GetLogicalPosition( dc ) ) | |
455 # Enable brush optimizations | |
456 #dc.SetOptimization( True ) | |
457 # Set up the pen used for drawing our marker | |
458 dc.SetPen( wx.Pen(wx.RED, 1, wx.LONG_DASH) ) | |
459 # Now, based on the marker mode, draw the right thing | |
460 if self.markerMode == MARKER_MODE_MEASURE: | |
461 if self.markerStop.x != -1 and self.markerStop.y != -1: | |
462 # Set the DC function that we need | |
463 dc.SetLogicalFunction(wx.INVERT) | |
464 # Erase old and Draw new marker line | |
465 dc.BeginDrawing() | |
466 dc.DrawLine( self.markerStart.x, self.markerStart.y, self.markerStop.x, self.markerStop.y ) | |
467 dc.DrawLine( self.markerStart.x, self.markerStart.y, pos.x, pos.y ) | |
468 dc.EndDrawing() | |
469 # Restore the default DC function | |
470 dc.SetLogicalFunction(wx.COPY) | |
471 # As long as we are in marker mode, we ned to update the stop point | |
472 self.markerStop = pos | |
473 dc.SetPen(wx.NullPen) | |
474 # Disable brush optimizations | |
475 #dc.SetOptimization( False ) | |
476 del dc | |
477 self.log.log("Exit MapCanvas->on_tape_motion(self, evt)", ORPG_DEBUG) | |
478 | |
479 def on_tape_down(self, evt): | |
480 """Greg's experimental tape measure code. Hopefully, when this is done, it will all be | |
481 modal based on a toolbar.""" | |
482 self.log.log("Enter MapCanvas->on_tape_down(self, evt)", ORPG_DEBUG) | |
483 dc = wx.ClientDC( self ) | |
484 self.PrepareDC( dc ) | |
485 dc.SetUserScale(self.layers['grid'].mapscale,self.layers['grid'].mapscale) | |
486 pos = evt.GetLogicalPosition( dc ) | |
487 # If grid snap is enabled, then snap the tool to a proper position | |
488 pos = self.snapMarker( evt.GetLogicalPosition( dc ) ) | |
489 # Maker mode should really be set by a toolbar | |
490 self.markerMode = MARKER_MODE_MEASURE | |
491 # Erase the old line if her have one | |
492 if self.markerStart.x != -1 and self.markerStart.y != -1: | |
493 # Enable brush optimizations | |
494 #dc.SetOptimization( True ) | |
495 # Set up the pen used for drawing our marker | |
496 dc.SetPen( wx.Pen(wx.RED, 1, wx.LONG_DASH) ) | |
497 # Set the DC function that we need | |
498 dc.SetLogicalFunction(wx.INVERT) | |
499 # Draw the marker line | |
500 dc.BeginDrawing() | |
501 dc.DrawLine( self.markerStart.x, self.markerStart.y, self.markerStop.x, self.markerStop.y ) | |
502 dc.EndDrawing() | |
503 # Restore the default DC function and pen | |
504 dc.SetLogicalFunction(wx.COPY) | |
505 dc.SetPen(wx.NullPen) | |
506 # Disable brush optimizations | |
507 #dc.SetOptimization( False ) | |
508 # Save our current start and reset the stop value | |
509 self.markerStart = pos | |
510 self.markerStop = pos | |
511 del dc | |
512 self.log.log("Exit MapCanvas->on_tape_down(self, evt)", ORPG_DEBUG) | |
513 | |
514 def on_tape_up(self, evt): | |
515 """When we release the middle button, disable any marking updates that we have been doing.""" | |
516 self.log.log("Enter MapCanvas->on_tape_up(self, evt)", ORPG_DEBUG) | |
517 # If we are in measure mode, draw the actual UNIT distance | |
518 if self.markerMode == MARKER_MODE_MEASURE: | |
519 dc = wx.ClientDC( self ) | |
520 self.PrepareDC( dc ) | |
521 dc.SetUserScale(self.layers['grid'].mapscale,self.layers['grid'].mapscale) | |
522 # Draw the measured distance on the DC. Since we want | |
523 # the text to match the line angle, calculate the angle | |
524 # of the line. | |
525 lineAngle = self.calcLineAngle( self.markerStart, self.markerStop ) | |
526 distance = self.calcUnitDistance( self.markerStart, self.markerStop, lineAngle ) | |
527 midPoint = (self.markerStart + self.markerStop) | |
528 midPoint.x /= 2 | |
529 midPoint.y /= 2 | |
530 # Adjust out font to be bigger & scaled | |
531 font = dc.GetFont() | |
532 # Set the DC function that we need | |
533 dc.SetLogicalFunction(wx.INVERT) | |
534 # Set the pen we want to use | |
535 dc.SetPen(wx.BLACK_PEN) | |
536 # Now, draw the text at the proper angle on the canvas | |
537 self.markerMidpoint = midPoint | |
538 self.markerAngle = lineAngle | |
539 dText = "%0.2f Units" % (distance) | |
540 dc.BeginDrawing() | |
541 dc.DrawRotatedText( dText, midPoint.x, midPoint.y, lineAngle ) | |
542 dc.EndDrawing() | |
543 # Restore the default font and DC | |
544 dc.SetFont(wx.NullFont) | |
545 dc.SetLogicalFunction(wx.COPY) | |
546 del font | |
547 del dc | |
548 self.markerMode = MARKER_MODE_NONE | |
549 self.log.log("Exit MapCanvas->on_tape_up(self, evt)", ORPG_DEBUG) | |
550 | |
551 # MODE 1 = MOVE, MODE 2 = whiteboard, MODE 3 = Tape measure | |
552 def on_left_down(self, evt): | |
553 self.log.log("Enter MapCanvas->on_left_down(self, evt)", ORPG_DEBUG) | |
554 if evt.ShiftDown(): | |
555 self.on_tape_down (evt) | |
556 else: | |
557 self.frame.on_left_down(evt) | |
558 self.log.log("Exit MapCanvas->on_left_down(self, evt)", ORPG_DEBUG) | |
559 | |
560 def on_right_down(self, evt): | |
561 self.log.log("Enter MapCanvas->on_right_down(self, evt)", ORPG_DEBUG) | |
562 if evt.ShiftDown(): | |
563 pass | |
564 else: | |
565 self.frame.on_right_down(evt) | |
566 self.log.log("Exit MapCanvas->on_right_down(self, evt)", ORPG_DEBUG) | |
567 | |
568 def on_left_dclick(self, evt): | |
569 self.log.log("Enter MapCanvas->on_left_dclick(self, evt)", ORPG_DEBUG) | |
570 if evt.ShiftDown(): | |
571 pass | |
572 else: | |
573 self.frame.on_left_dclick(evt) | |
574 self.log.log("Exit MapCanvas->on_left_dclick(self, evt)", ORPG_DEBUG) | |
575 | |
576 def on_left_up(self, evt): | |
577 self.log.log("Enter MapCanvas->on_left_up(self, evt)", ORPG_DEBUG) | |
578 if evt.ShiftDown(): | |
579 self.on_tape_up(evt) | |
580 elif open_rpg.get_component("tree").dragging: | |
581 tree = open_rpg.get_component("tree") | |
582 if tree.drag_obj.map_aware(): | |
583 tree.drag_obj.on_send_to_map(evt) | |
584 tree.dragging = False | |
585 tree.drag_obj = None | |
586 else: | |
587 self.frame.on_left_up(evt) | |
588 self.log.log("Exit MapCanvas->on_left_up(self, evt)", ORPG_DEBUG) | |
589 | |
590 def on_motion(self, evt): | |
591 self.log.log("Enter MapCanvas->on_motion(self, evt)", ORPG_DEBUG) | |
592 if evt.ShiftDown(): | |
593 self.on_tape_motion(evt) | |
594 elif evt.LeftIsDown() and open_rpg.get_component("tree").dragging: | |
595 pass | |
596 else: | |
597 self.frame.on_motion(evt) | |
598 self.log.log("Exit MapCanvas->on_motion(self, evt)", ORPG_DEBUG) | |
599 | |
600 def on_zoom_out(self, evt): | |
601 self.log.log("Enter MapCanvas->on_zoom_out(self, evt)", ORPG_DEBUG) | |
602 if self.layers['grid'].mapscale > 0.2: | |
603 # attempt to keep same logical point at center of screen | |
604 scale = self.layers['grid'].mapscale | |
605 scrollsize = self.GetScrollPixelsPerUnit() | |
606 clientsize = self.GetClientSize() | |
607 topleft1 = self.GetViewStart() | |
608 topleft = [topleft1[0]*scrollsize[0], topleft1[1]*scrollsize[1]] | |
609 scroll_x = (((topleft[0]+clientsize[0]/2)*(scale-.1)/scale)-clientsize[0]/2)/scrollsize[0] | |
610 scroll_y = (((topleft[1]+clientsize[1]/2)*(scale-.1)/scale)-clientsize[1]/2)/scrollsize[1] | |
611 self.Scroll(scroll_x, scroll_y) | |
612 self.layers['grid'].mapscale -= .1 | |
613 scalestring = "x" + `self.layers['grid'].mapscale`[:3] | |
614 self.frame.get_current_layer_handler().zoom_out_button.SetToolTip(wx.ToolTip("Zoom out from " + scalestring) ) | |
615 self.frame.get_current_layer_handler().zoom_in_button.SetToolTip(wx.ToolTip("Zoom in from " + scalestring) ) | |
616 self.set_size(self.size) | |
617 dc = wx.ClientDC(self) | |
618 dc.BeginDrawing() | |
619 scalestring = "Scale x" + `self.layers['grid'].mapscale`[:3] | |
620 (textWidth,textHeight) = dc.GetTextExtent(scalestring) | |
621 dc.SetPen(wx.LIGHT_GREY_PEN) | |
622 dc.SetBrush(wx.LIGHT_GREY_BRUSH) | |
623 dc.DrawRectangle(dc.DeviceToLogicalX(0),dc.DeviceToLogicalY(0),textWidth,textHeight) | |
624 dc.SetPen(wx.RED_PEN) | |
625 dc.DrawText(scalestring,dc.DeviceToLogicalX(0),dc.DeviceToLogicalY(0)) | |
626 dc.SetPen(wx.NullPen) | |
627 dc.SetBrush(wx.NullBrush) | |
628 dc.EndDrawing() | |
629 del dc | |
630 self.zoom_display_timer.Start(500,1) | |
631 self.log.log("Exit MapCanvas->on_zoom_out(self, evt)", ORPG_DEBUG) | |
632 | |
633 def on_zoom_in(self, evt): | |
634 self.log.log("Enter MapCanvas->on_zoom_in(self, evt)", ORPG_DEBUG) | |
635 # attempt to keep same logical point at center of screen | |
636 scale = self.layers['grid'].mapscale | |
637 scrollsize = self.GetScrollPixelsPerUnit() | |
638 clientsize = self.GetClientSize() | |
639 topleft1 = self.GetViewStart() | |
640 topleft = [topleft1[0]*scrollsize[0], topleft1[1]*scrollsize[1]] | |
641 scroll_x = (((topleft[0]+clientsize[0]/2)*(scale+.1)/scale)-clientsize[0]/2)/scrollsize[0] | |
642 scroll_y = (((topleft[1]+clientsize[1]/2)*(scale+.1)/scale)-clientsize[1]/2)/scrollsize[1] | |
643 self.Scroll(scroll_x, scroll_y) | |
644 self.layers['grid'].mapscale += .1 | |
645 scalestring = "x" + `self.layers['grid'].mapscale`[:3] | |
646 self.frame.get_current_layer_handler().zoom_out_button.SetToolTip(wx.ToolTip("Zoom out from " + scalestring) ) | |
647 self.frame.get_current_layer_handler().zoom_in_button.SetToolTip(wx.ToolTip("Zoom in from " + scalestring) ) | |
648 self.set_size(self.size) | |
649 dc = wx.ClientDC(self) | |
650 dc.BeginDrawing() | |
651 scalestring = "Scale x" + `self.layers['grid'].mapscale`[:3] | |
652 (textWidth,textHeight) = dc.GetTextExtent(scalestring) | |
653 dc.SetPen(wx.LIGHT_GREY_PEN) | |
654 dc.SetBrush(wx.LIGHT_GREY_BRUSH) | |
655 dc.DrawRectangle(dc.DeviceToLogicalX(0), dc.DeviceToLogicalY(0), textWidth,textHeight) | |
656 dc.SetPen(wx.RED_PEN) | |
657 dc.DrawText(scalestring, dc.DeviceToLogicalX(0), dc.DeviceToLogicalY(0)) | |
658 dc.SetPen(wx.NullPen) | |
659 dc.SetBrush(wx.NullBrush) | |
660 dc.EndDrawing() | |
661 del dc | |
662 self.zoom_display_timer.Start(500, 1) | |
663 self.log.log("Exit MapCanvas->on_zoom_in(self, evt)", ORPG_DEBUG) | |
664 | |
665 def on_prop(self, evt): | |
666 self.log.log("Enter MapCanvas->on_prop(self, evt)", ORPG_DEBUG) | |
667 self.session = open_rpg.get_component("session") | |
668 self.chat = open_rpg.get_component("chat") | |
669 if (self.session.my_role() != self.session.ROLE_GM): | |
670 self.chat.InfoPost("You must be a GM to use this feature") | |
671 self.log.log("Exit MapCanvas->on_prop(self, evt)", ORPG_DEBUG) | |
672 return | |
673 dlg = general_map_prop_dialog(self.frame.GetParent(),self.size,self.layers['bg'],self.layers['grid']) | |
674 if dlg.ShowModal() == wx.ID_OK: | |
675 self.set_size(dlg.size) | |
676 self.send_map_data() | |
677 self.Refresh(False) | |
678 dlg.Destroy() | |
679 os.chdir(self.root_dir) | |
680 self.log.log("Exit MapCanvas->on_prop(self, evt)", ORPG_DEBUG) | |
681 | |
682 def add_miniature(self, min_url, min_label='', min_unique=-1): | |
683 self.log.log("Enter MapCanvas->add_miniature(self, min_url, min_label, min_unique)", ORPG_DEBUG) | |
684 if min_unique == -1: | |
685 min_unique = not self.use_serial | |
686 if min_url == "" or min_url == "http://": | |
687 return | |
688 if min_url[:7] != "http://" : | |
689 min_url = "http://" + min_url | |
690 # make label | |
691 wx.BeginBusyCursor() | |
692 if self.auto_label: | |
693 if min_label == '': | |
694 min_label = self.get_label_from_url( min_url ) | |
695 if not min_unique and self.use_serial: | |
696 min_label = '%s %d' % ( min_label, self.layers['miniatures'].next_serial() ) | |
697 else: | |
698 min_label = "" | |
699 if self.frame.min_url.FindString(min_url) == -1: | |
700 self.frame.min_url.Append(min_url) | |
701 try: | |
702 id = 'mini-' + self.frame.session.get_next_id() | |
703 self.layers['miniatures'].add_miniature(id, min_url, label=min_label) | |
704 except Exception, e: | |
705 self.log.log(traceback.format_exc(), ORPG_GENERAL) | |
706 self.log.log("Unable to load/resolve URL: " + min_url + " on resource ' + min_label + ' !!!", ORPG_GENERAL) | |
707 self.layers['miniatures'].rollback_serial() | |
708 wx.EndBusyCursor() | |
709 self.send_map_data() | |
710 self.Refresh(False) | |
711 self.log.log("Exit MapCanvas->add_miniature(self, min_url, min_label, min_unique)", ORPG_DEBUG) | |
712 | |
713 def get_label_from_url(self, url=''): | |
714 self.log.log("Enter MapCanvas->get_label_from_url(self, url)", ORPG_DEBUG) | |
715 if url == '': | |
716 self.log.log("Exit MapCanvas->get_label_from_url(self, url)", ORPG_DEBUG) | |
717 return '' | |
718 start = url.rfind("/")+1 | |
719 label = url[start:len(url)-4] | |
720 self.log.log("Exit MapCanvas->get_label_from_url(self, url)", ORPG_DEBUG) | |
721 return label | |
722 | |
723 def toxml(self, action="update"): | |
724 self.log.log("Enter MapCanvas->toxml(self, " + action + ")", ORPG_DEBUG) | |
725 if action == "new": | |
726 self.size_changed = 1 | |
727 xml_str = "<map version='" + self.map_version + "'" | |
728 changed = self.size_changed | |
729 if self.size_changed: | |
730 xml_str += " sizex='" + str(self.size[0]) + "'" | |
731 xml_str += " sizey='" + str(self.size[1]) + "'" | |
732 s = "" | |
733 keys = self.layers.keys() | |
734 for k in keys: | |
735 if (k != "fog" or action != "update"): | |
736 s += self.layers[k].layerToXML(action) | |
737 self.size_changed = 0 | |
738 if s: | |
739 self.log.log("Exit MapCanvas->toxml(self, " + action + ")", ORPG_DEBUG) | |
740 return xml_str + " action='" + action + "'>" + s + "</map>" | |
741 else: | |
742 if changed: | |
743 self.log.log("Exit MapCanvas->toxml(self, " + action + ")", ORPG_DEBUG) | |
744 return xml_str + " action='" + action + "'/>" | |
745 else: | |
746 self.log.log("Exit MapCanvas->toxml(self, " + action + ")", ORPG_DEBUG) | |
747 return "" | |
748 | |
749 def takexml(self, xml): | |
750 # | |
751 # Added Process Dialog to display during long map parsings | |
752 # as well as a try block with an exception traceback to try | |
753 # and isolate some of the map related problems users have been | |
754 # experiencing --Snowdog 5/15/03 | |
755 # | |
756 # Apparently Process Dialog causes problems with linux.. commenting it out. sheez. | |
757 # --Snowdog 5/27/03 | |
758 self.log.log("Enter MapCanvas->takexml(self, xml)", ORPG_DEBUG) | |
759 try: | |
760 #parse the map DOM | |
761 xml_dom = parseXml(xml) | |
762 if xml_dom == None: | |
763 self.log.log("xml_dom == None\n" + xml, ORPG_INFO) | |
764 self.log.log("Exit MapCanvas->takexml(self, xml)", ORPG_DEBUG) | |
765 return | |
766 node_list = xml_dom.getElementsByTagName("map") | |
767 if len(node_list) < 1: | |
768 self.log.log("Invalid XML format for mapper", ORPG_INFO) | |
769 else: | |
770 # set map version to incoming data so layers can convert | |
771 self.map_version = node_list[0].getAttribute("version") | |
772 action = node_list[0].getAttribute("action") | |
773 if action == "new": | |
774 self.layers = {} | |
775 try: | |
776 self.layers['bg'] = layer_back_ground(self) | |
777 except: | |
778 pass | |
779 try: | |
780 self.layers['grid'] = grid_layer(self) | |
781 except: | |
782 pass | |
783 try: | |
784 self.layers['miniatures'] = miniature_layer(self) | |
785 except: | |
786 pass | |
787 try: | |
788 self.layers['whiteboard'] = whiteboard_layer(self) | |
789 except: | |
790 pass | |
791 try: | |
792 self.layers['fog'] = fog_layer(self) | |
793 except: | |
794 pass | |
795 sizex = node_list[0].getAttribute("sizex") | |
796 if sizex != "": | |
797 sizex = int(float(sizex)) | |
798 sizey = self.size[1] | |
799 self.set_size((sizex,sizey)) | |
800 self.size_changed = 0 | |
801 sizey = node_list[0].getAttribute("sizey") | |
802 if sizey != "": | |
803 sizey = int(float(sizey)) | |
804 sizex = self.size[0] | |
805 self.set_size((sizex,sizey)) | |
806 self.size_changed = 0 | |
807 children = node_list[0]._get_childNodes() | |
808 #fog layer must be computed first, so that no data is inadvertently revealed | |
809 for c in children: | |
810 name = c._get_nodeName() | |
811 if name == "fog": | |
812 self.layers[name].layerTakeDOM(c) | |
813 for c in children: | |
814 name = c._get_nodeName() | |
815 if name != "fog": | |
816 self.layers[name].layerTakeDOM(c) | |
817 # all map data should be converted, set map version to current version | |
818 self.map_version = MAP_VERSION | |
819 self.Refresh(False) | |
820 xml_dom.unlink() # eliminate circular refs | |
821 except: | |
822 self.log.log(traceback.format_exc(), ORPG_GENERAL) | |
823 self.log.log("EXCEPTION: Critical Error Loading Map!!!", ORPG_GENERAL) | |
824 self.log.log("Exit MapCanvas->takexml(self, xml)", ORPG_DEBUG) | |
825 | |
826 def re_ids_in_xml(self, xml): | |
827 self.log.log("Enter MapCanvas->re_ids_in_xml(self, xml)", ORPG_DEBUG) | |
828 new_xml = "" | |
829 tmp_map = map_msg() | |
830 xml_dom = parseXml(str(xml)) | |
831 node_list = xml_dom.getElementsByTagName("map") | |
832 if len(node_list) < 1: | |
833 self.log.log("Invalid XML format for mapper", ORPG_INFO) | |
834 else: | |
835 tmp_map.init_from_dom(node_list[0]) | |
836 if tmp_map.children.has_key("miniatures"): | |
837 miniatures_layer = tmp_map.children["miniatures"] | |
838 if miniatures_layer: | |
839 minis = miniatures_layer.get_children().keys() | |
840 if minis: | |
841 for mini in minis: | |
842 m = miniatures_layer.children[mini] | |
843 id = 'mini-' + self.frame.session.get_next_id() | |
844 m.init_prop("id", id) | |
845 # This allows for backward compatibility with older maps which do not | |
846 # have a whiteboard node. As such, if it's not there, we'll just happily | |
847 # move on and process as always. | |
848 if tmp_map.children.has_key("whiteboard"): | |
849 whiteboard_layer = tmp_map.children["whiteboard"] | |
850 if whiteboard_layer: | |
851 lines = whiteboard_layer.get_children().keys() | |
852 if lines: | |
853 for line in lines: | |
854 l = whiteboard_layer.children[line] | |
855 if l.tagname == 'line': | |
856 id = 'line-' + self.frame.session.get_next_id() | |
857 elif l.tagname == 'text': | |
858 id = 'text-' + self.frame.session.get_next_id() | |
859 elif l.tagname == 'circle': | |
860 id = 'circle-' + self.frame.session.get_next_id() | |
861 l.init_prop("id", id) | |
862 new_xml = tmp_map.get_all_xml() | |
863 if xml_dom: | |
864 xml_dom.unlink() | |
865 self.log.log("Exit MapCanvas->re_ids_in_xml(self, xml)", ORPG_DEBUG) | |
866 return str(new_xml) | |
867 | |
868 class map_wnd(wx.Panel): | |
869 def __init__(self, parent, id): | |
870 self.log = open_rpg.get_component('log') | |
871 self.log.log("Enter map_wnd", ORPG_DEBUG) | |
872 wx.Panel.__init__(self, parent, id) | |
873 self.canvas = MapCanvas(self, -1) | |
874 self.session = open_rpg.get_component('session') | |
875 self.settings = open_rpg.get_component('settings') | |
876 self.chat = open_rpg.get_component('chat') | |
877 self.top_frame = open_rpg.get_component('frame') | |
878 self.root_dir = os.getcwd() | |
879 self.current_layer = 2 | |
880 self.layer_tabs = orpgTabberWnd(self, style=FNB.FNB_NO_X_BUTTON|FNB.FNB_BOTTOM|FNB.FNB_NO_NAV_BUTTONS) | |
881 self.layer_handlers = [] | |
882 self.layer_handlers.append(background_handler(self.layer_tabs,-1,self.canvas)) | |
883 self.layer_tabs.AddPage(self.layer_handlers[0],"Background") | |
884 self.layer_handlers.append(grid_handler(self.layer_tabs,-1,self.canvas)) | |
885 self.layer_tabs.AddPage(self.layer_handlers[1],"Grid") | |
886 self.layer_handlers.append(miniatures_handler(self.layer_tabs,-1,self.canvas)) | |
887 self.layer_tabs.AddPage(self.layer_handlers[2],"Miniatures", True) | |
888 self.layer_handlers.append(whiteboard_handler(self.layer_tabs,-1,self.canvas)) | |
889 self.layer_tabs.AddPage(self.layer_handlers[3],"Whiteboard") | |
890 self.layer_handlers.append(fog_handler(self.layer_tabs,-1,self.canvas)) | |
891 self.layer_tabs.AddPage(self.layer_handlers[4],"Fog") | |
892 self.layer_handlers.append(map_handler(self.layer_tabs,-1,self.canvas)) | |
893 self.layer_tabs.AddPage(self.layer_handlers[5],"General") | |
894 self.layer_tabs.SetSelection(2) | |
895 self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.on_layer_change) | |
896 self.Bind(wx.EVT_SIZE, self.on_size) | |
897 self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) | |
898 self.load_default() | |
899 # size of tabs is diffrent on windows and linux :( | |
900 if wx.Platform == '__WXMSW__': | |
901 self.toolbar_height = 50 | |
902 else: | |
903 self.toolbar_height = 55 | |
904 self.log.log("Exit map_wnd", ORPG_DEBUG) | |
905 | |
906 def OnLeave(self, evt): | |
907 if "__WXGTK__" in wx.PlatformInfo: | |
908 wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) | |
909 | |
910 def load_default(self): | |
911 self.log.log("Enter map_wnd->load_default(self)", ORPG_DEBUG) | |
912 if self.session.is_connected() and (self.session.my_role() != self.session.ROLE_GM) and (self.session.use_roles()): | |
913 self.chat.InfoPost("You must be a GM to use this feature") | |
914 self.log.log("Exit map_wnd->load_default(self)", ORPG_DEBUG) | |
915 return | |
916 f = open(orpg.dirpath.dir_struct["template"] + "default_map.xml") | |
917 self.new_data(f.read()) | |
918 f.close() | |
919 self.canvas.send_map_data("new") | |
920 if not self.session.is_connected() and (self.session.my_role() != self.session.ROLE_GM): | |
921 self.session.update_role("GM") | |
922 self.log.log("Exit map_wnd->load_default(self)", ORPG_DEBUG) | |
923 | |
924 def new_data(self, data): | |
925 self.log.log("Enter map_wnd->new_data(self, data)", ORPG_DEBUG) | |
926 self.canvas.takexml(data) | |
927 self.update_tools() | |
928 self.log.log("Exit map_wnd->new_data(self, data)", ORPG_DEBUG) | |
929 | |
930 def on_save(self,evt): | |
931 self.log.log("Enter map_wnd->new_data(self, data)", ORPG_DEBUG) | |
932 if (self.session.my_role() != self.session.ROLE_GM): | |
933 self.chat.InfoPost("You must be a GM to use this feature") | |
934 self.log.log("Exit map_wnd->new_data(self, data)", ORPG_DEBUG) | |
935 return | |
936 d = wx.FileDialog(self.GetParent(), "Save map data", orpg.dirpath.dir_struct["user"], "", "*.xml", wx.SAVE) | |
937 if d.ShowModal() == wx.ID_OK: | |
938 f = open(d.GetPath(), "w") | |
939 data = '<nodehandler class="min_map" icon="compass" module="core" name="miniature Map">' | |
940 data += self.canvas.toxml("new") | |
941 data += "</nodehandler>" | |
942 data = data.replace(">",">\n") | |
943 f.write(data) | |
944 f.close() | |
945 d.Destroy() | |
946 os.chdir(self.root_dir) | |
947 self.log.log("Exit map_wnd->new_data(self, data)", ORPG_DEBUG) | |
948 | |
949 def on_open(self, evt): | |
950 self.log.log("Enter map_wnd->on_open(self, evt)", ORPG_DEBUG) | |
951 if self.session.is_connected() and (self.session.my_role() != self.session.ROLE_GM) and (self.session.use_roles()): | |
952 self.chat.InfoPost("You must be a GM to use this feature") | |
953 self.log.log("Exit map_wnd->on_open(self, evt)", ORPG_DEBUG) | |
954 return | |
955 d = wx.FileDialog(self.GetParent(), "Select a file", orpg.dirpath.dir_struct["user"], "", "*.xml", wx.OPEN) | |
956 if d.ShowModal() == wx.ID_OK: | |
957 f = open(d.GetPath()) | |
958 map_string = f.read() | |
959 new_xml = self.canvas.re_ids_in_xml(map_string) | |
960 if new_xml: | |
961 self.canvas.takexml(new_xml) | |
962 self.canvas.send_map_data("new") | |
963 self.update_tools() | |
964 if not self.session.is_connected() and (self.session.my_role() != self.session.ROLE_GM): | |
965 self.session.update_role("GM") | |
966 d.Destroy() | |
967 os.chdir(self.root_dir) | |
968 self.log.log("Exit map_wnd->on_open(self, evt)", ORPG_DEBUG) | |
969 | |
970 def get_current_layer_handler(self): | |
971 self.log.log("Enter map_wnd->get_current_layer_handler(self)", ORPG_DEBUG) | |
972 self.log.log("Exit map_wnd->get_current_layer_handler(self)", ORPG_DEBUG) | |
973 return self.layer_handlers[self.current_layer] | |
974 | |
975 def get_tab_index(self, layer): | |
976 """Return the index of a chatpanel in the wxNotebook.""" | |
977 self.log.log("Enter map_wnd->get_tab_index(self, layer)", ORPG_DEBUG) | |
978 for i in xrange(self.layer_tabs.GetPageCount()): | |
979 if (self.layer_tabs.GetPageText(i) == layer): | |
980 self.log.log("Exit map_wnd->get_tab_index(self, layer) return " + str(i), ORPG_DEBUG) | |
981 return i | |
982 self.log.log("Exit map_wnd->get_tab_index(self, layer) return 0", ORPG_DEBUG) | |
983 return 0 | |
984 | |
985 def on_layer_change(self, evt): | |
986 self.log.log("Enter map_wnd->on_layer_change(self, evt)", ORPG_DEBUG) | |
987 layer = self.layer_tabs.GetPage(evt.GetSelection()) | |
988 for i in xrange(0, len(self.layer_handlers)): | |
989 if layer == self.layer_handlers[i]: | |
990 self.current_layer = i | |
991 if self.current_layer == 0: | |
992 bg = self.layer_handlers[0] | |
993 if (self.session.my_role() != self.session.ROLE_GM): | |
994 bg.url_path.Show(False) | |
995 else: | |
996 bg.url_path.Show(True) | |
997 self.canvas.Refresh(False) | |
998 evt.Skip() | |
999 self.log.log("Exit map_wnd->on_layer_change(self, evt)", ORPG_DEBUG) | |
1000 | |
1001 def on_left_down(self, evt): | |
1002 self.log.log("Enter map_wnd->on_left_down(self, evt)", ORPG_DEBUG) | |
1003 self.log.log("Exit map_wnd->on_left_down(self, evt)", ORPG_DEBUG) | |
1004 self.layer_handlers[self.current_layer].on_left_down(evt) | |
1005 | |
1006 #double click handler added by Snowdog 5/03 | |
1007 def on_left_dclick(self, evt): | |
1008 self.log.log("Enter map_wnd->on_left_dclick(self, evt)", ORPG_DEBUG) | |
1009 self.log.log("Exit map_wnd->on_left_dclick(self, evt)", ORPG_DEBUG) | |
1010 self.layer_handlers[self.current_layer].on_left_dclick(evt) | |
1011 | |
1012 def on_right_down(self, evt): | |
1013 self.log.log("Enter map_wnd->on_right_down(self, evt)", ORPG_DEBUG) | |
1014 self.log.log("Exit map_wnd->on_right_down(self, evt)", ORPG_DEBUG) | |
1015 self.layer_handlers[self.current_layer].on_right_down(evt) | |
1016 | |
1017 def on_left_up(self, evt): | |
1018 self.log.log("Enter map_wnd->on_left_up(self, evt)", ORPG_DEBUG) | |
1019 self.log.log("Exit map_wnd->on_left_up(self, evt)", ORPG_DEBUG) | |
1020 self.layer_handlers[self.current_layer].on_left_up(evt) | |
1021 | |
1022 def on_motion(self, evt): | |
1023 self.log.log("Enter map_wnd->on_motion(self, evt)", ORPG_DEBUG) | |
1024 self.log.log("Exit map_wnd->on_motion(self, evt)", ORPG_DEBUG) | |
1025 self.layer_handlers[self.current_layer].on_motion(evt) | |
1026 | |
1027 def MapBar(self, id, data): | |
1028 self.log.log("Enter map_wnd->MapBar(self, id, data)", ORPG_DEBUG) | |
1029 self.canvas.MAP_MODE = data | |
1030 if id == 1: | |
1031 self.canvas.MAP_MODE = data | |
1032 self.log.log("Exit map_wnd->MapBar(self, id, data)", ORPG_DEBUG) | |
1033 | |
1034 def set_map_focus(self, evt): | |
1035 self.log.log("Enter map_wnd->set_map_focus(self, evt)", ORPG_DEBUG) | |
1036 self.canvas.SetFocus() | |
1037 self.log.log("Exit map_wnd->set_map_focus(self, evt)", ORPG_DEBUG) | |
1038 | |
1039 def pre_exit_cleanup(self): | |
1040 self.log.log("Enter map_wnd->pre_exit_cleanup(self)", ORPG_DEBUG) | |
1041 # do some pre exit clean up for bitmaps or other objects | |
1042 try: | |
1043 ImageHandler.flushCache() | |
1044 self.canvas.pre_destory_cleanup() | |
1045 except Exception, e: | |
1046 self.log.log(traceback.format_exc(), ORPG_CRITICAL) | |
1047 self.log.log("EXCEPTION: " + str(e), ORPG_CRITICAL) | |
1048 self.log.log("Exit map_wnd->pre_exit_cleanup(self)", ORPG_DEBUG) | |
1049 | |
1050 def update_tools(self): | |
1051 self.log.log("Enter map_wnd->update_tools(self)", ORPG_DEBUG) | |
1052 for h in self.layer_handlers: | |
1053 h.update_info() | |
1054 self.log.log("Exit map_wnd->update_tools(self)", ORPG_DEBUG) | |
1055 | |
1056 def on_hk_map_layer(self, evt): | |
1057 self.log.log("Enter map_wnd->on_hk_map_layer(self, evt)", ORPG_DEBUG) | |
1058 id = self.top_frame.mainmenu.GetHelpString(evt.GetId()) | |
1059 #print evt.GetMenu().GetTitle() | |
1060 if id == "Background Layer": | |
1061 self.current_layer = self.get_tab_index("Background") | |
1062 if id == "Grid Layer": | |
1063 self.current_layer = self.get_tab_index("Grid") | |
1064 if id == "Miniature Layer": | |
1065 self.current_layer = self.get_tab_index("Miniatures") | |
1066 elif id == "Whiteboard Layer": | |
1067 self.current_layer = self.get_tab_index("Whiteboard") | |
1068 elif id == "Fog Layer": | |
1069 self.current_layer = self.get_tab_index("Fog") | |
1070 elif id == "General Properties": | |
1071 self.current_layer = self.get_tab_index("General") | |
1072 self.layer_tabs.SetSelection(self.current_layer) | |
1073 self.log.log("Exit map_wnd->on_hk_map_layer(self, evt)", ORPG_DEBUG) | |
1074 | |
1075 def on_flush_cache(self, evt): | |
1076 self.log.log("Enter map_wnd->on_flush_cache(self, evt)", ORPG_DEBUG) | |
1077 ImageHandler.flushCache() | |
1078 self.log.log("Exit map_wnd->on_flush_cache(self, evt)", ORPG_DEBUG) | |
1079 | |
1080 def build_menu(self): | |
1081 self.log.log("Enter map_wnd->build_menu(self)", ORPG_DEBUG) | |
1082 # temp menu | |
1083 menu = wx.Menu() | |
1084 item = wx.MenuItem(menu, wx.ID_ANY, "&Load Map", "Load Map") | |
1085 self.top_frame.Bind(wx.EVT_MENU, self.on_open, item) | |
1086 menu.AppendItem(item) | |
1087 item = wx.MenuItem(menu, wx.ID_ANY, "&Save Map", "Save Map") | |
1088 self.top_frame.Bind(wx.EVT_MENU, self.on_save, item) | |
1089 menu.AppendItem(item) | |
1090 menu.AppendSeparator() | |
1091 item = wx.MenuItem(menu, wx.ID_ANY, "Background Layer\tCtrl+1", "Background Layer") | |
1092 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1093 menu.AppendItem(item) | |
1094 item = wx.MenuItem(menu, wx.ID_ANY, "Grid Layer\tCtrl+2", "Grid Layer") | |
1095 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1096 menu.AppendItem(item) | |
1097 item = wx.MenuItem(menu, wx.ID_ANY, "Miniature Layer\tCtrl+3", "Miniature Layer") | |
1098 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1099 menu.AppendItem(item) | |
1100 item = wx.MenuItem(menu, wx.ID_ANY, "Whiteboard Layer\tCtrl+4", "Whiteboard Layer") | |
1101 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1102 menu.AppendItem(item) | |
1103 item = wx.MenuItem(menu, wx.ID_ANY, "Fog Layer\tCtrl+5", "Fog Layer") | |
1104 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1105 menu.AppendItem(item) | |
1106 item = wx.MenuItem(menu, wx.ID_ANY, "General Properties\tCtrl+6", "General Properties") | |
1107 self.top_frame.Bind(wx.EVT_MENU, self.on_hk_map_layer, item) | |
1108 menu.AppendItem(item) | |
1109 menu.AppendSeparator() | |
1110 item = wx.MenuItem(menu, wx.ID_ANY, "&Flush Image Cache\tCtrl+F", "Flush Image Cache") | |
1111 self.top_frame.Bind(wx.EVT_MENU, self.on_flush_cache, item) | |
1112 menu.AppendItem(item) | |
1113 menu.AppendSeparator() | |
1114 item = wx.MenuItem(menu, wx.ID_ANY, "&Properties", "Properties") | |
1115 self.top_frame.Bind(wx.EVT_MENU, self.canvas.on_prop, item) | |
1116 menu.AppendItem(item) | |
1117 self.top_frame.mainmenu.Insert(2, menu, '&Map') | |
1118 self.log.log("Exit map_wnd->build_menu(self)", ORPG_DEBUG) | |
1119 | |
1120 def get_hot_keys(self): | |
1121 self.log.log("Enter map_wnd->get_hot_keys(self)", ORPG_DEBUG) | |
1122 self.build_menu() | |
1123 self.log.log("Exit map_wnd->get_hot_keys(self)", ORPG_DEBUG) | |
1124 return [] | |
1125 | |
1126 def on_size(self, evt): | |
1127 self.log.log("Enter map_wnd->on_size(self, evt)", ORPG_DEBUG) | |
1128 s = self.GetClientSizeTuple() | |
1129 self.canvas.SetDimensions(0,0,s[0],s[1]-self.toolbar_height) | |
1130 self.layer_tabs.SetDimensions(0,s[1]-self.toolbar_height,s[0],self.toolbar_height) | |
1131 self.log.log("Exit map_wnd->on_size(self, evt)", ORPG_DEBUG) |