Mercurial > traipse_dev
comparison orpg/mapper/miniatures.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 | 2b9e766f9dee |
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/miniatures.py | |
21 # Author: Chris Davis | |
22 # Maintainer: | |
23 # Version: | |
24 # $Id: miniatures.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $ | |
25 # | |
26 # Description: This file contains some of the basic definitions for the chat | |
27 # utilities in the orpg project. | |
28 # | |
29 __version__ = "$Id: miniatures.py,v 1.46 2007/12/07 20:39:50 digitalxero Exp $" | |
30 | |
31 from base import * | |
32 import thread | |
33 import time | |
34 import urllib | |
35 import os.path | |
36 | |
37 MIN_STICKY_BACK = -0XFFFFFF | |
38 MIN_STICKY_FRONT = 0xFFFFFF | |
39 | |
40 ##---------------------------------------- | |
41 ## miniature object | |
42 ##---------------------------------------- | |
43 | |
44 FACE_NONE = 0 | |
45 FACE_NORTH = 1 | |
46 FACE_NORTHEAST = 2 | |
47 FACE_EAST = 3 | |
48 FACE_SOUTHEAST = 4 | |
49 FACE_SOUTH = 5 | |
50 FACE_SOUTHWEST = 6 | |
51 FACE_WEST = 7 | |
52 FACE_NORTHWEST = 8 | |
53 SNAPTO_ALIGN_CENTER = 0 | |
54 SNAPTO_ALIGN_TL = 1 | |
55 | |
56 def cmp_zorder(first,second): | |
57 f = first.zorder | |
58 s = second.zorder | |
59 if f == None: | |
60 f = 0 | |
61 if s == None: | |
62 s = 0 | |
63 if f == s: | |
64 value = 0 | |
65 elif f < s: | |
66 value = -1 | |
67 else: | |
68 value = 1 | |
69 return value | |
70 | |
71 class BmpMiniature: | |
72 def __init__(self, id,path, bmp, pos=cmpPoint(0,0), heading=FACE_NONE, face=FACE_NONE, label="", locked=False, hide=False, snap_to_align=SNAPTO_ALIGN_CENTER, zorder=0, width=0, height=0, log=None, local=False, localPath='', localTime=-1): | |
73 self.log = log | |
74 self.log.log("Enter BmpMiniature", ORPG_DEBUG) | |
75 self.heading = heading | |
76 self.face = face | |
77 self.label = label | |
78 self.path = path | |
79 self.bmp = bmp | |
80 self.pos = pos | |
81 self.selected = False | |
82 self.locked = locked | |
83 self.snap_to_align = snap_to_align | |
84 self.hide = hide | |
85 self.id = id | |
86 self.zorder = zorder | |
87 self.left = 0 | |
88 self.local = local | |
89 self.localPath = localPath | |
90 self.localTime = localTime | |
91 if not width: | |
92 self.width = 0 | |
93 else: | |
94 self.width = width | |
95 if not height: | |
96 self.height = 0 | |
97 else: | |
98 self.height = height | |
99 self.right = bmp.GetWidth() | |
100 self.top = 0 | |
101 self.bottom = bmp.GetHeight() | |
102 self.isUpdated = False | |
103 self.gray = False | |
104 self.log.log("Exit BmpMiniature", ORPG_DEBUG) | |
105 | |
106 def __del__(self): | |
107 self.log.log("Enter BmpMiniature->__del__(self)", ORPG_DEBUG) | |
108 del self.bmp | |
109 self.bmp = None | |
110 self.log.log("Exit BmpMiniature->__del__(self)", ORPG_DEBUG) | |
111 | |
112 def set_bmp(self, bmp): | |
113 self.log.log("Enter BmpMiniature->set_bmp(self, bmp)", ORPG_DEBUG) | |
114 self.bmp = bmp | |
115 self.log.log("Exit BmpMiniature->set_bmp(self, bmp)", ORPG_DEBUG) | |
116 | |
117 def set_min_props(self, heading=FACE_NONE, face=FACE_NONE, label="", locked=False, hide=False, width=0, height=0): | |
118 self.log.log("Enter BmpMiniature->set_min_props(self, heading, face, label, locked, hide, width, height)", ORPG_DEBUG) | |
119 self.heading = heading | |
120 self.face = face | |
121 self.label = label | |
122 if locked: | |
123 self.locked = True | |
124 else: | |
125 self.locked = False | |
126 if hide: | |
127 self.hide = True | |
128 else: | |
129 self.hide = False | |
130 self.width = int(width) | |
131 self.height = int(height) | |
132 self.isUpdated = True | |
133 self.log.log("Exit BmpMiniature->set_min_props(self, heading, face, label, locked, hide, width, height)", ORPG_DEBUG) | |
134 | |
135 def hit_test(self, pt): | |
136 self.log.log("Enter BmpMiniature->hit_test(self, pt)", ORPG_DEBUG) | |
137 rect = self.get_rect() | |
138 result = None | |
139 result = rect.InsideXY(pt.x, pt.y) | |
140 self.log.log("Exit BmpMiniature->hit_test(self, pt)", ORPG_DEBUG) | |
141 return result | |
142 | |
143 def get_rect(self): | |
144 self.log.log("Enter BmpMiniature->get_rect(self)", ORPG_DEBUG) | |
145 ret = wx.Rect(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
146 self.log.log("Exit BmpMiniature->get_rect(self)", ORPG_DEBUG) | |
147 return ret | |
148 | |
149 def draw(self, dc, mini_layer, op=wx.COPY): | |
150 self.log.log("Enter BmpMiniature->draw(self, dc, mini_layer, op)", ORPG_DEBUG) | |
151 if isinstance(self.bmp, tuple): | |
152 self.log.log("bmp is a tuple, it shouldnt be!", ORPG_INFO) | |
153 self.bmp = wx.ImageFromMime(self.bmp[1], self.bmp[2]).ConvertToBitmap() | |
154 if self.bmp != None and self.bmp.Ok(): | |
155 # check if hidden and GM: we outline the mini in grey (little bit smaller than the actual size) | |
156 # and write the label in the center of the mini | |
157 if self.hide and mini_layer.canvas.frame.session.my_role() == mini_layer.canvas.frame.session.ROLE_GM: | |
158 self.log.log("Enter BmpMiniature->draw->Draw Hidden", ORPG_DEBUG) | |
159 # set the width and height of the image | |
160 if self.width and self.height: | |
161 tmp_image = self.bmp.ConvertToImage() | |
162 tmp_image.Rescale(int(self.width), int(self.height)) | |
163 tmp_image.ConvertAlphaToMask() | |
164 self.bmp = tmp_image.ConvertToBitmap() | |
165 mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) | |
166 self.bmp.SetMask(mask) | |
167 del tmp_image | |
168 del mask | |
169 self.left = 0 | |
170 self.right = self.bmp.GetWidth() | |
171 self.top = 0 | |
172 self.bottom = self.bmp.GetHeight() | |
173 # grey outline | |
174 graypen = wx.Pen("gray", 1, wx.DOT) | |
175 dc.SetPen(graypen) | |
176 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
177 #if width or height < 20 then offset = 1 | |
178 if self.bmp.GetWidth() <= 20: | |
179 xoffset = 1 | |
180 else: | |
181 xoffset = 5 | |
182 if self.bmp.GetHeight() <= 20: | |
183 yoffset = 1 | |
184 else: | |
185 yoffset = 5 | |
186 dc.DrawRectangle(self.pos.x + xoffset, self.pos.y + yoffset, self.bmp.GetWidth() - (xoffset * 2), self.bmp.GetHeight() - (yoffset * 2)) | |
187 dc.SetBrush(wx.NullBrush) | |
188 dc.SetPen(wx.NullPen) | |
189 ## draw label in the center of the mini | |
190 label = mini_layer.get_mini_label(self) | |
191 if len(label): | |
192 dc.SetTextForeground(wx.RED) | |
193 (textWidth,textHeight) = dc.GetTextExtent(label) | |
194 x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 | |
195 y = self.pos.y + (self.bmp.GetHeight() / 2) | |
196 dc.SetPen(wx.GREY_PEN) | |
197 dc.SetBrush(wx.LIGHT_GREY_BRUSH) | |
198 dc.DrawRectangle(x, y, textWidth+2, textHeight+2) | |
199 if (textWidth+2 > self.right): | |
200 self.right += int((textWidth+2-self.right)/2)+1 | |
201 self.left -= int((textWidth+2-self.right)/2)+1 | |
202 self.bottom = y+textHeight+2-self.pos.y | |
203 dc.SetPen(wx.NullPen) | |
204 dc.SetBrush(wx.NullBrush) | |
205 dc.DrawText(label, x+1, y+1) | |
206 | |
207 #selected outline | |
208 if self.selected: | |
209 dc.SetPen(wx.RED_PEN) | |
210 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
211 dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
212 dc.SetBrush(wx.NullBrush) | |
213 dc.SetPen(wx.NullPen) | |
214 self.log.log("Exit BmpMiniature->draw->Draw Hidden", ORPG_DEBUG) | |
215 return True | |
216 elif self.hide: | |
217 self.log.log("Enter/Exit BmpMiniature->draw->Skip Hidden", ORPG_DEBUG) | |
218 return True | |
219 | |
220 else: | |
221 self.log.log("Enter BmpMiniature->draw->Not Hidden", ORPG_DEBUG) | |
222 # set the width and height of the image | |
223 bmp = self.bmp | |
224 if self.width and self.height: | |
225 tmp_image = self.bmp.ConvertToImage() | |
226 tmp_image.Rescale(int(self.width), int(self.height)) | |
227 tmp_image.ConvertAlphaToMask() | |
228 self.bmp = tmp_image.ConvertToBitmap() | |
229 mask = wx.Mask(self.bmp, wx.Colour(tmp_image.GetMaskRed(), tmp_image.GetMaskGreen(), tmp_image.GetMaskBlue())) | |
230 self.bmp.SetMask(mask) | |
231 if self.gray: | |
232 tmp_image = tmp_image.ConvertToGreyscale() | |
233 bmp = tmp_image.ConvertToBitmap() | |
234 else: | |
235 bmp = self.bmp | |
236 dc.DrawBitmap(bmp, self.pos.x, self.pos.y, True) | |
237 self.left = 0 | |
238 self.right = self.bmp.GetWidth() | |
239 self.top = 0 | |
240 self.bottom = self.bmp.GetHeight() | |
241 | |
242 # Draw the facing marker if needed | |
243 if self.face != 0: | |
244 x_mid = self.pos.x + (self.bmp.GetWidth()/2) | |
245 x_right = self.pos.x + self.bmp.GetWidth() | |
246 y_mid = self.pos.y + (self.bmp.GetHeight()/2) | |
247 y_bottom = self.pos.y + self.bmp.GetHeight() | |
248 dc.SetPen(wx.WHITE_PEN) | |
249 dc.SetBrush(wx.RED_BRUSH) | |
250 triangle = [] | |
251 | |
252 # Figure out which direction to draw the marker!! | |
253 if self.face == FACE_WEST: | |
254 triangle.append(cmpPoint(self.pos.x,self.pos.y)) | |
255 triangle.append(cmpPoint(self.pos.x - 5, y_mid)) | |
256 triangle.append(cmpPoint(self.pos.x, y_bottom)) | |
257 elif self.face == FACE_EAST: | |
258 triangle.append(cmpPoint(x_right, self.pos.y)) | |
259 triangle.append(cmpPoint(x_right + 5, y_mid)) | |
260 triangle.append(cmpPoint(x_right, y_bottom)) | |
261 elif self.face == FACE_SOUTH: | |
262 triangle.append(cmpPoint(self.pos.x, y_bottom)) | |
263 triangle.append(cmpPoint(x_mid, y_bottom + 5)) | |
264 triangle.append(cmpPoint(x_right, y_bottom)) | |
265 elif self.face == FACE_NORTH: | |
266 triangle.append(cmpPoint(self.pos.x, self.pos.y)) | |
267 triangle.append(cmpPoint(x_mid, self.pos.y - 5)) | |
268 triangle.append(cmpPoint(x_right, self.pos.y)) | |
269 elif self.face == FACE_NORTHEAST: | |
270 triangle.append(cmpPoint(x_mid, self.pos.y)) | |
271 triangle.append(cmpPoint(x_right + 5, self.pos.y - 5)) | |
272 triangle.append(cmpPoint(x_right, y_mid)) | |
273 triangle.append(cmpPoint(x_right, self.pos.y)) | |
274 elif self.face == FACE_SOUTHEAST: | |
275 triangle.append(cmpPoint(x_right, y_mid)) | |
276 triangle.append(cmpPoint(x_right + 5, y_bottom + 5)) | |
277 triangle.append(cmpPoint(x_mid, y_bottom)) | |
278 triangle.append(cmpPoint(x_right, y_bottom)) | |
279 elif self.face == FACE_SOUTHWEST: | |
280 triangle.append(cmpPoint(x_mid, y_bottom)) | |
281 triangle.append(cmpPoint(self.pos.x - 5, y_bottom + 5)) | |
282 triangle.append(cmpPoint(self.pos.x, y_mid)) | |
283 triangle.append(cmpPoint(self.pos.x, y_bottom)) | |
284 elif self.face == FACE_NORTHWEST: | |
285 triangle.append(cmpPoint(self.pos.x, y_mid)) | |
286 triangle.append(cmpPoint(self.pos.x - 5, self.pos.y - 5)) | |
287 triangle.append(cmpPoint(x_mid, self.pos.y)) | |
288 triangle.append(cmpPoint(self.pos.x, self.pos.y)) | |
289 dc.DrawPolygon(triangle) | |
290 dc.SetBrush(wx.NullBrush) | |
291 dc.SetPen(wx.NullPen) | |
292 | |
293 # Draw the heading if needed | |
294 if self.heading: | |
295 x_adjust = 0 | |
296 y_adjust = 4 | |
297 x_half = self.bmp.GetWidth()/2 | |
298 y_half = self.bmp.GetHeight()/2 | |
299 x_quarter = self.bmp.GetWidth()/4 | |
300 y_quarter = self.bmp.GetHeight()/4 | |
301 x_3quarter = x_quarter*3 | |
302 y_3quarter = y_quarter*3 | |
303 x_full = self.bmp.GetWidth() | |
304 y_full = self.bmp.GetHeight() | |
305 x_center = self.pos.x + x_half | |
306 y_center = self.pos.y + y_half | |
307 # Remember, the pen/brush must be a different color than the | |
308 # facing marker!!!! We'll use black/cyan for starters. | |
309 # Also notice that we will draw the heading on top of the | |
310 # larger facing marker. | |
311 dc.SetPen(wx.BLACK_PEN) | |
312 dc.SetBrush(wx.CYAN_BRUSH) | |
313 triangle = [] | |
314 | |
315 # Figure out which direction to draw the marker!! | |
316 if self.heading == FACE_NORTH: | |
317 triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) | |
318 triangle.append(cmpPoint(x_center, y_center - y_3quarter )) | |
319 triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) | |
320 elif self.heading == FACE_SOUTH: | |
321 triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) | |
322 triangle.append(cmpPoint(x_center, y_center + y_3quarter )) | |
323 triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) | |
324 elif self.heading == FACE_NORTHEAST: | |
325 triangle.append(cmpPoint(x_center + x_quarter, y_center - y_half )) | |
326 triangle.append(cmpPoint(x_center + x_3quarter, y_center - y_3quarter )) | |
327 triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) | |
328 elif self.heading == FACE_EAST: | |
329 triangle.append(cmpPoint(x_center + x_half, y_center - y_quarter )) | |
330 triangle.append(cmpPoint(x_center + x_3quarter, y_center )) | |
331 triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) | |
332 elif self.heading == FACE_SOUTHEAST: | |
333 triangle.append(cmpPoint(x_center + x_half, y_center + y_quarter )) | |
334 triangle.append(cmpPoint(x_center + x_3quarter, y_center + y_3quarter )) | |
335 triangle.append(cmpPoint(x_center + x_quarter, y_center + y_half )) | |
336 elif self.heading == FACE_SOUTHWEST: | |
337 triangle.append(cmpPoint(x_center - x_quarter, y_center + y_half )) | |
338 triangle.append(cmpPoint(x_center - x_3quarter, y_center + y_3quarter )) | |
339 triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) | |
340 elif self.heading == FACE_WEST: | |
341 triangle.append(cmpPoint(x_center - x_half, y_center + y_quarter )) | |
342 triangle.append(cmpPoint(x_center - x_3quarter, y_center )) | |
343 triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) | |
344 elif self.heading == FACE_NORTHWEST: | |
345 triangle.append(cmpPoint(x_center - x_half, y_center - y_quarter )) | |
346 triangle.append(cmpPoint(x_center - x_3quarter, y_center - y_3quarter )) | |
347 triangle.append(cmpPoint(x_center - x_quarter, y_center - y_half )) | |
348 dc.DrawPolygon(triangle) | |
349 dc.SetBrush(wx.NullBrush) | |
350 dc.SetPen(wx.NullPen) | |
351 #selected outline | |
352 if self.selected: | |
353 dc.SetPen(wx.RED_PEN) | |
354 dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
355 dc.DrawRectangle(self.pos.x, self.pos.y, self.bmp.GetWidth(), self.bmp.GetHeight()) | |
356 dc.SetBrush(wx.NullBrush) | |
357 dc.SetPen(wx.NullPen) | |
358 # draw label | |
359 label = mini_layer.get_mini_label(self) | |
360 if len(label): | |
361 dc.SetTextForeground(wx.RED) | |
362 (textWidth,textHeight) = dc.GetTextExtent(label) | |
363 x = self.pos.x +((self.bmp.GetWidth() - textWidth) /2) - 1 | |
364 y = self.pos.y + self.bmp.GetHeight() + 6 | |
365 dc.SetPen(wx.WHITE_PEN) | |
366 dc.SetBrush(wx.WHITE_BRUSH) | |
367 dc.DrawRectangle(x,y,textWidth+2,textHeight+2) | |
368 if (textWidth+2 > self.right): | |
369 self.right += int((textWidth+2-self.right)/2)+1 | |
370 self.left -= int((textWidth+2-self.right)/2)+1 | |
371 self.bottom = y+textHeight+2-self.pos.y | |
372 dc.SetPen(wx.NullPen) | |
373 dc.SetBrush(wx.NullBrush) | |
374 dc.DrawText(label,x+1,y+1) | |
375 self.top-=5 | |
376 self.bottom+=5 | |
377 self.left-=5 | |
378 self.right+=5 | |
379 self.log.log("Exit BmpMiniature->draw->Not Hidden", ORPG_DEBUG) | |
380 return True | |
381 else: | |
382 self.log.log("Exit BmpMiniature->draw(self, dc, mini_layer, op) return False", ORPG_DEBUG) | |
383 return False | |
384 self.log.log("Exit BmpMiniature->draw(self, dc, mini_layer, op)", ORPG_DEBUG) | |
385 | |
386 def toxml(self, action="update"): | |
387 self.log.log("Enter BmpMiniature->toxml(self, " + action + ")", ORPG_DEBUG) | |
388 if action == "del": | |
389 xml_str = "<miniature action='del' id='" + self.id + "'/>" | |
390 self.log.log(xml_str, ORPG_DEBUG) | |
391 self.log.log("Exit BmpMiniature->toxml(self, " + action + ")", ORPG_DEBUG) | |
392 return xml_str | |
393 xml_str = "<miniature" | |
394 xml_str += " action='" + action + "'" | |
395 xml_str += " label='" + self.label + "'" | |
396 xml_str+= " id='" + self.id + "'" | |
397 if self.pos != None: | |
398 xml_str += " posx='" + str(self.pos.x) + "'" | |
399 xml_str += " posy='" + str(self.pos.y) + "'" | |
400 if self.heading != None: | |
401 xml_str += " heading='" + str(self.heading) + "'" | |
402 if self.face != None: | |
403 xml_str += " face='" + str(self.face) + "'" | |
404 if self.path != None: | |
405 xml_str += " path='" + urllib.quote(self.path).replace('%3A', ':') + "'" | |
406 if self.locked: | |
407 xml_str += " locked='1'" | |
408 else: | |
409 xml_str += " locked='0'" | |
410 if self.hide: | |
411 xml_str += " hide='1'" | |
412 else: | |
413 xml_str += " hide='0'" | |
414 if self.snap_to_align != None: | |
415 xml_str += " align='" + str(self.snap_to_align) + "'" | |
416 if self.id != None: | |
417 xml_str += " zorder='" + str(self.zorder) + "'" | |
418 if self.width != None: | |
419 xml_str += " width='" + str(self.width) + "'" | |
420 if self.height != None: | |
421 xml_str += " height='" + str(self.height) + "'" | |
422 if self.local: | |
423 xml_str += ' local="' + str(self.local) + '"' | |
424 xml_str += ' localPath="' + str(urllib.quote(self.localPath).replace('%3A', ':')) + '"' | |
425 xml_str += ' localTime="' + str(self.localTime) + '"' | |
426 xml_str += " />" | |
427 self.log.log(xml_str, ORPG_DEBUG) | |
428 self.log.log("Exit BmpMiniature->toxml(self, " + action + ")", ORPG_DEBUG) | |
429 if (action == "update" and self.isUpdated) or action == "new": | |
430 self.isUpdated = False | |
431 return xml_str | |
432 else: | |
433 return '' | |
434 | |
435 def takedom(self, xml_dom): | |
436 self.log.log("Enter BmpMiniature->takedom(self, xml_dom)", ORPG_DEBUG) | |
437 self.id = xml_dom.getAttribute("id") | |
438 self.log.log("self.id=" + str(self.id), ORPG_DEBUG) | |
439 if xml_dom.hasAttribute("posx"): | |
440 self.pos.x = int(xml_dom.getAttribute("posx")) | |
441 self.log.log("self.pos.x=" + str(self.pos.x), ORPG_DEBUG) | |
442 if xml_dom.hasAttribute("posy"): | |
443 self.pos.y = int(xml_dom.getAttribute("posy")) | |
444 self.log.log("self.pos.y=" + str(self.pos.y), ORPG_DEBUG) | |
445 if xml_dom.hasAttribute("heading"): | |
446 self.heading = int(xml_dom.getAttribute("heading")) | |
447 self.log.log("self.heading=" + str(self.heading), ORPG_DEBUG) | |
448 if xml_dom.hasAttribute("face"): | |
449 self.face = int(xml_dom.getAttribute("face")) | |
450 self.log.log("self.face=" + str(self.face), ORPG_DEBUG) | |
451 if xml_dom.hasAttribute("path"): | |
452 self.path = urllib.unquote(xml_dom.getAttribute("path")) | |
453 self.set_bmp(ImageHandler.load(self.path, 'miniature', self.id)) | |
454 self.log.log("self.path=" + self.path, ORPG_DEBUG) | |
455 if xml_dom.hasAttribute("locked"): | |
456 if xml_dom.getAttribute("locked") == '1' or xml_dom.getAttribute("locked") == 'True': | |
457 self.locked = True | |
458 else: | |
459 self.locked = False | |
460 self.log.log("self.locked=" + str(self.locked), ORPG_DEBUG) | |
461 if xml_dom.hasAttribute("hide"): | |
462 if xml_dom.getAttribute("hide") == '1' or xml_dom.getAttribute("hide") == 'True': | |
463 self.hide = True | |
464 else: | |
465 self.hide = False | |
466 self.log.log("self.hide=" + str(self.hide), ORPG_DEBUG) | |
467 if xml_dom.hasAttribute("label"): | |
468 self.label = xml_dom.getAttribute("label") | |
469 self.log.log("self.label=" + self.label, ORPG_DEBUG) | |
470 if xml_dom.hasAttribute("zorder"): | |
471 self.zorder = int(xml_dom.getAttribute("zorder")) | |
472 self.log.log("self.zorder=" + str(self.zorder), ORPG_DEBUG) | |
473 if xml_dom.hasAttribute("align"): | |
474 if xml_dom.getAttribute("align") == '1' or xml_dom.getAttribute("align") == 'True': | |
475 self.snap_to_align = 1 | |
476 else: | |
477 self.snap_to_align = 0 | |
478 self.log.log("self.snap_to_align=" + str(self.snap_to_align), ORPG_DEBUG) | |
479 if xml_dom.hasAttribute("width"): | |
480 self.width = int(xml_dom.getAttribute("width")) | |
481 self.log.log("self.width=" + str(self.width), ORPG_DEBUG) | |
482 if xml_dom.hasAttribute("height"): | |
483 self.height = int(xml_dom.getAttribute("height")) | |
484 self.log.log("self.height=" + str(self.height), ORPG_DEBUG) | |
485 self.log.log("Exit BmpMiniature->takedom(self, xml_dom)", ORPG_DEBUG) | |
486 | |
487 ##----------------------------- | |
488 ## miniature layer | |
489 ##----------------------------- | |
490 class miniature_layer(layer_base): | |
491 def __init__(self, canvas): | |
492 self.canvas = canvas | |
493 self.log = self.canvas.log | |
494 self.log.log("Enter miniature_layer", ORPG_DEBUG) | |
495 self.settings = self.canvas.settings | |
496 layer_base.__init__(self) | |
497 self.miniatures = [] | |
498 self.serial_number = 0 | |
499 self.log.log("Exit miniature_layer", ORPG_DEBUG) | |
500 | |
501 def next_serial(self): | |
502 self.log.log("Enter miniature_layer->next_serial(self)", ORPG_DEBUG) | |
503 self.serial_number += 1 | |
504 self.log.log("Exit miniature_layer->next_serial(self)", ORPG_DEBUG) | |
505 return self.serial_number | |
506 | |
507 def get_next_highest_z(self): | |
508 self.log.log("Enter miniature_layer->get_next_highest_z(self)", ORPG_DEBUG) | |
509 z = len(self.miniatures)+1 | |
510 self.log.log("Exit miniature_layer->get_next_highest_z(self)", ORPG_DEBUG) | |
511 return z | |
512 | |
513 def cleanly_collapse_zorder(self): | |
514 self.log.log("Enter miniature_layer->cleanly_collapse_zorder(self)", ORPG_DEBUG) | |
515 # lock the zorder stuff | |
516 sorted_miniatures = self.miniatures[:] | |
517 sorted_miniatures.sort(cmp_zorder) | |
518 i = 0 | |
519 for mini in sorted_miniatures: | |
520 mini.zorder = i | |
521 i = i + 1 | |
522 self.log.log("Exit miniature_layer->cleanly_collapse_zorder(self)", ORPG_DEBUG) | |
523 # unlock the zorder stuff | |
524 | |
525 def collapse_zorder(self): | |
526 self.log.log("Enter miniature_layer->collapse_zorder(self)", ORPG_DEBUG) | |
527 # lock the zorder stuff | |
528 sorted_miniatures = self.miniatures[:] | |
529 sorted_miniatures.sort(cmp_zorder) | |
530 i = 0 | |
531 for mini in sorted_miniatures: | |
532 if (mini.zorder != MIN_STICKY_BACK) and (mini.zorder != MIN_STICKY_FRONT): | |
533 mini.zorder = i | |
534 else: | |
535 pass | |
536 i = i + 1 | |
537 self.log.log("Exit miniature_layer->collapse_zorder(self)", ORPG_DEBUG) | |
538 # unlock the zorder stuff | |
539 | |
540 def rollback_serial(self): | |
541 self.log.log("Enter miniature_layer->rollback_serial(self)", ORPG_DEBUG) | |
542 self.serial_number -= 1 | |
543 self.log.log("Exit miniature_layer->rollback_serial(self)", ORPG_DEBUG) | |
544 | |
545 def add_miniature(self, id, path, pos=cmpPoint(0,0), label="", heading=FACE_NONE, face=FACE_NONE, width=0, height=0, local=False, localPath='', localTime=-1): | |
546 self.log.log("Enter miniature_layer->add_miniature(self, id, path, pos, label, heading, face, width, height)", ORPG_DEBUG) | |
547 self.log.log("Before mini creation: " + str(self.get_next_highest_z()), ORPG_DEBUG) | |
548 bmp = ImageHandler.load(path, 'miniature', id) | |
549 if bmp: | |
550 mini = BmpMiniature(id, path, bmp, pos, heading, face, label, zorder=self. get_next_highest_z(), width=width, height=height, log=self.log, local=local, localPath=localPath, localTime=localTime) | |
551 self.log.log("After mini creation:" + str(self.get_next_highest_z()), ORPG_DEBUG) | |
552 self.miniatures.append(mini) | |
553 self.log.log("After mini addition:" + str(self.get_next_highest_z()), ORPG_DEBUG) | |
554 xml_str = "<map><miniatures>" | |
555 xml_str += mini.toxml("new") | |
556 xml_str += "</miniatures></map>" | |
557 self.canvas.frame.session.send(xml_str) | |
558 else: | |
559 self.log.log("Invalid image " + path + " has been ignored!", ORPG_DEBUG) | |
560 self.log.log("Exit miniature_layer->add_miniature(self, id, path, pos, label, heading, face, width, height)", ORPG_DEBUG) | |
561 | |
562 def get_miniature_by_id(self, id): | |
563 self.log.log("Enter miniature_layer->get_miniature_by_id(self, id)", ORPG_DEBUG) | |
564 for mini in self.miniatures: | |
565 if str(mini.id) == str(id): | |
566 self.log.log("Exit miniature_layer->get_miniature_by_id(self, id) return miniID: " + str(id), ORPG_DEBUG) | |
567 return mini | |
568 self.log.log("Exit miniature_layer->get_miniature_by_id(self, id) return None", ORPG_DEBUG) | |
569 return None | |
570 | |
571 def del_miniature(self, min): | |
572 self.log.log("Enter miniature_layer->del_miniature(self, min)", ORPG_DEBUG) | |
573 xml_str = "<map><miniatures>" | |
574 xml_str += min.toxml("del") | |
575 xml_str += "</miniatures></map>" | |
576 self.canvas.frame.session.send(xml_str) | |
577 self.miniatures.remove(min) | |
578 del min | |
579 self.collapse_zorder() | |
580 self.log.log("Exit miniature_layer->del_miniature(self, min)", ORPG_DEBUG) | |
581 | |
582 def del_all_miniatures(self): | |
583 self.log.log("Enter miniature_layer->del_all_miniatures(self)", ORPG_DEBUG) | |
584 while len(self.miniatures): | |
585 min = self.miniatures.pop() | |
586 del min | |
587 self.collapse_zorder() | |
588 self.log.log("Exit miniature_layer->del_all_miniatures(self)", ORPG_DEBUG) | |
589 | |
590 def layerDraw(self, dc, topleft, size): | |
591 self.log.log("Enter miniature_layer->layerDraw(self, dc, topleft, size)", ORPG_DEBUG) | |
592 sorted_miniatures = self.miniatures[:] | |
593 sorted_miniatures.sort(cmp_zorder) | |
594 for m in sorted_miniatures: | |
595 if (m.pos.x>topleft[0]-m.right and | |
596 m.pos.y>topleft[1]-m.bottom and | |
597 m.pos.x<topleft[0]+size[0]-m.left and | |
598 m.pos.y<topleft[1]+size[1]-m.top): | |
599 m.draw(dc, self) | |
600 self.log.log("Exit miniature_layer->layerDraw(self, dc, topleft, size)", ORPG_DEBUG) | |
601 | |
602 def find_miniature(self, pt, only_unlocked=False): | |
603 self.log.log("Enter miniature_layer->find_miniature(self, pt, only_unlocked)", ORPG_DEBUG) | |
604 min_list = [] | |
605 for m in self.miniatures: | |
606 if m.hit_test(pt): | |
607 if m.hide and self.canvas.frame.session.my_role() != self.canvas.frame.session.ROLE_GM: | |
608 continue | |
609 if only_unlocked and not m.locked: | |
610 min_list.append(m) | |
611 elif not only_unlocked and m.locked: | |
612 min_list.append(m) | |
613 else: | |
614 continue | |
615 if len(min_list) > 0: | |
616 self.log.log("Exit miniature_layer->find_miniature(self, pt, only_unlocked)", ORPG_DEBUG) | |
617 return min_list | |
618 else: | |
619 self.log.log("Exit miniature_layer->find_miniature(self, pt, only_unlocked)", ORPG_DEBUG) | |
620 return None | |
621 | |
622 def layerToXML(self, action="update"): | |
623 """ format """ | |
624 self.log.log("Enter miniature_layer->layerToXML(self, " + action + ")", ORPG_DEBUG) | |
625 minis_string = "" | |
626 if self.miniatures: | |
627 for m in self.miniatures: | |
628 minis_string += m.toxml(action) | |
629 if minis_string != '': | |
630 s = "<miniatures" | |
631 s += " serial='" + str(self.serial_number) + "'" | |
632 s += ">" | |
633 s += minis_string | |
634 s += "</miniatures>" | |
635 self.log.log("Exit miniature_layer->layerToXML(self, " + action + ")", ORPG_DEBUG) | |
636 return s | |
637 else: | |
638 self.log.log("Exit miniature_layer->layerToXML(self, " + action + ") return None", ORPG_DEBUG) | |
639 return "" | |
640 | |
641 def layerTakeDOM(self, xml_dom): | |
642 self.log.log("Enter miniature_layer->layerTakeDOM(self, xml_dom)", ORPG_DEBUG) | |
643 if xml_dom.hasAttribute('serial'): | |
644 self.serial_number = int(xml_dom.getAttribute('serial')) | |
645 children = xml_dom._get_childNodes() | |
646 for c in children: | |
647 action = c.getAttribute("action") | |
648 id = c.getAttribute('id') | |
649 if action == "del": | |
650 mini = self.get_miniature_by_id(id) | |
651 if mini: | |
652 self.miniatures.remove(mini) | |
653 del mini | |
654 else: | |
655 self.log.log("Map Synchronization Error :: Update of unknown mini attempted", ORPG_DEBUG) | |
656 #wx.MessageBox("Deletion of unknown mini attempted","Map Synchronization Error") | |
657 elif action == "new": | |
658 pos = cmpPoint(int(c.getAttribute('posx')),int(c.getAttribute('posy'))) | |
659 path = urllib.unquote(c.getAttribute('path')) | |
660 label = c.getAttribute('label') | |
661 height = width = heading = face = snap_to_align = zorder = 0 | |
662 locked = hide = False | |
663 if c.hasAttribute('height'): | |
664 height = int(c.getAttribute('height')) | |
665 if c.hasAttribute('width'): | |
666 width = int(c.getAttribute('width')) | |
667 if c.getAttribute('locked') == 'True' or c.getAttribute('locked') == '1': | |
668 locked = True | |
669 if c.getAttribute('hide') == 'True' or c.getAttribute('hide') == '1': | |
670 hide = True | |
671 if c.getAttribute('heading'): | |
672 heading = int(c.getAttribute('heading')) | |
673 if c.hasAttribute('face'): | |
674 face = int(c.getAttribute('face')) | |
675 if c.hasAttribute('align'): | |
676 snap_to_align = int(c.getAttribute('align')) | |
677 if c.getAttribute('zorder'): | |
678 zorder = int(c.getAttribute('zorder')) | |
679 min = BmpMiniature(id, path, ImageHandler.load(path, 'miniature', id), pos, heading, face, label, locked, hide, snap_to_align, zorder, width, height, self.log) | |
680 self.miniatures.append(min) | |
681 if c.hasAttribute('local') and c.getAttribute('local') == 'True' and os.path.exists(urllib.unquote(c.getAttribute('localPath'))): | |
682 localPath = urllib.unquote(c.getAttribute('localPath')) | |
683 local = True | |
684 localTime = float(c.getAttribute('localTime')) | |
685 if localTime-time.time() <= 144000: | |
686 file = open(localPath, "rb") | |
687 imgdata = file.read() | |
688 file.close() | |
689 filename = os.path.split(localPath) | |
690 (imgtype,j) = mimetypes.guess_type(filename[1]) | |
691 postdata = urllib.urlencode({'filename':filename[1], 'imgdata':imgdata, 'imgtype':imgtype}) | |
692 thread.start_new_thread(self.upload, (postdata, localPath, True)) | |
693 # collapse the zorder. If the client behaved well, then nothing should change. | |
694 # Otherwise, this will ensure that there's some kind of z-order | |
695 self.collapse_zorder() | |
696 else: | |
697 mini = self.get_miniature_by_id(id) | |
698 if mini: | |
699 mini.takedom(c) | |
700 else: | |
701 self.log.log("Map Synchronization Error :: Update of unknown mini attempted", ORPG_DEBUG) | |
702 #wx.MessageBox("Update of unknown mini attempted","Map Synchronization Error") | |
703 self.log.log("Exit miniature_layer->layerTakeDOM(self, xml_dom)", ORPG_DEBUG) | |
704 | |
705 def upload(self, postdata, filename, modify=False, pos=cmpPoint(0,0)): | |
706 self.lock.acquire() | |
707 url = self.settings.get_setting('ImageServerBaseURL') | |
708 file = urllib.urlopen(url, postdata) | |
709 recvdata = file.read() | |
710 file.close() | |
711 try: | |
712 xml_dom = minidom.parseString(recvdata)._get_documentElement() | |
713 if xml_dom.nodeName == 'path': | |
714 path = xml_dom.getAttribute('url') | |
715 path = urllib.unquote(path) | |
716 if not modify: | |
717 start = path.rfind("/") + 1 | |
718 if self.canvas.parent.layer_handlers[2].auto_label: | |
719 min_label = path[start:len(path)-4] | |
720 else: | |
721 min_label = "" | |
722 id = 'mini-' + self.canvas.frame.session.get_next_id() | |
723 self.add_miniature(id, path, pos=pos, label=min_label, local=True, localPath=filename, localTime=time.time()) | |
724 else: | |
725 self.miniatures[len(self.miniatures)-1].local = True | |
726 self.miniatures[len(self.miniatures)-1].localPath = filename | |
727 self.miniatures[len(self.miniatures)-1].localTime = time.time() | |
728 self.miniatures[len(self.miniatures)-1].path = path | |
729 else: | |
730 print xml_dom.getAttribute('msg') | |
731 except Exception, e: | |
732 print e | |
733 print recvdata | |
734 urllib.urlcleanup() | |
735 self.lock.release() | |
736 #################################################################### | |
737 ## helper function | |
738 | |
739 def get_mini_label(self, mini): | |
740 # override this to change the label displayed under each mini (and the label on hidden minis) | |
741 return mini.label |