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()