Mercurial > traipse_dev
comparison orpg/map/_canvas.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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4385a7d0efd1 |
---|---|
1 from threading import Lock | |
2 import mimetypes | |
3 import xml.dom.minidom as minidom | |
4 | |
5 import wx | |
6 | |
7 import orpg.dirpath | |
8 from orpg.orpgCore import * | |
9 from orpg.tools.rgbhex import RGBHex | |
10 | |
11 from _object import * | |
12 | |
13 from _circles import MapCircle | |
14 from _text import MapText | |
15 from _lines import MapLine | |
16 from _grid import GridLayer | |
17 from _fog import FogLayer | |
18 | |
19 USE_BUFFER = True | |
20 if "wxMAC" in wx.PlatformInfo: | |
21 USE_BUFFER = False | |
22 | |
23 class MapCanvas(wx.ScrolledWindow): | |
24 def __init__(self, parent, openrpg): | |
25 wx.ScrolledWindow.__init__(self, parent, wx.ID_ANY, style=wx.HSCROLL | wx.VSCROLL | wx.NO_FULL_REPAINT_ON_RESIZE | wx.SUNKEN_BORDER) | |
26 | |
27 self.openrpg = openrpg | |
28 self.log = self.openrpg.get_component("log") | |
29 self.xml = self.openrpg.get_component("xml") | |
30 self.dir_struct = self.openrpg.get_component("dir_struct") | |
31 self.validate = self.openrpg.get_component("validate") | |
32 self.settings = self.openrpg.get_component("settings") | |
33 self.session = self.openrpg.get_component("session") | |
34 self.chat = self.openrpg.get_component("chat") | |
35 | |
36 self.lock = Lock() | |
37 | |
38 self.RGBHex = RGBHex() | |
39 | |
40 self.toolWnd = parent | |
41 | |
42 self.shift = False | |
43 self.ctrl = False | |
44 | |
45 self.selectedObjects = [] | |
46 self.overObjects = [] | |
47 self._objectId = 0 | |
48 | |
49 self.gridLayer = GridLayer(self) | |
50 self.circleLayer = MapCircle(self) | |
51 self.textLayer = MapText(self) | |
52 self.lineLayer = MapLine(self) | |
53 self.fogLayer = FogLayer(self) | |
54 | |
55 self.zOrder = {} | |
56 self.zOrder['tiles'] = [] | |
57 self.zOrder["back"] = [] | |
58 self.zOrder["front"] = [] | |
59 | |
60 self.bgImage = None | |
61 self.bgType = 'Image' | |
62 self.bgPath = None | |
63 self.backgroundColor = '#008040' | |
64 | |
65 self.gridType = 'Square' | |
66 self.gridLines = wx.SOLID | |
67 self.gridSnap = True | |
68 self.gridSize = 60 | |
69 self.gridColor = "#000000" | |
70 | |
71 self.whiteboardColor = "#000000" | |
72 | |
73 self.zoomScale = 1.0 | |
74 self.lastZoomTime = time.time() | |
75 self.lastZoomScale = 1.0 | |
76 | |
77 self.useFog = False | |
78 self.fogRegion = [] | |
79 self.fogColor = "#000000" | |
80 | |
81 self.zoomScale = 1.0 | |
82 self.lastZoomTime = time.time() | |
83 self.lastZoomScale = 1.0 | |
84 self.zoomTimer = wx.Timer(self) | |
85 self.Bind(wx.EVT_TIMER, self.OnZoomTimer, self.zoomTimer) | |
86 #self.zoomTimer.Start(1000) | |
87 | |
88 self.imageCache = {} | |
89 | |
90 self._SetSize((1000,1000)) | |
91 | |
92 self.Bind(wx.EVT_PAINT, self.OnPaint) | |
93 self.Bind(wx.EVT_SIZE, self.OnSize) | |
94 self.Bind(wx.EVT_MOUSEWHEEL, self.OnZoom) | |
95 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) | |
96 self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) | |
97 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) | |
98 self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) | |
99 self.Bind(wx.EVT_MOTION, self.OnMotion) | |
100 self.Bind(wx.EVT_SCROLLWIN, self.OnScroll) | |
101 self.Bind(wx.EVT_CLOSE, self.OnClose) | |
102 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnBackground) | |
103 self.Bind(wx.EVT_KEY_DOWN, self.OnKey) | |
104 self.Bind(wx.EVT_KEY_UP, self.OnKey) | |
105 | |
106 self.Bind(EVT_ENTER_OBJECT, self.EnterObject) | |
107 self.Bind(EVT_LEAVE_OBJECT, self.LeaveObject) | |
108 self.Bind(EVT_SELECT_OBJECT, self.ObjectSelected) | |
109 self.Bind(EVT_DESELECT_OBJECT, self.ObjectDeselected) | |
110 | |
111 self.roleTimer = wx.Timer(self) | |
112 self.Bind(wx.EVT_TIMER, self.OnRoleTimer, self.roleTimer) | |
113 | |
114 wx.CallAfter(self.OnSize, None) | |
115 | |
116 | |
117 #Public API | |
118 def UpdateMap(self, send=True): | |
119 cdc = wx.ClientDC(self) | |
120 self.PrepareDC(cdc) | |
121 cdc.SetBackgroundMode(wx.TRANSPARENT) | |
122 if USE_BUFFER: | |
123 bdc = wx.BufferedDC(cdc, self._buffer) | |
124 bdc.Clear() | |
125 dc = wx.GraphicsContext.Create(bdc) | |
126 else: | |
127 cdc.Clear() | |
128 dc = wx.GraphicsContext.Create(cdc) | |
129 | |
130 | |
131 dc.SetPen(wx.TRANSPARENT_PEN) | |
132 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
133 | |
134 #Draw BG Color | |
135 r,g,b = self.RGBHex.rgb_tuple(self.backgroundColor) | |
136 brush = wx.Brush(wx.Color(r,g,b,255)) | |
137 dc.SetBrush(brush) | |
138 | |
139 path = dc.CreatePath() | |
140 | |
141 dc.PushState() | |
142 path.AddRectangle(0, 0, self.size[0]+2, self.size[1]+2) | |
143 dc.DrawPath(path) | |
144 dc.PopState() | |
145 | |
146 dc.SetBrush(wx.NullBrush) | |
147 | |
148 #Set the Zoom | |
149 dc.Scale(self.zoomScale, self.zoomScale) | |
150 | |
151 #Draw BG Image | |
152 if self.bgImage != None: | |
153 if self.bgType == 'Image': | |
154 dc.DrawBitmap(self.bgImage, self.offset[0], self.offset[1], self.bgImage.GetWidth(), self.bgImage.GetHeight()) | |
155 else: | |
156 bmpW = self.bgImage.GetWidth() | |
157 bmpH = self.bgImage.GetHeight() | |
158 | |
159 pos = wx.Point(self.offset[0], self.offset[1]) | |
160 while pos.x < self.size[0]: | |
161 dc.DrawBitmap(self.bgImage, pos.x, pos.y, self.bgImage.GetWidth(), self.bgImage.GetHeight()) | |
162 while pos.y < self.size[1]: | |
163 pos.y += bmpH | |
164 dc.DrawBitmap(self.bgImage, pos.x, pos.y, self.bgImage.GetWidth(), self.bgImage.GetHeight()) | |
165 pos.y = 0 | |
166 pos.x += bmpW | |
167 | |
168 #Draw Tiles | |
169 for tile in self.zOrder['tiles']: | |
170 tile.Draw(dc) | |
171 | |
172 #Draw Grid | |
173 self.gridLayer.Draw(dc) | |
174 | |
175 #Draw Objects | |
176 for object in self.zOrder['back']: | |
177 object.Draw(dc) | |
178 | |
179 zl = self.zOrder.keys() | |
180 zl.remove('back') | |
181 zl.remove('front') | |
182 zl.remove('tiles') | |
183 zl.sort() | |
184 | |
185 for layer in zl: | |
186 for object in self.zOrder[layer]: | |
187 object.Draw(dc) | |
188 | |
189 for object in self.zOrder['front']: | |
190 object.Draw(dc) | |
191 | |
192 | |
193 #Draw Fog | |
194 if self.useFog: | |
195 self.fogLayer.Draw(dc) | |
196 | |
197 dc.SetBrush(wx.NullBrush) | |
198 | |
199 dc.Scale(1/self.zoomScale, 1/self.zoomScale) | |
200 | |
201 if self.zoomScale != 1.0: | |
202 pos = self.GetViewStart() | |
203 unit = self.GetScrollPixelsPerUnit() | |
204 pos = [pos[0]*unit[0],pos[1]*unit[1]] | |
205 font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL) | |
206 dc.SetFont(font, wx.BLACK) | |
207 | |
208 dc.DrawText("Zoom Factor: " + str(self.zoomScale), pos[0], pos[1], dc.CreateBrush(wx.WHITE_BRUSH)) | |
209 | |
210 def Clear(self): | |
211 self._SetSize((1000,1000)) | |
212 self.selectedObjects = [] | |
213 self.overObjects = [] | |
214 self._objectId = 0 | |
215 self.bgImage = None | |
216 self.bgType = 'Image' | |
217 self.bgPath = None | |
218 | |
219 self.backgroundColor = '#008040' | |
220 r, g, b = self.RGBHex.rgb_tuple(self.backgroundColor) | |
221 self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.BGColorBtn) | |
222 | |
223 self.gridType = 'Square' | |
224 self.gridLines = wx.SOLID | |
225 self.gridSnap = True | |
226 self.gridSize = 60 | |
227 self.gridColor = "#000000" | |
228 | |
229 self.whiteboardColor = "#000000" | |
230 r, g, b = self.RGBHex.rgb_tuple(self.whiteboardColor) | |
231 self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.ColorBtn) | |
232 | |
233 self.zoomScale = 1.0 | |
234 self.lastZoomTime = time.time() | |
235 self.lastZoomScale = 1.0 | |
236 | |
237 self.useFog = False | |
238 self.fogRegion = [] | |
239 self.fogColor = "#000000" | |
240 | |
241 self.OnRemoveAllObjects(None) | |
242 | |
243 self.toolWnd.Freeze() | |
244 for btn in self.toolWnd.exclusiveToolList: | |
245 self.toolWnd.exclusiveToolList[btn].SetToggled(False) | |
246 | |
247 self.toolWnd.FogBtn.SetToggled(False) | |
248 self.toolWnd.SelectorBtn.SetToggled(True) | |
249 self.toolWnd.Thaw() | |
250 | |
251 def GetNewObjectId(self): | |
252 return str(self._objectId+1) | |
253 | |
254 #Map Events | |
255 def OnBackground(self, event): | |
256 #Dont do it | |
257 pass | |
258 | |
259 def OnPaint(self, event): | |
260 if USE_BUFFER: | |
261 dc = wx.PaintDC(self) | |
262 self.PrepareDC(dc) | |
263 dc.DrawBitmap(self._buffer, 0, 0) | |
264 else: | |
265 event.Skip() | |
266 | |
267 | |
268 def OnSize(self, event): | |
269 self._buffer = wx.EmptyBitmap(self.size[0], self.size[1]) | |
270 self._FixScroll() | |
271 wx.CallAfter(self.UpdateMap) | |
272 | |
273 | |
274 def OnZoom(self, event): | |
275 if event.GetWheelRotation() < 0: | |
276 self.zoomScale -= .1 | |
277 if self.zoomScale < .5: | |
278 self.zoomScale = .5 | |
279 else: | |
280 self.lastZoomTime = time.time() | |
281 self._FixScroll() | |
282 self.UpdateMap() | |
283 else: | |
284 self.zoomScale += .1 | |
285 | |
286 if self.zoomScale > 1.5: | |
287 self.zoomScale = 1.5 | |
288 else: | |
289 self.lastZoomTime = time.time() | |
290 self._FixScroll() | |
291 self.UpdateMap() | |
292 | |
293 def OnKey(self, event): | |
294 self.shift = False | |
295 self.ctrl = False | |
296 if event.ShiftDown(): | |
297 self.shift = True | |
298 elif event.ControlDown(): | |
299 self.ctrl = True | |
300 | |
301 | |
302 def EnterObject(self, event): | |
303 obj = event.GetObject() | |
304 self.overObjects.append(obj) | |
305 obj.Highlight() | |
306 | |
307 def LeaveObject(self, event): | |
308 obj = event.GetObject() | |
309 try: | |
310 self.overObjects.remove(obj) | |
311 except: | |
312 pass | |
313 obj.UnHighlight() | |
314 | |
315 def ObjectSelected(self, event): | |
316 obj = event.GetObject() | |
317 self.selectedObjects.append(obj) | |
318 try: | |
319 self.overObjects.remove(obj) | |
320 except: | |
321 pass | |
322 obj.UnHighlight() | |
323 | |
324 def ObjectDeselected(self, event): | |
325 obj = event.GetObject() | |
326 try: | |
327 self.selectedObjects.remove(obj) | |
328 except: | |
329 pass | |
330 obj.Update() | |
331 | |
332 def OnLeftDown(self, event): | |
333 dc = wx.ClientDC(self) | |
334 self.PrepareDC(dc) | |
335 pos = event.GetLogicalPosition(dc) | |
336 pos.x /= self.zoomScale | |
337 pos.y /= self.zoomScale | |
338 | |
339 if self.toolWnd.AddShapeBtn.GetToggled() and self.toolWnd.currentShape == 'Circle': | |
340 self.circleLayer.OnLeftDown(pos) | |
341 | |
342 elif self.toolWnd.AddTextBtn.GetToggled(): | |
343 self.textLayer.OnLeftDown(pos) | |
344 | |
345 elif self.toolWnd.DrawBtn.GetToggled(): | |
346 self.lineLayer.OnLeftDown(pos) | |
347 | |
348 elif self.toolWnd.SelectorBtn.GetToggled() and (self.selectedObjects == [] or self.ctrl or self.shift) and not (self.useFog and self.fogLayer.region.Contains(pos.x, pos.y) and not self.toolWnd.gmToolBar.IsShown()): | |
349 self.initiatPos = pos | |
350 self.lxd = 0 | |
351 self.lyd = 0 | |
352 if len(self.overObjects) == 0: | |
353 return | |
354 elif len(self.overObjects) == 1: | |
355 self.overObjects[0].Select() | |
356 else: | |
357 if not self.shift: | |
358 menu = wx.Menu("Object Selection") | |
359 id = 0 | |
360 for obj in self.overObjects: | |
361 menu.Append(id, obj.GetName()) | |
362 id += 1 | |
363 | |
364 def selectmenu(event): | |
365 id = event.GetId() | |
366 self.overObjects[id].Select() | |
367 self.Unbind(wx.EVT_MENU) | |
368 | |
369 self.Bind(wx.EVT_MENU, selectmenu) | |
370 self.PopupMenu(menu) | |
371 else: | |
372 for i in xrange(len(self.overObjects)): | |
373 self.overObjects[0].Select() | |
374 | |
375 elif self.toolWnd.SelectorBtn.GetToggled() and not self.selectedObjects == []: | |
376 xd = (self.initiatPos.x+pos.x)*(self.initiatPos.x+pos.x) | |
377 yd = (self.initiatPos.y+pos.y)*(self.initiatPos.y+pos.y) | |
378 | |
379 for i in xrange(len(self.selectedObjects)): | |
380 self.selectedObjects[0].Deselect() | |
381 | |
382 elif self.toolWnd.FogToolBtn.GetToggled(): | |
383 self.fogLayer.OnLeftDown(pos) | |
384 | |
385 def OnLeftDClick(self, event): | |
386 dc = wx.ClientDC(self) | |
387 self.PrepareDC(dc) | |
388 pos = event.GetLogicalPosition(dc) | |
389 pos.x /= self.zoomScale | |
390 pos.y /= self.zoomScale | |
391 | |
392 if self.toolWnd.DrawBtn.GetToggled(): | |
393 self.lineLayer.OnLeftDClick(pos) | |
394 | |
395 def OnLeftUp(self, event): | |
396 dc = wx.ClientDC(self) | |
397 self.PrepareDC(dc) | |
398 pos = event.GetLogicalPosition(dc) | |
399 pos.x /= self.zoomScale | |
400 pos.y /= self.zoomScale | |
401 | |
402 if self.toolWnd.AddShapeBtn.GetToggled() and self.toolWnd.currentShape == 'Circle': | |
403 self.circleLayer.OnLeftUp(pos) | |
404 | |
405 elif self.toolWnd.FogToolBtn.GetToggled(): | |
406 self.fogLayer.OnLeftUp(pos) | |
407 | |
408 elif self.toolWnd.DrawBtn.GetToggled(): | |
409 self.lineLayer.OnLeftUp(pos) | |
410 | |
411 elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects == []: | |
412 rgn = wx.Region(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) | |
413 | |
414 for object in self.zOrder['back']: | |
415 if rgn.Contains(object.start.x, object.start.y): | |
416 object.Select() | |
417 | |
418 zl = self.zOrder.keys() | |
419 zl.remove('back') | |
420 zl.remove('front') | |
421 zl.remove('tiles') | |
422 zl.sort() | |
423 | |
424 for layer in zl: | |
425 for object in self.zOrder[layer]: | |
426 if rgn.Contains(object.start.x, object.start.y): | |
427 object.Select() | |
428 | |
429 for object in self.zOrder['front']: | |
430 if rgn.Contains(object.start.x, object.start.y): | |
431 object.Select() | |
432 | |
433 self.lxd = 0 | |
434 self.lyd = 0 | |
435 self.initiatPos = pos | |
436 self.Refresh() | |
437 | |
438 def OnMotion(self, event): | |
439 dc = wx.ClientDC(self) | |
440 self.PrepareDC(dc) | |
441 pos = event.GetLogicalPosition(dc) | |
442 pos.x /= self.zoomScale | |
443 pos.y /= self.zoomScale | |
444 | |
445 | |
446 #HitTest | |
447 for object in self.zOrder['back']: | |
448 object.HitTest(pos) | |
449 | |
450 zl = self.zOrder.keys() | |
451 zl.remove('back') | |
452 zl.remove('front') | |
453 zl.remove('tiles') | |
454 zl.sort() | |
455 | |
456 for layer in zl: | |
457 for object in self.zOrder[layer]: | |
458 object.HitTest(pos) | |
459 | |
460 for object in self.zOrder['front']: | |
461 object.HitTest(pos) | |
462 | |
463 if self.toolWnd.AddShapeBtn.GetToggled() and event.m_leftDown and self.toolWnd.currentShape == 'Circle': | |
464 self.circleLayer.OnMotion(pos) | |
465 | |
466 elif self.toolWnd.DrawBtn.GetToggled() and self.lineLayer.start != wx.Point(0,0): | |
467 self.lineLayer.OnMotion(pos) | |
468 | |
469 elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects != [] and not (self.ctrl or self.shift): | |
470 xd = (pos.x-self.initiatPos.x) | |
471 yd = (pos.y-self.initiatPos.y) | |
472 for obj in self.selectedObjects: | |
473 obj.start.x += xd | |
474 obj.start.y += yd | |
475 obj.Update() | |
476 self.initiatPos = pos | |
477 | |
478 | |
479 elif self.toolWnd.SelectorBtn.GetToggled() and self.selectedObjects == [] and event.m_leftDown: | |
480 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
481 pen = wx.Pen(wx.BLACK, 3, wx.DOT) | |
482 dc.SetPen(pen) | |
483 dc.SetLogicalFunction(wx.INVERT) | |
484 | |
485 xd = (pos.x-self.initiatPos.x) | |
486 yd = (pos.y-self.initiatPos.y) | |
487 | |
488 if self.lxd != 0 and self.lyd != 0: | |
489 r = wx.Rect(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) | |
490 dc.DrawRectangleRect(r) | |
491 | |
492 self.lxd = xd | |
493 self.lyd = yd | |
494 r = wx.Rect(self.initiatPos.x, self.initiatPos.y, self.lxd, self.lyd) | |
495 dc.DrawRectangleRect(r) | |
496 | |
497 elif (self.toolWnd.FogToolBtn.GetToggled()) and event.m_leftDown: | |
498 self.fogLayer.OnMotion(pos) | |
499 | |
500 def OnRightDown(self, event): | |
501 mapmenu = wx.Menu() | |
502 | |
503 item = wx.MenuItem(mapmenu, wx.ID_ANY, "Load Map", "Load Map") | |
504 #self.Bind(wx.EVT_MENU, self.OnOpenBtn, item) | |
505 mapmenu.AppendItem(item) | |
506 | |
507 item = wx.MenuItem(mapmenu, wx.ID_ANY, "Save Map", "Save Map") | |
508 #self.Bind(wx.EVT_MENU, self.OnSaveBtn, item) | |
509 mapmenu.AppendItem(item) | |
510 | |
511 item = wx.MenuItem(mapmenu, wx.ID_ANY, "Default Map", "Default Map") | |
512 self.Bind(wx.EVT_MENU, self.OnDefaultBtn, item) | |
513 mapmenu.AppendItem(item) | |
514 | |
515 item = wx.MenuItem(mapmenu, wx.ID_ANY, "Map Properties", "Map Properties") | |
516 #self.Bind(wx.EVT_MENU, OnMapPropsBtn, item) | |
517 mapmenu.AppendItem(item) | |
518 | |
519 bgmenu = wx.Menu() | |
520 | |
521 item = wx.MenuItem(bgmenu, wx.ID_ANY, "Change Background Image", "Change Background Image") | |
522 self.Bind(wx.EVT_MENU, self.OnBGBtn, item) | |
523 bgmenu.AppendItem(item) | |
524 | |
525 item = wx.MenuItem(bgmenu, wx.ID_ANY, "Change Background Color", "Change Background Color") | |
526 self.Bind(wx.EVT_MENU, self.OnBGColorBtn, item) | |
527 bgmenu.AppendItem(item) | |
528 | |
529 item = wx.MenuItem(bgmenu, wx.ID_ANY, "Grid Properties", "Grid Properties") | |
530 #self.Bind(wx.EVT_MENU, self.OnGridBtn, item) | |
531 bgmenu.AppendItem(item) | |
532 | |
533 fogmenu = wx.Menu() | |
534 | |
535 item = wx.MenuItem(fogmenu, wx.ID_ANY, "Toggle Fog", "Toggle Fog") | |
536 self.Bind(wx.EVT_MENU, self.OnFogBtn, item) | |
537 fogmenu.AppendItem(item) | |
538 | |
539 item = wx.MenuItem(fogmenu, wx.ID_ANY, "Fog Color", "Fog Color") | |
540 self.Bind(wx.EVT_MENU, self.OnFogColorBtn, item) | |
541 fogmenu.AppendItem(item) | |
542 | |
543 menu = wx.Menu() | |
544 | |
545 if self.toolWnd.gmToolBar.IsShown(): | |
546 menu.AppendMenu(wx.ID_ANY, "Map", mapmenu) | |
547 menu.AppendMenu(wx.ID_ANY, "Background", bgmenu) | |
548 menu.AppendMenu(wx.ID_ANY, "Fog", fogmenu) | |
549 menu.AppendSeparator() | |
550 item = wx.MenuItem(menu, wx.ID_ANY, "Miniture Properties", "Miniture Properties") | |
551 #self.Bind(wx.EVT_MENU, self.OnColorBtn, item) | |
552 menu.AppendItem(item) | |
553 menu.AppendSeparator() | |
554 | |
555 item = wx.MenuItem(menu, wx.ID_ANY, "Whiteboard Color", "Whiteboard Color") | |
556 self.Bind(wx.EVT_MENU, self.OnColorBtn, item) | |
557 menu.AppendItem(item) | |
558 | |
559 | |
560 def ObjectMenu(event): | |
561 id = event.GetId() | |
562 objid = int(menu.GetHelpString(id)) | |
563 menuname = menu.GetLabel(id) | |
564 obj = self.overObjects[objid] | |
565 | |
566 if menuname == "Move To Back": | |
567 self.MoveToBack(obj) | |
568 | |
569 elif menuname == "Move Back": | |
570 self.MoveBack(obj) | |
571 | |
572 elif menuname == "Move Forward": | |
573 self.MoveForward(obj) | |
574 | |
575 elif menuname == "Move To Front": | |
576 self.MoveToFront(obj) | |
577 | |
578 elif menuname == "Remove": | |
579 self.zOrder[obj.zOrder].remove(obj) | |
580 obj.Update() | |
581 | |
582 self.Unbind(wx.EVT_MENU) | |
583 self.overObjects.remove(obj) | |
584 | |
585 | |
586 if len(self.overObjects): | |
587 menu.AppendSeparator() | |
588 | |
589 id = 0 | |
590 for obj in self.overObjects: | |
591 if obj.IsShown() or self.toolWnd.gmToolBar.IsShown(): | |
592 objmenu = wx.Menu() | |
593 item = wx.MenuItem(objmenu, wx.ID_ANY, "Move To Back", str(id)) | |
594 self.Bind(wx.EVT_MENU, ObjectMenu, item) | |
595 objmenu.AppendItem(item) | |
596 item = wx.MenuItem(objmenu, wx.ID_ANY, "Move Back", str(id)) | |
597 self.Bind(wx.EVT_MENU, ObjectMenu, item) | |
598 objmenu.AppendItem(item) | |
599 item = wx.MenuItem(objmenu, wx.ID_ANY, "Move Forward", str(id)) | |
600 self.Bind(wx.EVT_MENU, ObjectMenu, item) | |
601 objmenu.AppendItem(item) | |
602 item = wx.MenuItem(objmenu, wx.ID_ANY, "Move To Front", str(id)) | |
603 self.Bind(wx.EVT_MENU, ObjectMenu, item) | |
604 objmenu.AppendItem(item) | |
605 objmenu.AppendSeparator() | |
606 if obj.IsShown(): | |
607 item = wx.MenuItem(objmenu, wx.ID_ANY, "Hide", str(id)) | |
608 self.Bind(wx.EVT_MENU, obj.Hide, item) | |
609 objmenu.AppendItem(item) | |
610 objmenu.AppendSeparator() | |
611 elif self.toolWnd.gmToolBar.IsShown(): | |
612 item = wx.MenuItem(objmenu, wx.ID_ANY, "Show", str(id)) | |
613 self.Bind(wx.EVT_MENU, obj.Show, item) | |
614 objmenu.AppendItem(item) | |
615 objmenu.AppendSeparator() | |
616 item = wx.MenuItem(objmenu, wx.ID_ANY, "Remove", str(id)) | |
617 self.Bind(wx.EVT_MENU, ObjectMenu, item) | |
618 objmenu.AppendItem(item) | |
619 item = wx.MenuItem(objmenu, wx.ID_ANY, "Properties", str(id)) | |
620 self.Bind(wx.EVT_MENU, obj.ShowProperties, item) | |
621 objmenu.AppendItem(item) | |
622 menu.AppendMenu(wx.ID_ANY, obj.GetName(), objmenu) | |
623 | |
624 menu.AppendSeparator() | |
625 item = wx.MenuItem(menu, wx.ID_ANY, "Remove All Objects", "Remove All Whiteboard Items") | |
626 self.Bind(wx.EVT_MENU, self.OnRemoveAllObjects, item) | |
627 menu.AppendItem(item) | |
628 | |
629 self.PopupMenu(menu) | |
630 | |
631 | |
632 def OnRemoveAllObjects(self, event): | |
633 for layer in self.zOrder: | |
634 for i in xrange(len(self.zOrder[layer])): | |
635 del self.zOrder[layer][0] | |
636 | |
637 self.zOrder = {} | |
638 self.zOrder['tiles'] = [] | |
639 self.zOrder["back"] = [] | |
640 self.zOrder["front"] = [] | |
641 if event != None: | |
642 self.UpdateMap() | |
643 | |
644 def MoveToBack(self, object): | |
645 self.zOrder[object.zOrder].remove(object) | |
646 self.zOrder['back'].append(object) | |
647 object.zOrder = 'back' | |
648 self.UpdateMap() | |
649 | |
650 def MoveToFront(self, object): | |
651 self.zOrder[object.zOrder].remove(object) | |
652 self.zOrder['front'].append(object) | |
653 object.zOrder = 'front' | |
654 self.UpdateMap() | |
655 | |
656 def MoveBack(self, object): | |
657 self.zOrder[object.zOrder].remove(object) | |
658 | |
659 zl = self.zOrder.keys() | |
660 zl.remove('back') | |
661 zl.remove('front') | |
662 zl.remove('tiles') | |
663 zl.sort() | |
664 lzo = 1 | |
665 if len(zl): | |
666 lzo = zl.pop() | |
667 | |
668 if object.zOrder == 'back' or object.zOrder == 1: | |
669 self.zOrder['back'].append(object) | |
670 object.zOrder = 'back' | |
671 elif object.zOrder == 'front': | |
672 if not self.zOrder.has_key(lzo): | |
673 self.zOrder[lzo] = [] | |
674 self.zOrder[lzo].append(object) | |
675 object.zOrder = lzo | |
676 else: | |
677 object.zOrder -= 1 | |
678 if not self.zOrder.has_key(object.zOrder): | |
679 self.zOrder[object.zOrder] = [] | |
680 self.zOrder[object.zOrder].append(object) | |
681 self.UpdateMap() | |
682 | |
683 def MoveForward(self, object): | |
684 self.zOrder[object.zOrder].remove(object) | |
685 | |
686 zl = self.zOrder.keys() | |
687 zl.remove('back') | |
688 zl.remove('front') | |
689 zl.remove('tiles') | |
690 zl.sort() | |
691 lzo = 1 | |
692 if len(zl): | |
693 lzo = zl.pop() | |
694 | |
695 if object.zOrder == 'back': | |
696 if not self.zOrder.has_key(1): | |
697 self.zOrder[1] = [] | |
698 self.zOrder[1].append(object) | |
699 object.zOrder = 1 | |
700 elif z == 'front': | |
701 self.zOrder['front'].append(object) | |
702 object.zOrder = 'front' | |
703 else: | |
704 object.zOrder += 1 | |
705 if not self.zOrder.has_key(object.zOrder): | |
706 self.zOrder[object.zOrder] = [] | |
707 self.zOrder[object.zOrder].append(object) | |
708 self.UpdateMap() | |
709 | |
710 def OnScroll(self, event): | |
711 event.Skip() | |
712 self.Refresh() | |
713 | |
714 def OnZoomTimer(self, event): | |
715 if (time.time() - self.lastZoomTime) >= 3 and self.lastZoomScale != self.zoomScale: | |
716 #Send Zoome Notice to other clients | |
717 self.lastZoomTime = time.time() | |
718 self.lastZoomScale = self.zoomScale | |
719 | |
720 def OnRoleTimer(self, event): | |
721 #Figure out the users role | |
722 if self.session.my_role() == self.session.ROLE_GM: | |
723 self.role = 'GM' | |
724 elif self.session.my_role() == self.session.ROLE_PLAYER: | |
725 self.role = 'Player' | |
726 else: | |
727 self.role = 'Lurker' | |
728 | |
729 if self.role == 'GM' and not self.toolWnd.gmToolBar.IsShown() and not (str(self.session.group_id) == '0' and str(self.session.status) == '1'): | |
730 self.toolWnd.Freeze() | |
731 self.toolWnd.gmToolBar.Show() | |
732 self.toolWnd.Thaw() | |
733 elif self.role == 'Player' and not (str(self.session.group_id) == '0' and str(self.session.status) == '1'): | |
734 if self.toolWnd.gmToolBar.IsShown(): | |
735 self.toolWnd.Freeze() | |
736 self.toolWnd.gmToolBar.Hide() | |
737 self.toolWnd.Thaw() | |
738 | |
739 if not self.toolWnd.playerToolBar.IsShown(): | |
740 self.toolWnd.Freeze() | |
741 self.toolWnd.playerToolBar.Show() | |
742 self.toolWnd.Thaw() | |
743 elif self.role == 'Lurker' or (str(self.session.group_id) == '0' and str(self.session.status) == '1'): | |
744 if self.toolWnd.playerToolBar.IsShown(): | |
745 self.toolWnd.Freeze() | |
746 self.toolWnd.gmToolBar.Hide() | |
747 self.toolWnd.playerToolBar.Hide() | |
748 self.toolWnd.Thaw() | |
749 | |
750 try: | |
751 self.toolWnd.Layout() | |
752 except: | |
753 pass | |
754 | |
755 def OnClose(self, event): | |
756 self.zoomTimer.Stop() | |
757 self.roleTimer.Stop() | |
758 event.Skip() | |
759 | |
760 #Toolbar Events | |
761 def OnDefaultBtn(self, event): | |
762 self.Clear() | |
763 wx.CallAfter(self.UpdateMap) | |
764 | |
765 def OnColorBtn(self, event): | |
766 newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) | |
767 if newcolor == None: | |
768 return | |
769 | |
770 self.whiteboardColor = newcolor | |
771 r, g, b = self.RGBHex.rgb_tuple(self.whiteboardColor) | |
772 self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.ColorBtn) | |
773 | |
774 def OnBGColorBtn(self, event): | |
775 newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) | |
776 if newcolor == None: | |
777 return | |
778 | |
779 self.backgroundColor = newcolor | |
780 r, g, b = self.RGBHex.rgb_tuple(self.backgroundColor) | |
781 self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.BGColorBtn) | |
782 self.UpdateMap() | |
783 | |
784 def OnFogColorBtn(self, event): | |
785 newcolor = self.RGBHex.do_hex_color_dlg(self.toolWnd) | |
786 if newcolor == None: | |
787 return | |
788 | |
789 self.fogColor = newcolor | |
790 r, g, b = self.RGBHex.rgb_tuple(self.fogColor) | |
791 self.toolWnd._SetColorBtn(wx.Color(r, g, b, 255), self.toolWnd.FogColorBtn) | |
792 self.UpdateMap() | |
793 | |
794 def OnExlusiveBtn(self, event): | |
795 id = event.GetId() | |
796 #This is backwards because the Toggle Switch does not get set until AFTER The mouse gets released | |
797 if not self.toolWnd.exclusiveToolList[id].GetToggled(): | |
798 self.toolWnd.Freeze() | |
799 #Disable all mutualy exclusive tools | |
800 for btn in self.toolWnd.exclusiveToolList: | |
801 if self.toolWnd.exclusiveToolList[btn].GetId() != id: | |
802 self.toolWnd.exclusiveToolList[btn].SetToggled(False) | |
803 self.toolWnd.Thaw() | |
804 else: | |
805 wx.CallAfter(self.toolWnd.SelectorBtn.SetToggled, True) | |
806 | |
807 def OnFogBtn(self, event): | |
808 if not self.toolWnd.FogBtn.GetToggled(): | |
809 self.useFog = True | |
810 else: | |
811 self.useFog = False | |
812 self.toolWnd.Freeze() | |
813 self.toolWnd.SelectorBtn.SetToggled(True) | |
814 self.toolWnd.FogToolBtn.SetToggled(False) | |
815 self.toolWnd.Thaw() | |
816 self.fogRegion = [] | |
817 self.UpdateMap() | |
818 | |
819 def OnBGBtn(self, event): | |
820 dlg = wx.Dialog(self.toolWnd, wx.ID_ANY, title="Background Properties") | |
821 sizer = wx.BoxSizer(wx.HORIZONTAL) | |
822 | |
823 filename = wx.TextCtrl(dlg, wx.ID_ANY) | |
824 filename.Hide() | |
825 | |
826 bgpath = wx.TextCtrl(dlg, wx.ID_ANY) | |
827 if self.bgPath != None: | |
828 bgpath.SetValue(self.bgPath) | |
829 | |
830 bgtype = wx.Choice(dlg, wx.ID_ANY, choices=['Image', 'Texture']) | |
831 bgtype.SetStringSelection(self.bgType) | |
832 | |
833 browsebtn = wx.Button(dlg, wx.ID_ANY, "Browse") | |
834 okbtn = wx.Button(dlg, wx.ID_OK) | |
835 cancelbtn = wx.Button(dlg, wx.ID_CANCEL) | |
836 | |
837 sizer.Add(wx.StaticText(dlg, wx.ID_ANY, "Image Path"), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2) | |
838 sizer.Add(bgpath, 0, wx.EXPAND|wx.ALL, 3) | |
839 sizer.Add(wx.StaticText(dlg, wx.ID_ANY, "Image Type"), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 2) | |
840 sizer.Add(bgtype, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 3) | |
841 sizer.Add(browsebtn, 0, wx.EXPAND|wx.ALL, 2) | |
842 sizer.Add(okbtn, 0, wx.EXPAND|wx.ALL, 3) | |
843 sizer.Add(cancelbtn, 0, wx.EXPAND|wx.ALL, 2) | |
844 | |
845 dlg.SetSizer(sizer) | |
846 dlg.SetAutoLayout(True) | |
847 dlg.Fit() | |
848 | |
849 def OnBrowse(event): | |
850 filedlg = wx.FileDialog(self, "Select an Image File", self.dir_struct["user"], wildcard="Image files (*.bmp, *.gif, *.jpg, *.png)|*.bmp;*.gif;*.jpg;*.png", style=wx.HIDE_READONLY|wx.OPEN) | |
851 if filedlg.ShowModal() != wx.ID_OK: | |
852 filedlg.Destroy() | |
853 return | |
854 | |
855 bgpath.SetValue(filedlg.GetPath()) | |
856 filename.SetValue(filedlg.GetFilename()) | |
857 | |
858 dlg.Bind(wx.EVT_BUTTON, OnBrowse, browsebtn) | |
859 dlg.Show() | |
860 | |
861 if not dlg.ShowModal() == wx.ID_OK: | |
862 dlg.Destroy() | |
863 return | |
864 | |
865 self.bgType = bgtype.GetStringSelection() | |
866 | |
867 if bgpath.GetValue().lower().find('http:') == -1: | |
868 file = open(bgpath.GetValue(), "rb") | |
869 imgdata = file.read() | |
870 file.close() | |
871 | |
872 (imgtype,j) = mimetypes.guess_type(filename.GetValue()) | |
873 | |
874 postdata = urllib.urlencode({'filename':filename.GetValue(), 'imgdata':imgdata, 'imgtype':imgtype}) | |
875 | |
876 thread.start_new_thread(self.__Upload, (postdata, bgpath.GetValue(), "Background")) | |
877 else: | |
878 self.bgImage = self._LoadImage(bgpath.GetValue()) | |
879 self.UpdateMap() | |
880 | |
881 | |
882 #Private Methods | |
883 def _SetSize(self, size): | |
884 if size[0] == -1: | |
885 size[0] = self.size[0] | |
886 if size[1] == -1: | |
887 size[1] = self.size[1] | |
888 | |
889 if size[0] < 300: | |
890 size = (300, size[1]) | |
891 if size[1] < 300: | |
892 size = (size[0], 300) | |
893 | |
894 size1 = self.GetClientSizeTuple() | |
895 | |
896 if size[0] < size1[0]: | |
897 size = (size1[0], size[1]) | |
898 if size[1] < size1[1]: | |
899 size = (size[0], size1[1]) | |
900 | |
901 self.sizeChanged = 1 | |
902 self.size = size | |
903 self._FixScroll() | |
904 | |
905 def _FixScroll(self): | |
906 scale = self.zoomScale | |
907 pos = self.GetViewStart() | |
908 unit = self.GetScrollPixelsPerUnit() | |
909 pos = [pos[0]*unit[0],pos[1]*unit[1]] | |
910 size = self.GetClientSize() | |
911 unit = [10*scale,10*scale] | |
912 if (unit[0] == 0 or unit[1] == 0): | |
913 return | |
914 pos[0] /= unit[0] | |
915 pos[1] /= unit[1] | |
916 mx = [int(self.size[0]*scale/unit[0])+1, int(self.size[1]*scale/unit[1]+1)] | |
917 self.SetScrollbars(unit[0], unit[1], mx[0], mx[1], pos[0], pos[1]) | |
918 | |
919 def _LoadImage(self, path, miniId=None): | |
920 if self.imageCache.has_key(path): | |
921 return self.imageCache[path] | |
922 | |
923 while len(self.imageCache) > int(self.settings.get_setting("ImageCacheSize")): | |
924 keys = self.imageCache.keys() | |
925 del self.imageCache[keys[0]] | |
926 | |
927 | |
928 thread.start_new_thread(self.__DownloadImage, (path, miniId)) | |
929 | |
930 return wx.Bitmap(orpg.dirpath.dir_struct["icon"] + "fetching.png", wx.BITMAP_TYPE_PNG) | |
931 | |
932 def _ClearCache(self): | |
933 for key in self.imageCache: | |
934 del self.imageCache[key] | |
935 | |
936 #Threads | |
937 def __Upload(self, postdata, filename, type="Background"): | |
938 self.lock.acquire() | |
939 | |
940 url = self.settings.get_setting('ImageServerBaseURL') | |
941 file = urllib.urlopen(url, postdata) | |
942 recvdata = file.read() | |
943 file.close() | |
944 try: | |
945 xml_dom = minidom.parseString(recvdata)._get_documentElement() | |
946 | |
947 if xml_dom.nodeName == 'path': | |
948 path = xml_dom.getAttribute('url') | |
949 path = urllib.unquote(path) | |
950 | |
951 if type == 'Background': | |
952 self.bgImage = self._LoadImage(path) | |
953 self.bgPath = path | |
954 | |
955 else: | |
956 self.minis.append(self.mapLayer.AddMiniture(path)) | |
957 | |
958 self.UpdateMap() | |
959 | |
960 else: | |
961 self.chat.InfoPost(xml_dom.getAttribute('msg')) | |
962 except Exception, e: | |
963 print e | |
964 print recvdata | |
965 | |
966 self.lock.release() | |
967 | |
968 def __DownloadImage(self, path, miniId): | |
969 self.lock.acquire() | |
970 | |
971 uriPath = urllib.unquote(path) | |
972 try: | |
973 data = urllib.urlretrieve(uriPath) | |
974 | |
975 if data[0] and data[1].getmaintype() == "image": | |
976 imageType = data[1].gettype() | |
977 img = wx.ImageFromMime(data[0], imageType).ConvertToBitmap() | |
978 self.imageCache[path] = img | |
979 | |
980 if miniId == None: | |
981 self.bgImage = img | |
982 if self.bgType == 'Image': | |
983 self._SetSize((img.GetHeight(), img.GetWidth())) | |
984 | |
985 else: | |
986 mini = self.GetMiniById(miniId) | |
987 mini.image = img | |
988 | |
989 self.UpdateMap() | |
990 except Exception, e: | |
991 self.chat.InfoPost("Unable to resolve/open the specified URI; image was NOT laoded:" + path) | |
992 | |
993 urllib.urlcleanup() | |
994 self.lock.release() |