Mercurial > traipse_dev
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/orpg/mapper/whiteboard_handler.py Tue Jul 14 16:41:58 2009 -0500 @@ -0,0 +1,868 @@ +# Copyright (C) 2000-2001 The OpenRPG Project +# +# openrpg-dev@lists.sourceforge.net +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# -- +# +# File: mapper/whiteboard_hander.py +# Author: OpenRPG Team +# Maintainer: +# Version: +# $Id: whiteboard_handler.py,v 1.37 2007/03/09 14:11:56 digitalxero Exp $ +# +# Description: Whiteboard layer handler +# +__version__ = "$Id: whiteboard_handler.py,v 1.37 2007/03/09 14:11:56 digitalxero Exp $" + +from base_handler import * +from math import floor +from math import sqrt + +class whiteboard_handler(base_layer_handler): + def __init__(self, parent, id, canvas): + self.drawing_mode = 'Freeform' + self.line_string = "0,0;" + self.drawing = False + self.upperleft = wx.Point(0,0) + self.lowerright = wx.Point(0,0) + #polyline drawing vars + self.polypoints = 0 + self.lastpoint = None + self.selected = None + #text drawing vars + self.style = str(wx.NORMAL) + self.weight = str(wx.NORMAL) + self.pointsize = str(12) + self.text_selected_item = None + #self.r_h = RGBHex() + base_layer_handler.__init__(self, parent, id, canvas) + self.build_text_properties_menu() + self.wb = self.canvas.layers['whiteboard'] + self.temp_circle = None + self.cone_start = None + self.temp_edge1 = None + self.temp_edge2 = None + + def build_ctrls(self): + base_layer_handler.build_ctrls(self) + self.color_button = wx.Button(self, wx.ID_ANY, "Pen Color", style=wx.BU_EXACTFIT) + self.color_button.SetBackgroundColour(wx.BLACK) + self.color_button.SetForegroundColour(wx.WHITE) + self.drawmode_ctrl = wx.Choice(self, wx.ID_ANY, choices = ["Freeform", "Polyline","Text", "Cone", "Circle"]) + self.drawmode_ctrl.SetSelection(0) #always start showing "Freeform" + self.radius = wx.TextCtrl(self, wx.ID_ANY, size=(32,-1) ) + self.radius.SetValue("15") + self.live_refresh = wx.CheckBox(self, wx.ID_ANY, " Live Refresh") + self.live_refresh.SetValue(True) + self.widthList= wx.Choice(self, wx.ID_ANY, size= wx.Size(40, 20), choices=['1','2','3','4','5','6','7','8','9','10']) + self.widthList.SetSelection(0) #always start showing "1" + self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Line Width: "),0,wx.ALIGN_CENTER) + self.sizer.Add(self.widthList, 0, wx.EXPAND) + self.sizer.Add(wx.Size(10,25)) + self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Drawing Mode: "),0,wx.ALIGN_CENTER) + self.sizer.Add(self.drawmode_ctrl, 0, wx.EXPAND) + self.sizer.Add(wx.StaticText(self, -1, " Radius: "), 0, wx.ALIGN_CENTER|wx.ALL, 3) + self.sizer.Add(self.radius, 0, wx.EXPAND|wx.ALL, 2) + self.sizer.Add(wx.Size(10,25)) + self.sizer.Add(self.live_refresh, 0, wx.EXPAND) + self.sizer.Add(wx.Size(20,25)) + self.sizer.Add(self.color_button, 0, wx.EXPAND) + self.sizer.Add(wx.Size(20,25)) + self.Bind(wx.EVT_MOTION, self.on_motion) + self.Bind(wx.EVT_CHOICE, self.check_draw_mode, self.drawmode_ctrl) + self.Bind(wx.EVT_BUTTON, self.on_pen_color, self.color_button) + self.Bind(wx.EVT_CHOICE, self.on_pen_width, self.widthList) + + def build_text_properties_menu(self, label="Text Properties"): + self.text_properties_dialog = wx.Dialog(self, -1, "Text Properties", name = "Text Properties") + self.text_props_sizer = wx.BoxSizer(wx.VERTICAL) + okay_boxer = wx.BoxSizer(wx.HORIZONTAL) + okay_button = wx.Button(self.text_properties_dialog, wx.ID_OK, "APPLY") + cancel_button = wx.Button(self.text_properties_dialog, wx.ID_CANCEL,"CANCEL") + okay_boxer.Add(okay_button, 1, wx.ALIGN_LEFT) + okay_boxer.Add(wx.Size(10,10)) + okay_boxer.Add(cancel_button, 1, wx.ALIGN_RIGHT) + self.txt_boxer = wx.BoxSizer(wx.HORIZONTAL) + self.txt_static = wx.StaticText(self.text_properties_dialog, -1, "Text: ") + self.text_control = wx.TextCtrl(self.text_properties_dialog, wx.ID_ANY, "", name = "Text: ") + self.txt_boxer.Add(self.txt_static,0,wx.EXPAND) + self.txt_boxer.Add(wx.Size(10,10)) + self.txt_boxer.Add(self.text_control,1,wx.EXPAND) + self.point_boxer = wx.BoxSizer(wx.HORIZONTAL) + self.point_static = wx.StaticText(self.text_properties_dialog, -1, "Text Size: ") + self.point_control = wx.SpinCtrl(self.text_properties_dialog, wx.ID_ANY, value = "12",min = 1, initial = 12, name = "Font Size: ") + self.point_boxer.Add(self.point_static,1,wx.EXPAND) + self.point_boxer.Add(wx.Size(10,10)) + self.point_boxer.Add(self.point_control,0,wx.EXPAND) + self.text_color_control = wx.Button(self.text_properties_dialog, wx.ID_ANY, "TEXT COLOR",style=wx.BU_EXACTFIT) + self.weight_control = wx.RadioBox(self.text_properties_dialog, wx.ID_ANY, "Weight", choices = ["Normal","Bold"]) + self.style_control = wx.RadioBox(self.text_properties_dialog, wx.ID_ANY, "Style", choices = ["Normal", "Italic"]) + self.text_props_sizer.Add(self.txt_boxer,0,wx.EXPAND) + self.text_props_sizer.Add(self.point_boxer,0, wx.EXPAND) + self.text_props_sizer.Add(self.weight_control,0, wx.EXPAND) + self.text_props_sizer.Add(self.style_control,0, wx.EXPAND) + self.text_props_sizer.Add(self.text_color_control, 0, wx.EXPAND) + self.text_props_sizer.Add(wx.Size(10,10)) + self.text_props_sizer.Add(okay_boxer,0, wx.EXPAND) + self.text_props_sizer.Fit(self) + self.text_properties_dialog.SetSizer(self.text_props_sizer) + self.text_properties_dialog.Fit() + self.text_properties_dialog.Bind(wx.EVT_BUTTON, self.on_text_color, self.text_color_control) + self.text_properties_dialog.Bind(wx.EVT_BUTTON, self.on_text_properties, okay_button) + #self.text_properties_dialog.Destroy() + + def build_menu(self, label = "Whiteboard"): + base_layer_handler.build_menu(self,label) + self.main_menu.AppendSeparator() + item = wx.MenuItem(self.main_menu, wx.ID_ANY, "&Change Pen Color", "Change Pen Color") + self.canvas.Bind(wx.EVT_MENU, self.on_pen_color, item) + self.main_menu.AppendItem(item) + item = wx.MenuItem(self.main_menu, wx.ID_ANY, "Delete &All Lines", "Delete All Lines") + self.canvas.Bind(wx.EVT_MENU, self.delete_all_lines, item) + self.main_menu.AppendItem(item) + item = wx.MenuItem(self.main_menu, wx.ID_ANY, "&Undo Last Deleted Line", "Undo Last Deleted Line") + self.canvas.Bind(wx.EVT_MENU, self.undo_line, item) + self.main_menu.AppendItem(item) + self.line_menu = wx.Menu("Whiteboard Line") + self.line_menu.SetTitle("Whiteboard Line") + item = wx.MenuItem(self.line_menu, wx.ID_ANY, "&Remove", "Remove") + self.canvas.Bind(wx.EVT_MENU, self.on_line_menu_item, item) + self.line_menu.AppendItem(item) + self.text_menu = wx.Menu("Whiteboard Text") + self.text_menu.SetTitle("Whiteboard Text") + item = wx.MenuItem(self.text_menu, wx.ID_ANY, "&Properties", "Properties") + self.canvas.Bind(wx.EVT_MENU, self.get_text_properties, item) + self.text_menu.AppendItem(item) + item = wx.MenuItem(self.text_menu, wx.ID_ANY, "&Remove", "Remove") + self.canvas.Bind(wx.EVT_MENU, self.on_text_menu_item, item) + self.text_menu.AppendItem(item) + + def do_line_menu(self,pos): + self.canvas.PopupMenu(self.line_menu, pos) + + def item_selected(self,evt): + item = evt.GetId() + self.item_selection = self.selection_list[item] + + def on_text_properties(self,evt): + text_string = self.text_control.GetValue() + if self.style_control.GetStringSelection() == 'Normal': + style = wx.NORMAL + else: + style = wx.ITALIC + if self.weight_control.GetStringSelection() == 'Normal': + weight = wx.NORMAL + else: + weight = wx.BOLD + point = str(self.point_control.GetValue()) + c = self.text_color_control.GetForegroundColour() + color = self.canvas.layers['whiteboard'].r_h.hexstring(c.Red(), c.Green(), c.Blue()) + self.text_selected_item.set_text_props(text_string, style, point, weight, color) + self.text_to_xml() + self.text_properties_dialog.Show(False) + self.text_selected_item.selected = False + self.text_selected_item.isUpdated = True + self.text_selected_item = None + + def on_text_color(self,evt): + dlg = wx.ColourDialog(self) + if dlg.ShowModal() == wx.ID_OK: + c = dlg.GetColourData() + self.text_color_control.SetForegroundColour(c.GetColour()) + dlg.Destroy() + + def text_to_xml(self): + xml_str = "<map><whiteboard>" + xml_str += self.text_selected_item.toxml('update') + xml_str += "</whiteboard></map>" + self.canvas.frame.session.send(xml_str) + self.canvas.Refresh(False) + + def get_text_properties(self, event=None): + self.text_color_control.SetForegroundColour(self.text_selected_item.textcolor) + self.text_control.SetValue(self.text_selected_item.text_string) + self.point_control.SetValue(int(self.text_selected_item.pointsize)) + if int(self.text_selected_item.weight) == wx.NORMAL: + self.weight_control.SetSelection(0) + else: + self.weight_control.SetSelection(1) + + if int(self.text_selected_item.style) == wx.NORMAL: + self.style_control.SetSelection(0) + else: + self.style_control.SetSelection(1) + self.text_properties_dialog.Center() + self.text_properties_dialog.Show(True) + + def do_text_menu(self, pos, items=None): + if items == None: + self.canvas.PopupMenu(self.text_menu) + else: + menu = wx.Menu() + self.ItemList = items + self.tmpPos = pos + for i in xrange(len(items)): + menu.Append(i+1, items[i].text_string) + self.canvas.Bind(wx.EVT_MENU, self.onItemSelect, id=i+1) + self.canvas.PopupMenu(menu) + return + + def onItemSelect(self, evt): + id = evt.GetId()-1 + self.text_selected_item = self.ItemList[id] + self.text_selected_item.selected = True + if self.tmpPos == 'right': + self.canvas.PopupMenu(self.text_menu) + self.ItemList = None + self.tmpPos = None + + def on_right_down(self,evt): + line = 0 + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC(self.canvas) + self.canvas.PrepareDC(dc) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + if self.drawing_mode == 'Text': + self.on_text_right_down(evt, dc) + elif self.drawing and ((self.drawing_mode == 'Circle') or (self.drawing_mode == 'Cone')): + self.check_draw_mode() + self.drawing = False + elif (self.drawing_mode == 'Freeform') or (self.drawing_mode == 'Polyline') or (self.drawing_mode == 'Circle') or (self.drawing_mode == 'Cone'): + line_list = self.canvas.layers['whiteboard'].find_line(pos) + if line_list: + self.sel_rline = self.canvas.layers['whiteboard'].get_line_by_id(line_list.id) + if self.sel_rline: + self.do_line_menu(evt.GetPosition()) + self.canvas.Refresh(False) + else: + base_layer_handler.on_right_down(self,evt) + else: + base_layer_handler.on_right_down(self,evt) + del dc + + def on_pen_color(self,evt): + data = wx.ColourData() + data.SetChooseFull(True) + dlg = wx.ColourDialog(self.canvas, data) + if dlg.ShowModal() == wx.ID_OK: + data = dlg.GetColourData() + color = data.GetColour() + self.canvas.layers['whiteboard'].setcolor(color) + self.color_button.SetBackgroundColour(color) + dlg.Destroy() + + def on_pen_width(self,evt): + width = int(self.widthList.GetStringSelection()) + self.canvas.layers['whiteboard'].setwidth(width) + + def undo_line(self,evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.use_roles()): + self.top_frame.openrpg.get_component("chat").InfoPost("You must be a GM to use this feature") + return + self.canvas.layers['whiteboard'].undo_line() + dc = self.create_dc() + self.un_highlight(dc) + self.selected = None + del dc + + def delete_all_lines(self,evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be a GM to use this feature") + return + 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) + if dlg.ShowModal() != wx.ID_YES: + return + self.canvas.layers['whiteboard'].del_all_lines() + dc = self.create_dc() + self.un_highlight(dc) + self.selected = None + del dc + + def on_line_menu_item(self, evt): + dc = self.create_dc() + self.un_highlight(dc) + self.canvas.layers['whiteboard'].del_line(self.sel_rline) + self.selected = None + del dc + + def on_text_menu_item(self, evt): + dc = self.create_dc() + self.un_highlight(dc) + self.canvas.layers['whiteboard'].del_text(self.selected) + self.selected = None + del dc + + # Check Draw Mode + # Queries the GUI to see what mode to draw in + # 05-09-2003 Snowdog + + def check_draw_mode(self, evt=None): + self.drawing_mode = self.drawmode_ctrl.GetStringSelection() + + #because mode can be changed while a polyline is being created + #clear the current linestring and reset the polyline data + self.upperleft.x = self.upperleft.y = 0 + self.lowerright.x = self.lowerright.y = 0 + self.lastpoint = None #because the end check function is not called we must force its lastpoint var to None again + self.polypoints = 0 + self.line_string = "0,0;" + if self.temp_circle: + self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) + if self.selected == self.temp_circle: + self.selected = None + self.canvas.Refresh(True) + self.temp_circle = None + self.cone_start = None + + # Altered on_left_up to toggle between + # drawing modes freeform vs polyline + # 05-09-2003 Snowdog + def on_left_down(self,evt): + if not self.drawing: + self.check_draw_mode() + if self.drawing_mode == 'Freeform': + #Freeform mode ignores the inital down click + pass + elif self.drawing_mode == 'Polyline': + self.polyline_add_point( evt ) + elif self.drawing_mode == 'Text': + self.on_text_left_down(evt) + elif self.drawing_mode == 'Cone': + if self.cone_start == None: + self.on_start_cone(evt) + else: + self.draw_temporary_cone(evt) + elif self.drawing_mode == 'Circle': + self.draw_temporary_circle(evt) + + # Added handling for double clicks within the map + # 05-09-2003 Snowdog + def on_left_dclick(self, evt): + if self.drawing_mode == 'Freeform': + #Freeform mode ignores the double click + pass + elif self.drawing_mode == 'Polyline': + self.polyline_last_point( evt ) + elif self.drawing_mode == 'Text': + pass + elif self.drawing_mode == 'Circle' or self.drawing_mode == 'Cone': + self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) + #pointArray = self.temp_circle.line_string.split(";") + self.canvas.layers['whiteboard'].add_line(self.temp_circle.line_string) + self.temp_circle = None + self.cone_start = None + self.drawing = False + + # Altered on_left_up to toggle between + # drawing modes freeform vs polyline + # 05-09-2003 Snowdog + def on_left_up(self,evt): + if self.drawing_mode == 'Freeform': + self.on_freeform_left_up(evt) + elif self.drawing_mode == 'Polyline': + #Polyline mode relies on the down click + #not the mouse button release + pass + elif self.drawing_mode == 'Text': + pass + + # Altered on_left_up to toggle between + # drawing modes freeform vs polyline + # 05-09-2003 Snowdog + def on_motion(self,evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) \ + and (session.my_role()!=session.ROLE_PLAYER) \ + and (session.use_roles()): + return + if self.drawing_mode == 'Freeform': + if evt.m_leftDown: + self.freeform_motion(evt) + elif self.drawing_mode == 'Polyline': + if self.drawing: + self.polyline_preview( evt ) + dc = self.create_dc() + pos = evt.GetLogicalPosition(dc) + hit = self.canvas.layers['whiteboard'].hit_test_lines(pos,dc) + if hit: + self.highlight(hit,dc) + else: + self.un_highlight(dc) + hit = self.canvas.layers['whiteboard'].hit_test_text(pos,dc) + if hit: + self.highlight(hit,dc) + else: + self.un_highlight(dc) + del dc + + def create_dc(self): + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + return dc + + def highlight(self,hit,dc): + if self.selected: + self.selected.highlight(False) + self.selected.draw(self.wb,dc) + self.selected = hit[0] + self.selected.highlight() + self.selected.draw(self.wb,dc) + + def un_highlight(self,dc): + if self.selected: + self.selected.highlight(False) + self.selected.draw(self.wb,dc) + + # Polyline Add Point + # adds a new point to the polyline + # 05-09-2003 Snowdog + def polyline_add_point(self, evt): + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + #reset the bounding points + if pos.x < self.upperleft.x: + self.upperleft.x = pos.x + elif pos.x > self.lowerright.x: + self.lowerright.x = pos.x + if pos.y < self.upperleft.y: + self.upperleft.y = pos.y + elif pos.y > self.lowerright.y: + self.lowerright.y = pos.y + + #if this point doens't end the line + #add a new point into the line string + if not self.polyline_end_check( pos ): + if self.drawing == True: + self.polypoints += 1 #add one to the point counter. + self.line_string += `pos.x` + "," + `pos.y` + ";" + self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) + else: #start of line... + self.polypoints += 1 #add one to the point counter. + self.line_string = `pos.x` + "," + `pos.y` + ";" + self.upperleft.x = pos.x + self.upperleft.y = pos.y + self.lowerright.x = pos.x + self.lowerright.y = pos.y + self.drawing = True + else: #end of line. Send and reset vars for next line + self.drawing = False + if self.polypoints < 2: + #not enough points to form a line. Ignore line + pass + else: + #have enough points to create valid line + #check to role to make sure user can draw at all.... + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + else: + #user allowed to draw on whiteboard.. send polyline + line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) + #resetting variables for next line + self.upperleft.x = self.upperleft.y = 0 + self.lowerright.x = self.lowerright.y = 0 + self.polypoints = 0 + self.line_string = "0,0;" + + # Polyline Last Point + # adds a final point to the polyline and ends it + # 05-09-2003 Snowdog + def polyline_last_point(self, evt): + #if we haven't started a line already. Ignore the click + if self.drawing != True: + return + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + #reset the bounding points + if pos.x < self.upperleft.x: + self.upperleft.x = pos.x + elif pos.x > self.lowerright.x: + self.lowerright.x = pos.x + if pos.y < self.upperleft.y: + self.upperleft.y = pos.y + elif pos.y > self.lowerright.y: + self.lowerright.y = pos.y + self.polypoints += 1 #add one to the point counter. + self.line_string += `pos.x` + "," + `pos.y` + ";" + self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) + #end of line. Send and reset vars for next line + self.drawing = False + if self.polypoints < 2: + #not enough points to form a line. Ignore line + pass + else: + #have enough points to create valid line + #check to role to make sure user can draw at all.... + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + else: + #user allowed to draw on whiteboard.. send polyline + line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) + #resetting variables for next line + self.upperleft.x = self.upperleft.y = 0 + self.lowerright.x = self.lowerright.y = 0 + self.lastpoint = None #becuase the end check function is not called we must force its lastpoint var to None again + self.polypoints = 0 + self.line_string = "0,0;" + + # Polyline End Check + # checks to see if a double click has occured + # a second click on the LAST polyline point + # (or very close proximity) should cause the + # polyline even to complete and send + # 05-09-2003 Snowdog + def polyline_end_check(self, pos): + # check to see if the position of the give point is within POLYLINE_END_TOLERANCE + # if it is then the line has been completed and should be sent to the map just like + # the original freeform version is. A line with fewer than 2 points should be ignored + x_in = y_in = 0 + tol = 5 + + #first point check + if type(self.lastpoint) == type(None): + self.lastpoint = wx.Point(pos.x,pos.y) + return 0 #not end of line + if ((self.lastpoint.x -tol) <= pos.x <= (self.lastpoint.x)): + x_in = 1 + if ((self.lastpoint.y -tol) <= pos.y <= (self.lastpoint.y)): + y_in = 1 + if x_in and y_in: + #point within tolerance. End line + self.lastpoint = None + return 1 + #if we've reached here the point is NOT a terminal point. Reset the lastpoint and return False + self.lastpoint.x = pos.x + self.lastpoint.y = pos.y + return 0 + + # Polyline Preview + # display a temporary/momentary line to the user + # from the last point to mouse position + # 05-09-2003 Snowdog + def polyline_preview(self, evt): + if self.drawing != True: + #not enough points to form a line. Ignore line + return + if self.live_refresh.GetValue() == 0: + #not using live redraw + return + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + + #reset the bounding points + if pos.x < self.upperleft.x: + self.upperleft.x = pos.x + elif pos.x > self.lowerright.x: + self.lowerright.x = pos.x + if pos.y < self.upperleft.y: + self.upperleft.y = pos.y + elif pos.y > self.lowerright.y: + self.lowerright.y = pos.y + + #redraw the line with a line connected to the cursor + temp_string = self.line_string + temp_string += `pos.x` + "," + `pos.y` + ";" + self.canvas.layers['whiteboard'].draw_working_line(dc,temp_string) + self.canvas.Refresh(True) + + # moved original on_motion to this function + # to allow alternate drawing method to be used + # 05-09-2003 Snowdog + def freeform_motion(self, evt): +# if not self.drawing: +# return + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + if pos.x < self.upperleft.x: + self.upperleft.x = pos.x + elif pos.x > self.lowerright.x: + self.lowerright.x = pos.x + if pos.y < self.upperleft.y: + self.upperleft.y = pos.y + elif pos.y > self.lowerright.y: + self.lowerright.y = pos.y + if evt.m_leftDown: + if self.drawing == True: + self.line_string += `pos.x` + "," + `pos.y` + ";" + self.canvas.layers['whiteboard'].draw_working_line(dc,self.line_string) + else: + self.line_string = `pos.x` + "," + `pos.y` + ";" + self.upperleft.x = pos.x + self.upperleft.y = pos.y + self.lowerright.x = pos.x + self.lowerright.y = pos.y + self.drawing = True + del dc + + # moved original on_left_up to this function + # to allow alternate drawing method to be used + # 05-09-2003 Snowdog + def on_freeform_left_up(self,evt): + if self.drawing == True: + self.drawing = False + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + return + #self.id +=1 + line = self.canvas.layers['whiteboard'].add_line(self.line_string,self.upperleft,self.lowerright) + dc = self.create_dc() + for m in range(30): + line.highlight() + line.draw(self.wb,dc) + line.highlight(False) + line.draw(self.wb,dc) + del dc + self.upperleft.x = self.upperleft.y = 0 + self.lowerright.x = self.lowerright.y = 0 + + def on_text_left_down(self, evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + return + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + test_text = self.canvas.layers['whiteboard'].hit_test_text(pos,dc) + if len(test_text) > 0: + if len(test_text) > 1: + self.do_text_menu('left', test_text) + else: + self.text_selected_item = test_text[0] + self.text_selected_item.selected = True + self.canvas.Refresh(True) + else: + if self.text_selected_item == None: + dlg = wx.TextEntryDialog(self,"Text to add to whiteboard", caption="Enter text",defaultValue=" ") + if dlg.ShowModal() == wx.ID_OK: + text_string = dlg.GetValue() + self.canvas.layers['whiteboard'].add_text(text_string,pos, self.style, self.pointsize, self.weight, self.canvas.layers['whiteboard'].color) + else: + self.text_selected_item.posx = pos.x + self.text_selected_item.posy = pos.y + self.text_selected_item.isUpdated = True + self.text_to_xml() + self.text_selected_item.selected = False + self.text_selected_item = None + del dc + + def on_text_right_down(self, evt, dc): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + return + pos = evt.GetLogicalPosition(dc) + test_text = self.canvas.layers['whiteboard'].hit_test_text(pos, dc) + if len(test_text) > 0: + if len(test_text) > 1: + self.do_text_menu('right', test_text) + else: + self.text_selected_item = test_text[0] + self.do_text_menu('right') + + def on_start_cone(self, evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + return + self.cone_start = self.get_snapped_to_logical_pos(evt) + self.drawing = True + + def get_snapped_to_logical_pos(self, evt): + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + if self.canvas.layers['grid'].snap: + size = self.canvas.layers['grid'].unit_size + pos.x = int((pos.x+size/2)/size)*size + pos.y = int((pos.y+size/2)/size)*size + return pos + + def draw_temporary_cone(self, evt): + scale = self.canvas.layers['grid'].mapscale + dc = wx.ClientDC( self.canvas ) + self.canvas.PrepareDC( dc ) + dc.SetUserScale(scale,scale) + pos = evt.GetLogicalPosition(dc) + pos2 = self.get_snapped_to_logical_pos(evt) + size = self.canvas.layers['grid'].unit_size #60 + if abs(pos.x-pos2.x)<=size/10 and abs(pos.y-pos2.y)<=size/10: + pos = pos2 + radius = int(int(self.radius.GetValue())/5) + curve = self.calculate_circle(self.cone_start, radius, size) + edge1 = [] + edge2 = [] + horizontal_inc = wx.Point(size,0) + if pos.x <= self.cone_start.x: + horizontal_inc = wx.Point(-size,0) + vertical_inc = wx.Point(0,size) + if pos.y <= self.cone_start.y: + vertical_inc = wx.Point(0,-size) + x_diff = float(pos.x - self.cone_start.x) + y_diff = float(pos.y - self.cone_start.y) + ratio = float(1) + if abs(x_diff) <= abs(y_diff): + ratio = x_diff / y_diff + elif abs(y_diff) < abs(x_diff): + ratio = -(y_diff / x_diff) + horizontal_inc,vertical_inc = vertical_inc,horizontal_inc #swap + horizontal_rotated = wx.Point(-horizontal_inc.y, horizontal_inc.x) + vertical_rotated = wx.Point(-vertical_inc.y, vertical_inc.x) + on_diagonal = True + for v in range(radius): + x = int(floor((v+1)*ratio)) - int(floor(v*ratio)) + if x < 0 and on_diagonal: + edge1 += [vertical_inc] + edge1 += [horizontal_inc] + elif x != 0: + edge1 += [horizontal_inc] + edge1 += [vertical_inc] + else: + edge1 += [vertical_inc] + on_diagonal = False + on_diagonal = True + for v in range(radius): + x = int(floor((v+1)*(-ratio))) - int(floor(v*(-ratio))) + if x < 0 and on_diagonal: + edge2 += [vertical_rotated] + edge2 += [horizontal_rotated] + elif x != 0: + edge2 += [horizontal_rotated] + edge2 += [vertical_rotated] + else: + edge2 += [vertical_rotated] + on_diagonal = False + p = wx.Point(0,0) + string1 = self.point_to_string(p, [self.cone_start]) + string1 += self.point_to_string(p, edge1) + p = wx.Point(0,0) + string2 = self.point_to_string(p, [self.cone_start]) + string2 += self.point_to_string(p, edge2) + + # truncate the edges where they meet the curve + pointArray = string1.split(";") + string1 = "" + for p in pointArray: + p += ";" + index = (";"+curve).find(";"+p) + if index >= 0: + # found intersection, start circle at intersection + curve = curve[index:]+curve[:index] + break + string1 += p + + # truncate the edges where they meet the curve + pointArray = string2.split(";") + string2 = "" + for p in pointArray: + p += ";" + string2 = p + string2 #backwards + index = (";"+curve).find(";"+p) + if index >= 0: + # found intersection, end circle at intersection + curve = curve[:index] + break + curve = string1 + curve + string2 + + # add the lines that define the real cone edges + sz = sqrt(x_diff*x_diff + y_diff*y_diff) + x_diff = radius*size*x_diff/sz + y_diff = radius*size*y_diff/sz + pos = wx.Point(self.cone_start.x+x_diff, self.cone_start.y+y_diff) + qos = wx.Point(self.cone_start.x-y_diff, self.cone_start.y+x_diff)# 90 degree rotation + curve = `pos.x`+","+`pos.y`+";" + curve + `qos.x`+","+`qos.y`+";" + if(self.temp_circle): + self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) + if self.selected == self.temp_circle: + self.selected = None + self.temp_circle = self.canvas.layers['whiteboard'].add_temp_line(curve) + self.canvas.Refresh(True) + + def draw_temporary_circle(self, evt): + session = self.canvas.frame.session + if (session.my_role() != session.ROLE_GM) and (session.my_role()!=session.ROLE_PLAYER) and (session.use_roles()): + open_rpg.get_component("chat").InfoPost("You must be either a player or GM to use this feature") + self.canvas.Refresh(False) + return + pos = self.get_snapped_to_logical_pos(evt) + size = self.canvas.layers['grid'].unit_size #60 + radius = int(int(self.radius.GetValue())/5) + center = wx.Point(pos.x, pos.y+size*radius) + curve = self.calculate_circle(center, radius, size) + if(self.temp_circle): + self.canvas.layers['whiteboard'].del_temp_line(self.temp_circle) + self.selected = None + self.temp_circle = self.canvas.layers['whiteboard'].add_temp_line(curve) + self.drawing = True + self.canvas.Refresh(True) + + def calculate_circle(self, center, radius, size): + pos = wx.Point(center.x, center.y-size*radius) + r = int(radius+2/3) + right = wx.Point(size,0) + left = wx.Point(-size,0) + up = wx.Point(0,-size) + down = wx.Point(0,size) + v1 = ([right, down, right]*r)[:radius] + v2 = ([down, right, down]*r)[r*3-radius:] + v3 = ([down, left, down]*r)[:radius] + v4 = ([left, down, left]*r)[r*3-radius:] + v5 = ([left, up, left]*r)[:radius] + v6 = ([up, left, up]*r)[r*3-radius:] + v7 = ([up, right, up]*r)[:radius] + v8 = ([right, up, right]*r)[r*3-radius:] + p = wx.Point(0,0) + temp_string = self.point_to_string(p, [pos]) + temp_string += self.point_to_string(p, v1+v2+v3+v4+v5+v6+v7+v8) + return temp_string + + def point_to_string(self, pos, vec): + str = "" + for i in range(len(vec)): + pos.x = pos.x + vec[i].x + pos.y = pos.y + vec[i].y + str += `pos.x` + "," + `pos.y` + ";" + return str +