Mercurial > traipse_dev
comparison orpg/mapper/whiteboard_handler.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 | 78407d627cba |
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/whiteboard_hander.py | |
21 # Author: OpenRPG Team | |
22 # Maintainer: | |
23 # Version: | |
24 # $Id: whiteboard_handler.py,v 1.37 2007/03/09 14:11:56 digitalxero Exp $ | |
25 # | |
26 # Description: Whiteboard layer handler | |
27 # | |
28 __version__ = "$Id: whiteboard_handler.py,v 1.37 2007/03/09 14:11:56 digitalxero Exp $" | |
29 | |
30 from base_handler import * | |
31 from math import floor | |
32 from math import sqrt | |
33 | |
34 class whiteboard_handler(base_layer_handler): | |
35 def __init__(self, parent, id, canvas): | |
36 self.drawing_mode = 'Freeform' | |
37 self.line_string = "0,0;" | |
38 self.drawing = False | |
39 self.upperleft = wx.Point(0,0) | |
40 self.lowerright = wx.Point(0,0) | |
41 #polyline drawing vars | |
42 self.polypoints = 0 | |
43 self.lastpoint = None | |
44 self.selected = None | |
45 #text drawing vars | |
46 self.style = str(wx.NORMAL) | |
47 self.weight = str(wx.NORMAL) | |
48 self.pointsize = str(12) | |
49 self.text_selected_item = None | |
50 #self.r_h = RGBHex() | |
51 base_layer_handler.__init__(self, parent, id, canvas) | |
52 self.build_text_properties_menu() | |
53 self.wb = self.canvas.layers['whiteboard'] | |
54 self.temp_circle = None | |
55 self.cone_start = None | |
56 self.temp_edge1 = None | |
57 self.temp_edge2 = None | |
58 | |
59 def build_ctrls(self): | |
60 base_layer_handler.build_ctrls(self) | |
61 self.color_button = wx.Button(self, wx.ID_ANY, "Pen Color", style=wx.BU_EXACTFIT) | |
62 self.color_button.SetBackgroundColour(wx.BLACK) | |
63 self.color_button.SetForegroundColour(wx.WHITE) | |
64 self.drawmode_ctrl = wx.Choice(self, wx.ID_ANY, choices = ["Freeform", "Polyline","Text", "Cone", "Circle"]) | |
65 self.drawmode_ctrl.SetSelection(0) #always start showing "Freeform" | |
66 self.radius = wx.TextCtrl(self, wx.ID_ANY, size=(32,-1) ) | |
67 self.radius.SetValue("15") | |
68 self.live_refresh = wx.CheckBox(self, wx.ID_ANY, " Live Refresh") | |
69 self.live_refresh.SetValue(True) | |
70 self.widthList= wx.Choice(self, wx.ID_ANY, size= wx.Size(40, 20), choices=['1','2','3','4','5','6','7','8','9','10']) | |
71 self.widthList.SetSelection(0) #always start showing "1" | |
72 self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Line Width: "),0,wx.ALIGN_CENTER) | |
73 self.sizer.Add(self.widthList, 0, wx.EXPAND) | |
74 self.sizer.Add(wx.Size(10,25)) | |
75 self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Drawing Mode: "),0,wx.ALIGN_CENTER) | |
76 self.sizer.Add(self.drawmode_ctrl, 0, wx.EXPAND) | |
77 self.sizer.Add(wx.StaticText(self, -1, " Radius: "), 0, wx.ALIGN_CENTER|wx.ALL, 3) | |
78 self.sizer.Add(self.radius, 0, wx.EXPAND|wx.ALL, 2) | |
79 self.sizer.Add(wx.Size(10,25)) | |
80 self.sizer.Add(self.live_refresh, 0, wx.EXPAND) | |
81 self.sizer.Add(wx.Size(20,25)) | |
82 self.sizer.Add(self.color_button, 0, wx.EXPAND) | |
83 self.sizer.Add(wx.Size(20,25)) | |
84 self.Bind(wx.EVT_MOTION, self.on_motion) | |
85 self.Bind(wx.EVT_CHOICE, self.check_draw_mode, self.drawmode_ctrl) | |
86 self.Bind(wx.EVT_BUTTON, self.on_pen_color, self.color_button) | |
87 self.Bind(wx.EVT_CHOICE, self.on_pen_width, self.widthList) | |
88 | |
89 def build_text_properties_menu(self, label="Text Properties"): | |
90 self.text_properties_dialog = wx.Dialog(self, -1, "Text Properties", name = "Text Properties") | |
91 self.text_props_sizer = wx.BoxSizer(wx.VERTICAL) | |
92 okay_boxer = wx.BoxSizer(wx.HORIZONTAL) | |
93 okay_button = wx.Button(self.text_properties_dialog, wx.ID_OK, "APPLY") | |
94 cancel_button = wx.Button(self.text_properties_dialog, wx.ID_CANCEL,"CANCEL") | |
95 okay_boxer.Add(okay_button, 1, wx.ALIGN_LEFT) | |
96 okay_boxer.Add(wx.Size(10,10)) | |
97 okay_boxer.Add(cancel_button, 1, wx.ALIGN_RIGHT) | |
98 self.txt_boxer = wx.BoxSizer(wx.HORIZONTAL) | |
99 self.txt_static = wx.StaticText(self.text_properties_dialog, -1, "Text: ") | |
100 self.text_control = wx.TextCtrl(self.text_properties_dialog, wx.ID_ANY, "", name = "Text: ") | |
101 self.txt_boxer.Add(self.txt_static,0,wx.EXPAND) | |
102 self.txt_boxer.Add(wx.Size(10,10)) | |
103 self.txt_boxer.Add(self.text_control,1,wx.EXPAND) | |
104 self.point_boxer = wx.BoxSizer(wx.HORIZONTAL) | |
105 self.point_static = wx.StaticText(self.text_properties_dialog, -1, "Text Size: ") | |
106 self.point_control = wx.SpinCtrl(self.text_properties_dialog, wx.ID_ANY, value = "12",min = 1, initial = 12, name = "Font Size: ") | |
107 self.point_boxer.Add(self.point_static,1,wx.EXPAND) | |
108 self.point_boxer.Add(wx.Size(10,10)) | |
109 self.point_boxer.Add(self.point_control,0,wx.EXPAND) | |
110 self.text_color_control = wx.Button(self.text_properties_dialog, wx.ID_ANY, "TEXT COLOR",style=wx.BU_EXACTFIT) | |
111 self.weight_control = wx.RadioBox(self.text_properties_dialog, wx.ID_ANY, "Weight", choices = ["Normal","Bold"]) | |
112 self.style_control = wx.RadioBox(self.text_properties_dialog, wx.ID_ANY, "Style", choices = ["Normal", "Italic"]) | |
113 self.text_props_sizer.Add(self.txt_boxer,0,wx.EXPAND) | |
114 self.text_props_sizer.Add(self.point_boxer,0, wx.EXPAND) | |
115 self.text_props_sizer.Add(self.weight_control,0, wx.EXPAND) | |
116 self.text_props_sizer.Add(self.style_control,0, wx.EXPAND) | |
117 self.text_props_sizer.Add(self.text_color_control, 0, wx.EXPAND) | |
118 self.text_props_sizer.Add(wx.Size(10,10)) | |
119 self.text_props_sizer.Add(okay_boxer,0, wx.EXPAND) | |
120 self.text_props_sizer.Fit(self) | |
121 self.text_properties_dialog.SetSizer(self.text_props_sizer) | |
122 self.text_properties_dialog.Fit() | |
123 self.text_properties_dialog.Bind(wx.EVT_BUTTON, self.on_text_color, self.text_color_control) | |
124 self.text_properties_dialog.Bind(wx.EVT_BUTTON, self.on_text_properties, okay_button) | |
125 #self.text_properties_dialog.Destroy() | |
126 | |
127 def build_menu(self, label = "Whiteboard"): | |
128 base_layer_handler.build_menu(self,label) | |
129 self.main_menu.AppendSeparator() | |
130 item = wx.MenuItem(self.main_menu, wx.ID_ANY, "&Change Pen Color", "Change Pen Color") | |
131 self.canvas.Bind(wx.EVT_MENU, self.on_pen_color, item) | |
132 self.main_menu.AppendItem(item) | |
133 item = wx.MenuItem(self.main_menu, wx.ID_ANY, "Delete &All Lines", "Delete All Lines") | |
134 self.canvas.Bind(wx.EVT_MENU, self.delete_all_lines, item) | |
135 self.main_menu.AppendItem(item) | |
136 item = wx.MenuItem(self.main_menu, wx.ID_ANY, "&Undo Last Deleted Line", "Undo Last Deleted Line") | |
137 self.canvas.Bind(wx.EVT_MENU, self.undo_line, item) | |
138 self.main_menu.AppendItem(item) | |
139 self.line_menu = wx.Menu("Whiteboard Line") | |
140 self.line_menu.SetTitle("Whiteboard Line") | |
141 item = wx.MenuItem(self.line_menu, wx.ID_ANY, "&Remove", "Remove") | |
142 self.canvas.Bind(wx.EVT_MENU, self.on_line_menu_item, item) | |
143 self.line_menu.AppendItem(item) | |
144 self.text_menu = wx.Menu("Whiteboard Text") | |
145 self.text_menu.SetTitle("Whiteboard Text") | |
146 item = wx.MenuItem(self.text_menu, wx.ID_ANY, "&Properties", "Properties") | |
147 self.canvas.Bind(wx.EVT_MENU, self.get_text_properties, item) | |
148 self.text_menu.AppendItem(item) | |
149 item = wx.MenuItem(self.text_menu, wx.ID_ANY, "&Remove", "Remove") | |
150 self.canvas.Bind(wx.EVT_MENU, self.on_text_menu_item, item) | |
151 self.text_menu.AppendItem(item) | |
152 | |
153 def do_line_menu(self,pos): | |
154 self.canvas.PopupMenu(self.line_menu, pos) | |
155 | |
156 def item_selected(self,evt): | |
157 item = evt.GetId() | |
158 self.item_selection = self.selection_list[item] | |
159 | |
160 def on_text_properties(self,evt): | |
161 text_string = self.text_control.GetValue() | |
162 if self.style_control.GetStringSelection() == 'Normal': | |
163 style = wx.NORMAL | |
164 else: | |
165 style = wx.ITALIC | |
166 if self.weight_control.GetStringSelection() == 'Normal': | |
167 weight = wx.NORMAL | |
168 else: | |
169 weight = wx.BOLD | |
170 point = str(self.point_control.GetValue()) | |
171 c = self.text_color_control.GetForegroundColour() | |
172 color = self.canvas.layers['whiteboard'].r_h.hexstring(c.Red(), c.Green(), c.Blue()) | |
173 self.text_selected_item.set_text_props(text_string, style, point, weight, color) | |
174 self.text_to_xml() | |
175 self.text_properties_dialog.Show(False) | |
176 self.text_selected_item.selected = False | |
177 self.text_selected_item.isUpdated = True | |
178 self.text_selected_item = None | |
179 | |
180 def on_text_color(self,evt): | |
181 dlg = wx.ColourDialog(self) | |
182 if dlg.ShowModal() == wx.ID_OK: | |
183 c = dlg.GetColourData() | |
184 self.text_color_control.SetForegroundColour(c.GetColour()) | |
185 dlg.Destroy() | |
186 | |
187 def text_to_xml(self): | |
188 xml_str = "<map><whiteboard>" | |
189 xml_str += self.text_selected_item.toxml('update') | |
190 xml_str += "</whiteboard></map>" | |
191 self.canvas.frame.session.send(xml_str) | |
192 self.canvas.Refresh(False) | |
193 | |
194 def get_text_properties(self, event=None): | |
195 self.text_color_control.SetForegroundColour(self.text_selected_item.textcolor) | |
196 self.text_control.SetValue(self.text_selected_item.text_string) | |
197 self.point_control.SetValue(int(self.text_selected_item.pointsize)) | |
198 if int(self.text_selected_item.weight) == wx.NORMAL: | |
199 self.weight_control.SetSelection(0) | |
200 else: | |
201 self.weight_control.SetSelection(1) | |
202 | |
203 if int(self.text_selected_item.style) == wx.NORMAL: | |
204 self.style_control.SetSelection(0) | |
205 else: | |
206 self.style_control.SetSelection(1) | |
207 self.text_properties_dialog.Center() | |
208 self.text_properties_dialog.Show(True) | |
209 | |
210 def do_text_menu(self, pos, items=None): | |
211 if items == None: | |
212 self.canvas.PopupMenu(self.text_menu) | |
213 else: | |
214 menu = wx.Menu() | |
215 self.ItemList = items | |
216 self.tmpPos = pos | |
217 for i in xrange(len(items)): | |
218 menu.Append(i+1, items[i].text_string) | |
219 self.canvas.Bind(wx.EVT_MENU, self.onItemSelect, id=i+1) | |
220 self.canvas.PopupMenu(menu) | |
221 return | |
222 | |
223 def onItemSelect(self, evt): | |
224 id = evt.GetId()-1 | |
225 self.text_selected_item = self.ItemList[id] | |
226 self.text_selected_item.selected = True | |
227 if self.tmpPos == 'right': | |
228 self.canvas.PopupMenu(self.text_menu) | |
229 self.ItemList = None | |
230 self.tmpPos = None | |
231 | |
232 def on_right_down(self,evt): | |
233 line = 0 | |
234 scale = self.canvas.layers['grid'].mapscale | |
235 dc = wx.ClientDC(self.canvas) | |
236 self.canvas.PrepareDC(dc) | |
237 dc.SetUserScale(scale,scale) | |
238 pos = evt.GetLogicalPosition(dc) | |
239 if self.drawing_mode == 'Text': | |
240 self.on_text_right_down(evt, dc) | |
241 elif self.drawing and ((self.drawing_mode == 'Circle') or (self.drawing_mode == 'Cone')): | |
242 self.check_draw_mode() | |
243 self.drawing = False | |
244 elif (self.drawing_mode == 'Freeform') or (self.drawing_mode == 'Polyline') or (self.drawing_mode == 'Circle') or (self.drawing_mode == 'Cone'): | |
245 line_list = self.canvas.layers['whiteboard'].find_line(pos) | |
246 if line_list: | |
247 self.sel_rline = self.canvas.layers['whiteboard'].get_line_by_id(line_list.id) | |
248 if self.sel_rline: | |
249 self.do_line_menu(evt.GetPosition()) | |
250 self.canvas.Refresh(False) | |
251 else: | |
252 base_layer_handler.on_right_down(self,evt) | |
253 else: | |
254 base_layer_handler.on_right_down(self,evt) | |
255 del dc | |
256 | |
257 def on_pen_color(self,evt): | |
258 data = wx.ColourData() | |
259 data.SetChooseFull(True) | |
260 dlg = wx.ColourDialog(self.canvas, data) | |
261 if dlg.ShowModal() == wx.ID_OK: | |
262 data = dlg.GetColourData() | |
263 color = data.GetColour() | |
264 self.canvas.layers['whiteboard'].setcolor(color) | |
265 self.color_button.SetBackgroundColour(color) | |
266 dlg.Destroy() | |
267 | |
268 def on_pen_width(self,evt): | |
269 width = int(self.widthList.GetStringSelection()) | |
270 self.canvas.layers['whiteboard'].setwidth(width) | |
271 | |
272 def undo_line(self,evt): | |
273 session = self.canvas.frame.session | |
274 if (session.my_role() != session.ROLE_GM) and (session.use_roles()): | |
275 self.top_frame.openrpg.get_component("chat").InfoPost("You must be a GM to use this feature") | |
276 return | |
277 self.canvas.layers['whiteboard'].undo_line() | |
278 dc = self.create_dc() | |
279 self.un_highlight(dc) | |
280 self.selected = None | |
281 del dc | |
282 | |
283 def delete_all_lines(self,evt): | |
284 session = self.canvas.frame.session | |
285 if (session.my_role() != session.ROLE_GM) and (session.use_roles()): | |
286 open_rpg.get_component("chat").InfoPost("You must be a GM to use this feature") | |
287 return | |
288 dlg = wx.MessageDialog(self, "Are you sure you want to delete all lines?","Delete All Lines",wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) | |
289 if dlg.ShowModal() != wx.ID_YES: | |
290 return | |
291 self.canvas.layers['whiteboard'].del_all_lines() | |
292 dc = self.create_dc() | |
293 self.un_highlight(dc) | |
294 self.selected = None | |
295 del dc | |
296 | |
297 def on_line_menu_item(self, evt): | |
298 dc = self.create_dc() | |
299 self.un_highlight(dc) | |
300 self.canvas.layers['whiteboard'].del_line(self.sel_rline) | |
301 self.selected = None | |
302 del dc | |
303 | |
304 def on_text_menu_item(self, evt): | |
305 dc = self.create_dc() | |
306 self.un_highlight(dc) | |
307 self.canvas.layers['whiteboard'].del_text(self.selected) | |
308 self.selected = None | |
309 del dc | |
310 | |
311 # Check Draw Mode | |
312 # Queries the GUI to see what mode to draw in | |
313 # 05-09-2003 Snowdog | |
314 | |
315 def check_draw_mode(self, evt=None): | |
316 self.drawing_mode = self.drawmode_ctrl.GetStringSelection() | |
317 | |
318 #because mode can be changed while a polyline is being created | |
319 #clear the current linestring and reset the polyline data | |
320 self.upperleft.x = self.upperleft.y = 0 | |
321 self.lowerright.x = self.lowerright.y = 0 | |
322 self.lastpoint = None #because the end check function is not called we must force its lastpoint var to None again | |
323 self.polypoints = 0 | |
324 self.line_string = "0,0;" | |
325 if self.temp_circle: | |
326 self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) | |
327 if self.selected == self.temp_circle: | |
328 self.selected = None | |
329 self.canvas.Refresh(True) | |
330 self.temp_circle = None | |
331 self.cone_start = None | |
332 | |
333 # Altered on_left_up to toggle between | |
334 # drawing modes freeform vs polyline | |
335 # 05-09-2003 Snowdog | |
336 def on_left_down(self,evt): | |
337 if not self.drawing: | |
338 self.check_draw_mode() | |
339 if self.drawing_mode == 'Freeform': | |
340 #Freeform mode ignores the inital down click | |
341 pass | |
342 elif self.drawing_mode == 'Polyline': | |
343 self.polyline_add_point( evt ) | |
344 elif self.drawing_mode == 'Text': | |
345 self.on_text_left_down(evt) | |
346 elif self.drawing_mode == 'Cone': | |
347 if self.cone_start == None: | |
348 self.on_start_cone(evt) | |
349 else: | |
350 self.draw_temporary_cone(evt) | |
351 elif self.drawing_mode == 'Circle': | |
352 self.draw_temporary_circle(evt) | |
353 | |
354 # Added handling for double clicks within the map | |
355 # 05-09-2003 Snowdog | |
356 def on_left_dclick(self, evt): | |
357 if self.drawing_mode == 'Freeform': | |
358 #Freeform mode ignores the double click | |
359 pass | |
360 elif self.drawing_mode == 'Polyline': | |
361 self.polyline_last_point( evt ) | |
362 elif self.drawing_mode == 'Text': | |
363 pass | |
364 elif self.drawing_mode == 'Circle' or self.drawing_mode == 'Cone': | |
365 self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) | |
366 #pointArray = self.temp_circle.line_string.split(";") | |
367 self.canvas.layers['whiteboard'].add_line(self.temp_circle.line_string) | |
368 self.temp_circle = None | |
369 self.cone_start = None | |
370 self.drawing = False | |
371 | |
372 # Altered on_left_up to toggle between | |
373 # drawing modes freeform vs polyline | |
374 # 05-09-2003 Snowdog | |
375 def on_left_up(self,evt): | |
376 if self.drawing_mode == 'Freeform': | |
377 self.on_freeform_left_up(evt) | |
378 elif self.drawing_mode == 'Polyline': | |
379 #Polyline mode relies on the down click | |
380 #not the mouse button release | |
381 pass | |
382 elif self.drawing_mode == 'Text': | |
383 pass | |
384 | |
385 # Altered on_left_up to toggle between | |
386 # drawing modes freeform vs polyline | |
387 # 05-09-2003 Snowdog | |
388 def on_motion(self,evt): | |
389 session = self.canvas.frame.session | |
390 if (session.my_role() != session.ROLE_GM) \ | |
391 and (session.my_role()!=session.ROLE_PLAYER) \ | |
392 and (session.use_roles()): | |
393 return | |
394 if self.drawing_mode == 'Freeform': | |
395 if evt.m_leftDown: | |
396 self.freeform_motion(evt) | |
397 elif self.drawing_mode == 'Polyline': | |
398 if self.drawing: | |
399 self.polyline_preview( evt ) | |
400 dc = self.create_dc() | |
401 pos = evt.GetLogicalPosition(dc) | |
402 hit = self.canvas.layers['whiteboard'].hit_test_lines(pos,dc) | |
403 if hit: | |
404 self.highlight(hit,dc) | |
405 else: | |
406 self.un_highlight(dc) | |
407 hit = self.canvas.layers['whiteboard'].hit_test_text(pos,dc) | |
408 if hit: | |
409 self.highlight(hit,dc) | |
410 else: | |
411 self.un_highlight(dc) | |
412 del dc | |
413 | |
414 def create_dc(self): | |
415 scale = self.canvas.layers['grid'].mapscale | |
416 dc = wx.ClientDC( self.canvas ) | |
417 self.canvas.PrepareDC( dc ) | |
418 dc.SetUserScale(scale,scale) | |
419 return dc | |
420 | |
421 def highlight(self,hit,dc): | |
422 if self.selected: | |
423 self.selected.highlight(False) | |
424 self.selected.draw(self.wb,dc) | |
425 self.selected = hit[0] | |
426 self.selected.highlight() | |
427 self.selected.draw(self.wb,dc) | |
428 | |
429 def un_highlight(self,dc): | |
430 if self.selected: | |
431 self.selected.highlight(False) | |
432 self.selected.draw(self.wb,dc) | |
433 | |
434 # Polyline Add Point | |
435 # adds a new point to the polyline | |
436 # 05-09-2003 Snowdog | |
437 def polyline_add_point(self, evt): | |
438 scale = self.canvas.layers['grid'].mapscale | |
439 dc = wx.ClientDC( self.canvas ) | |
440 self.canvas.PrepareDC( dc ) | |
441 dc.SetUserScale(scale,scale) | |
442 pos = evt.GetLogicalPosition(dc) | |
443 #reset the bounding points | |
444 if pos.x < self.upperleft.x: | |
445 self.upperleft.x = pos.x | |
446 elif pos.x > self.lowerright.x: | |
447 self.lowerright.x = pos.x | |
448 if pos.y < self.upperleft.y: | |
449 self.upperleft.y = pos.y | |
450 elif pos.y > self.lowerright.y: | |
451 self.lowerright.y = pos.y | |
452 | |
453 #if this point doens't end the line | |
454 #add a new point into the line string | |
455 if not self.polyline_end_check( pos ): | |
456 if self.drawing == True: | |
457 self.polypoints += 1 #add one to the point counter. | |
458 self.line_string += `pos.x` + "," + `pos.y` + ";" | |
459 self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) | |
460 else: #start of line... | |
461 self.polypoints += 1 #add one to the point counter. | |
462 self.line_string = `pos.x` + "," + `pos.y` + ";" | |
463 self.upperleft.x = pos.x | |
464 self.upperleft.y = pos.y | |
465 self.lowerright.x = pos.x | |
466 self.lowerright.y = pos.y | |
467 self.drawing = True | |
468 else: #end of line. Send and reset vars for next line | |
469 self.drawing = False | |
470 if self.polypoints < 2: | |
471 #not enough points to form a line. Ignore line | |
472 pass | |
473 else: | |
474 #have enough points to create valid line | |
475 #check to role to make sure user can draw at all.... | |
476 session = self.canvas.frame.session | |
477 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
478 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
479 self.canvas.Refresh(False) | |
480 else: | |
481 #user allowed to draw on whiteboard.. send polyline | |
482 line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) | |
483 #resetting variables for next line | |
484 self.upperleft.x = self.upperleft.y = 0 | |
485 self.lowerright.x = self.lowerright.y = 0 | |
486 self.polypoints = 0 | |
487 self.line_string = "0,0;" | |
488 | |
489 # Polyline Last Point | |
490 # adds a final point to the polyline and ends it | |
491 # 05-09-2003 Snowdog | |
492 def polyline_last_point(self, evt): | |
493 #if we haven't started a line already. Ignore the click | |
494 if self.drawing != True: | |
495 return | |
496 scale = self.canvas.layers['grid'].mapscale | |
497 dc = wx.ClientDC( self.canvas ) | |
498 self.canvas.PrepareDC( dc ) | |
499 dc.SetUserScale(scale,scale) | |
500 pos = evt.GetLogicalPosition(dc) | |
501 #reset the bounding points | |
502 if pos.x < self.upperleft.x: | |
503 self.upperleft.x = pos.x | |
504 elif pos.x > self.lowerright.x: | |
505 self.lowerright.x = pos.x | |
506 if pos.y < self.upperleft.y: | |
507 self.upperleft.y = pos.y | |
508 elif pos.y > self.lowerright.y: | |
509 self.lowerright.y = pos.y | |
510 self.polypoints += 1 #add one to the point counter. | |
511 self.line_string += `pos.x` + "," + `pos.y` + ";" | |
512 self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) | |
513 #end of line. Send and reset vars for next line | |
514 self.drawing = False | |
515 if self.polypoints < 2: | |
516 #not enough points to form a line. Ignore line | |
517 pass | |
518 else: | |
519 #have enough points to create valid line | |
520 #check to role to make sure user can draw at all.... | |
521 session = self.canvas.frame.session | |
522 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
523 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
524 self.canvas.Refresh(False) | |
525 else: | |
526 #user allowed to draw on whiteboard.. send polyline | |
527 line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) | |
528 #resetting variables for next line | |
529 self.upperleft.x = self.upperleft.y = 0 | |
530 self.lowerright.x = self.lowerright.y = 0 | |
531 self.lastpoint = None #becuase the end check function is not called we must force its lastpoint var to None again | |
532 self.polypoints = 0 | |
533 self.line_string = "0,0;" | |
534 | |
535 # Polyline End Check | |
536 # checks to see if a double click has occured | |
537 # a second click on the LAST polyline point | |
538 # (or very close proximity) should cause the | |
539 # polyline even to complete and send | |
540 # 05-09-2003 Snowdog | |
541 def polyline_end_check(self, pos): | |
542 # check to see if the position of the give point is within POLYLINE_END_TOLERANCE | |
543 # if it is then the line has been completed and should be sent to the map just like | |
544 # the original freeform version is. A line with fewer than 2 points should be ignored | |
545 x_in = y_in = 0 | |
546 tol = 5 | |
547 | |
548 #first point check | |
549 if type(self.lastpoint) == type(None): | |
550 self.lastpoint = wx.Point(pos.x,pos.y) | |
551 return 0 #not end of line | |
552 if ((self.lastpoint.x -tol) <= pos.x <= (self.lastpoint.x)): | |
553 x_in = 1 | |
554 if ((self.lastpoint.y -tol) <= pos.y <= (self.lastpoint.y)): | |
555 y_in = 1 | |
556 if x_in and y_in: | |
557 #point within tolerance. End line | |
558 self.lastpoint = None | |
559 return 1 | |
560 #if we've reached here the point is NOT a terminal point. Reset the lastpoint and return False | |
561 self.lastpoint.x = pos.x | |
562 self.lastpoint.y = pos.y | |
563 return 0 | |
564 | |
565 # Polyline Preview | |
566 # display a temporary/momentary line to the user | |
567 # from the last point to mouse position | |
568 # 05-09-2003 Snowdog | |
569 def polyline_preview(self, evt): | |
570 if self.drawing != True: | |
571 #not enough points to form a line. Ignore line | |
572 return | |
573 if self.live_refresh.GetValue() == 0: | |
574 #not using live redraw | |
575 return | |
576 scale = self.canvas.layers['grid'].mapscale | |
577 dc = wx.ClientDC( self.canvas ) | |
578 self.canvas.PrepareDC( dc ) | |
579 dc.SetUserScale(scale,scale) | |
580 pos = evt.GetLogicalPosition(dc) | |
581 | |
582 #reset the bounding points | |
583 if pos.x < self.upperleft.x: | |
584 self.upperleft.x = pos.x | |
585 elif pos.x > self.lowerright.x: | |
586 self.lowerright.x = pos.x | |
587 if pos.y < self.upperleft.y: | |
588 self.upperleft.y = pos.y | |
589 elif pos.y > self.lowerright.y: | |
590 self.lowerright.y = pos.y | |
591 | |
592 #redraw the line with a line connected to the cursor | |
593 temp_string = self.line_string | |
594 temp_string += `pos.x` + "," + `pos.y` + ";" | |
595 self.canvas.layers['whiteboard'].draw_working_line(dc,temp_string) | |
596 self.canvas.Refresh(True) | |
597 | |
598 # moved original on_motion to this function | |
599 # to allow alternate drawing method to be used | |
600 # 05-09-2003 Snowdog | |
601 def freeform_motion(self, evt): | |
602 # if not self.drawing: | |
603 # return | |
604 scale = self.canvas.layers['grid'].mapscale | |
605 dc = wx.ClientDC( self.canvas ) | |
606 self.canvas.PrepareDC( dc ) | |
607 dc.SetUserScale(scale,scale) | |
608 pos = evt.GetLogicalPosition(dc) | |
609 if pos.x < self.upperleft.x: | |
610 self.upperleft.x = pos.x | |
611 elif pos.x > self.lowerright.x: | |
612 self.lowerright.x = pos.x | |
613 if pos.y < self.upperleft.y: | |
614 self.upperleft.y = pos.y | |
615 elif pos.y > self.lowerright.y: | |
616 self.lowerright.y = pos.y | |
617 if evt.m_leftDown: | |
618 if self.drawing == True: | |
619 self.line_string += `pos.x` + "," + `pos.y` + ";" | |
620 self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) | |
621 else: | |
622 self.line_string = `pos.x` + "," + `pos.y` + ";" | |
623 self.upperleft.x = pos.x | |
624 self.upperleft.y = pos.y | |
625 self.lowerright.x = pos.x | |
626 self.lowerright.y = pos.y | |
627 self.drawing = True | |
628 del dc | |
629 | |
630 # moved original on_left_up to this function | |
631 # to allow alternate drawing method to be used | |
632 # 05-09-2003 Snowdog | |
633 def on_freeform_left_up(self,evt): | |
634 if self.drawing == True: | |
635 self.drawing = False | |
636 session = self.canvas.frame.session | |
637 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
638 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
639 self.canvas.Refresh(False) | |
640 return | |
641 #self.id +=1 | |
642 line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) | |
643 dc = self.create_dc() | |
644 for m in range(30): | |
645 line.highlight() | |
646 line.draw(self.wb,dc) | |
647 line.highlight(False) | |
648 line.draw(self.wb,dc) | |
649 del dc | |
650 self.upperleft.x = self.upperleft.y = 0 | |
651 self.lowerright.x = self.lowerright.y = 0 | |
652 | |
653 def on_text_left_down(self, evt): | |
654 session = self.canvas.frame.session | |
655 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
656 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
657 self.canvas.Refresh(False) | |
658 return | |
659 scale = self.canvas.layers['grid'].mapscale | |
660 dc = wx.ClientDC( self.canvas ) | |
661 self.canvas.PrepareDC( dc ) | |
662 dc.SetUserScale(scale,scale) | |
663 pos = evt.GetLogicalPosition(dc) | |
664 test_text = self.canvas.layers['whiteboard'].hit_test_text(pos,dc) | |
665 if len(test_text) > 0: | |
666 if len(test_text) > 1: | |
667 self.do_text_menu('left', test_text) | |
668 else: | |
669 self.text_selected_item = test_text[0] | |
670 self.text_selected_item.selected = True | |
671 self.canvas.Refresh(True) | |
672 else: | |
673 if self.text_selected_item == None: | |
674 dlg = wx.TextEntryDialog(self,"Text to add to whiteboard", caption="Enter text",defaultValue=" ") | |
675 if dlg.ShowModal() == wx.ID_OK: | |
676 text_string = dlg.GetValue() | |
677 self.canvas.layers['whiteboard'].add_text(text_string,pos, self.style, self.pointsize, self.weight, self.canvas.layers['whiteboard'].color) | |
678 else: | |
679 self.text_selected_item.posx = pos.x | |
680 self.text_selected_item.posy = pos.y | |
681 self.text_selected_item.isUpdated = True | |
682 self.text_to_xml() | |
683 self.text_selected_item.selected = False | |
684 self.text_selected_item = None | |
685 del dc | |
686 | |
687 def on_text_right_down(self, evt, dc): | |
688 session = self.canvas.frame.session | |
689 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
690 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
691 self.canvas.Refresh(False) | |
692 return | |
693 pos = evt.GetLogicalPosition(dc) | |
694 test_text = self.canvas.layers['whiteboard'].hit_test_text(pos, dc) | |
695 if len(test_text) > 0: | |
696 if len(test_text) > 1: | |
697 self.do_text_menu('right', test_text) | |
698 else: | |
699 self.text_selected_item = test_text[0] | |
700 self.do_text_menu('right') | |
701 | |
702 def on_start_cone(self, evt): | |
703 session = self.canvas.frame.session | |
704 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
705 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
706 self.canvas.Refresh(False) | |
707 return | |
708 self.cone_start = self.get_snapped_to_logical_pos(evt) | |
709 self.drawing = True | |
710 | |
711 def get_snapped_to_logical_pos(self, evt): | |
712 scale = self.canvas.layers['grid'].mapscale | |
713 dc = wx.ClientDC( self.canvas ) | |
714 self.canvas.PrepareDC( dc ) | |
715 dc.SetUserScale(scale,scale) | |
716 pos = evt.GetLogicalPosition(dc) | |
717 if self.canvas.layers['grid'].snap: | |
718 size = self.canvas.layers['grid'].unit_size | |
719 pos.x = int((pos.x+size/2)/size)*size | |
720 pos.y = int((pos.y+size/2)/size)*size | |
721 return pos | |
722 | |
723 def draw_temporary_cone(self, evt): | |
724 scale = self.canvas.layers['grid'].mapscale | |
725 dc = wx.ClientDC( self.canvas ) | |
726 self.canvas.PrepareDC( dc ) | |
727 dc.SetUserScale(scale,scale) | |
728 pos = evt.GetLogicalPosition(dc) | |
729 pos2 = self.get_snapped_to_logical_pos(evt) | |
730 size = self.canvas.layers['grid'].unit_size #60 | |
731 if abs(pos.x-pos2.x)<=size/10 and abs(pos.y-pos2.y)<=size/10: | |
732 pos = pos2 | |
733 radius = int(int(self.radius.GetValue())/5) | |
734 curve = self.calculate_circle(self.cone_start, radius, size) | |
735 edge1 = [] | |
736 edge2 = [] | |
737 horizontal_inc = wx.Point(size,0) | |
738 if pos.x <= self.cone_start.x: | |
739 horizontal_inc = wx.Point(-size,0) | |
740 vertical_inc = wx.Point(0,size) | |
741 if pos.y <= self.cone_start.y: | |
742 vertical_inc = wx.Point(0,-size) | |
743 x_diff = float(pos.x - self.cone_start.x) | |
744 y_diff = float(pos.y - self.cone_start.y) | |
745 ratio = float(1) | |
746 if abs(x_diff) <= abs(y_diff): | |
747 ratio = x_diff / y_diff | |
748 elif abs(y_diff) < abs(x_diff): | |
749 ratio = -(y_diff / x_diff) | |
750 horizontal_inc,vertical_inc = vertical_inc,horizontal_inc #swap | |
751 horizontal_rotated = wx.Point(-horizontal_inc.y, horizontal_inc.x) | |
752 vertical_rotated = wx.Point(-vertical_inc.y, vertical_inc.x) | |
753 on_diagonal = True | |
754 for v in range(radius): | |
755 x = int(floor((v+1)*ratio)) - int(floor(v*ratio)) | |
756 if x < 0 and on_diagonal: | |
757 edge1 += [vertical_inc] | |
758 edge1 += [horizontal_inc] | |
759 elif x != 0: | |
760 edge1 += [horizontal_inc] | |
761 edge1 += [vertical_inc] | |
762 else: | |
763 edge1 += [vertical_inc] | |
764 on_diagonal = False | |
765 on_diagonal = True | |
766 for v in range(radius): | |
767 x = int(floor((v+1)*(-ratio))) - int(floor(v*(-ratio))) | |
768 if x < 0 and on_diagonal: | |
769 edge2 += [vertical_rotated] | |
770 edge2 += [horizontal_rotated] | |
771 elif x != 0: | |
772 edge2 += [horizontal_rotated] | |
773 edge2 += [vertical_rotated] | |
774 else: | |
775 edge2 += [vertical_rotated] | |
776 on_diagonal = False | |
777 p = wx.Point(0,0) | |
778 string1 = self.point_to_string(p, [self.cone_start]) | |
779 string1 += self.point_to_string(p, edge1) | |
780 p = wx.Point(0,0) | |
781 string2 = self.point_to_string(p, [self.cone_start]) | |
782 string2 += self.point_to_string(p, edge2) | |
783 | |
784 # truncate the edges where they meet the curve | |
785 pointArray = string1.split(";") | |
786 string1 = "" | |
787 for p in pointArray: | |
788 p += ";" | |
789 index = (";"+curve).find(";"+p) | |
790 if index >= 0: | |
791 # found intersection, start circle at intersection | |
792 curve = curve[index:]+curve[:index] | |
793 break | |
794 string1 += p | |
795 | |
796 # truncate the edges where they meet the curve | |
797 pointArray = string2.split(";") | |
798 string2 = "" | |
799 for p in pointArray: | |
800 p += ";" | |
801 string2 = p + string2 #backwards | |
802 index = (";"+curve).find(";"+p) | |
803 if index >= 0: | |
804 # found intersection, end circle at intersection | |
805 curve = curve[:index] | |
806 break | |
807 curve = string1 + curve + string2 | |
808 | |
809 # add the lines that define the real cone edges | |
810 sz = sqrt(x_diff*x_diff + y_diff*y_diff) | |
811 x_diff = radius*size*x_diff/sz | |
812 y_diff = radius*size*y_diff/sz | |
813 pos = wx.Point(self.cone_start.x+x_diff, self.cone_start.y+y_diff) | |
814 qos = wx.Point(self.cone_start.x-y_diff, self.cone_start.y+x_diff)# 90 degree rotation | |
815 curve = `pos.x`+","+`pos.y`+";" + curve + `qos.x`+","+`qos.y`+";" | |
816 if(self.temp_circle): | |
817 self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) | |
818 if self.selected == self.temp_circle: | |
819 self.selected = None | |
820 self.temp_circle = self.canvas.layers['whiteboard'].add_temp_line(curve) | |
821 self.canvas.Refresh(True) | |
822 | |
823 def draw_temporary_circle(self, evt): | |
824 session = self.canvas.frame.session | |
825 if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): | |
826 open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") | |
827 self.canvas.Refresh(False) | |
828 return | |
829 pos = self.get_snapped_to_logical_pos(evt) | |
830 size = self.canvas.layers['grid'].unit_size #60 | |
831 radius = int(int(self.radius.GetValue())/5) | |
832 center = wx.Point(pos.x, pos.y+size*radius) | |
833 curve = self.calculate_circle(center, radius, size) | |
834 if(self.temp_circle): | |
835 self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) | |
836 self.selected = None | |
837 self.temp_circle = self.canvas.layers['whiteboard'].add_temp_line(curve) | |
838 self.drawing = True | |
839 self.canvas.Refresh(True) | |
840 | |
841 def calculate_circle(self, center, radius, size): | |
842 pos = wx.Point(center.x, center.y-size*radius) | |
843 r = int(radius+2/3) | |
844 right = wx.Point(size,0) | |
845 left = wx.Point(-size,0) | |
846 up = wx.Point(0,-size) | |
847 down = wx.Point(0,size) | |
848 v1 = ([right, down, right]*r)[:radius] | |
849 v2 = ([down, right, down]*r)[r*3-radius:] | |
850 v3 = ([down, left, down]*r)[:radius] | |
851 v4 = ([left, down, left]*r)[r*3-radius:] | |
852 v5 = ([left, up, left]*r)[:radius] | |
853 v6 = ([up, left, up]*r)[r*3-radius:] | |
854 v7 = ([up, right, up]*r)[:radius] | |
855 v8 = ([right, up, right]*r)[r*3-radius:] | |
856 p = wx.Point(0,0) | |
857 temp_string = self.point_to_string(p, [pos]) | |
858 temp_string += self.point_to_string(p, v1+v2+v3+v4+v5+v6+v7+v8) | |
859 return temp_string | |
860 | |
861 def point_to_string(self, pos, vec): | |
862 str = "" | |
863 for i in range(len(vec)): | |
864 pos.x = pos.x + vec[i].x | |
865 pos.y = pos.y + vec[i].y | |
866 str += `pos.x` + "," + `pos.y` + ";" | |
867 return str | |
868 |