comparison tools/editor/scripts/gui/mapeditor.py @ 418:70ba57cd9d18

Documented, commented, cleaned and updated mapeditor.py to match new python coding guidelines.
author cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 06 Feb 2010 18:50:36 +0000
parents 64738befdf3b
children b2feacaed53c
comparison
equal deleted inserted replaced
417:14e8087cde2c 418:70ba57cd9d18
19 # License along with this library; if not, write to the 19 # License along with this library; if not, write to the
20 # Free Software Foundation, Inc., 20 # Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # #################################################################### 22 # ####################################################################
23 23
24 # MapEditor is a plugin for Fifedit. It allows for selection and visual editing of maps. 24 """
25 25 Visual Map Editor
26 import math, os, time 26 =================
27
28 The map editor provides the user with an interface for editing
29 maps visually.
30
31 To edit a map through code, use MapController.
32
33 """
34
35 import math
36 import os
37 import time
27 from datetime import date 38 from datetime import date
28 39
29 from fife import fife 40 from fife import fife
30 from fife.extensions import pychan 41 from fife.extensions import pychan
31 import fife.extensions.pychan.widgets as widgets 42 import fife.extensions.pychan.widgets as widgets
43 from fife.extensions import fife_utils
44
32 import scripts 45 import scripts
33 import scripts.events as events 46 import scripts.events as events
34 import action 47 import action
35 from toolbar import ToolBar 48 from toolbar import ToolBar
36 from menubar import Menu, MenuBar 49 from menubar import Menu, MenuBar
37 from action import Action, ActionGroup 50 from action import Action, ActionGroup
38 from scripts.mapcontroller import MapController 51 from scripts.mapcontroller import MapController
39 from fife.extensions import fife_utils
40
41 states = (u'SELECTING', u'INSERTING', u'REMOVING', u'MOVING', u'OBJECTPICKER')
42 for s in states:
43 globals()[s] = s
44 NOT_INITIALIZED = -9999999
45 52
46 class MapEditor: 53 class MapEditor:
47 def __init__(self): 54 """ This class provides a basic user interface for map editing. It allows the user
55 to visually edit a map.
56 """
57
58 # Editor states
59 SELECTING = u"Selecting"
60 INSERTING = u"Inserting"
61 REMOVING = u"Removing"
62 MOVING = u"Moving"
63 OBJECTPICKER = u"Objectpicking"
64
65 def __init__(self):
66 """ Set up all variables and call some initial functions """
48 self._ignoreToggles = False # A hack to avoid infinite recursion when toggling a button 67 self._ignoreToggles = False # A hack to avoid infinite recursion when toggling a button
49 self._controller = None 68 self._controller = None
50 self._mode = SELECTING 69 self._mode = MapEditor.SELECTING
51 70 self._debug = False # TODO: We should have a central system for activating debug messages
71
72 # GUI
52 self._editor = scripts.editor.getEditor() 73 self._editor = scripts.editor.getEditor()
53 self._eventlistener = self._editor.getEventListener() 74 self._eventlistener = self._editor.getEventListener()
54 self._statusbar = self._editor.getStatusBar() 75 self._statusbar = self._editor.getStatusBar()
55 self._toolbar = self._editor.getToolBar() 76 self._toolbar = self._editor.getToolBar()
77 self._toolbox = self._editor.getToolbox()
78
79 # Currently selected object type
56 self._object = None 80 self._object = None
57 self._startDragPos = None 81
58 self._lastDragPos = None 82 # Variables used for moving instances
59 self._lastDragPosExact = None 83 self._last_drag_pos = None
60 84 self._last_drag_pos_exact = None
61 self._toolbox = self._editor.getToolbox() 85
62 86 self._selected_instances = []
63 self._initToolbuttons() 87
64 88 self._undogroup = False
89
90 # Variables for scrolling the map
91 self._dragx = 0
92 self._dragy = 0
93 self._scrollX = 0
94 self._scrollY = 0
95
96 self._initToolboxButtons()
65 self._toolbox.show() 97 self._toolbox.show()
66 self._instances = []
67 98
68 events.postMapShown.connect(self._mapChanged) 99 events.postMapShown.connect(self._mapChanged)
69 events.preMapClosed.connect(self._mapClosed) 100 events.preMapClosed.connect(self._mapClosed)
70 events.onObjectSelected.connect(self.setObject) 101 events.onObjectSelected.connect(self.setObject)
71 self._undogroup = False 102
72 103 def setObject(self, object):
73 self._scrollX = 0 104 """ Set the object type to be paint onto map """
74 self._scrollY = 0 105 self._object = object
106
107 def setController(self, controller):
108 """ Set the controller to use. """
109 if self._controller is not None:
110 self._clear()
111
112 self._controller = controller
113
114 if self._controller is not None:
115 self._init()
75 116
76 def _init(self): 117 def _init(self):
77 self._dragx = NOT_INITIALIZED 118 """ Sets up the mapeditor to work with the selected controller """
78 self._dragy = NOT_INITIALIZED 119 self._debug = self._controller.debug
79 120 self._setMode(MapEditor.SELECTING)
80 self._setMode(SELECTING)
81 121
82 self._initToolbarbuttons() 122 self._initToolbarbuttons()
83 123
84 events.keyPressed.connect(self.keyPressed) 124 events.keyPressed.connect(self.keyPressed)
85 events.keyReleased.connect(self.keyReleased) 125 events.keyReleased.connect(self.keyReleased)
93 events.mouseWheelMovedUp.connect(self.mouseWheelMovedUp) 133 events.mouseWheelMovedUp.connect(self.mouseWheelMovedUp)
94 events.mouseWheelMovedDown.connect(self.mouseWheelMovedDown) 134 events.mouseWheelMovedDown.connect(self.mouseWheelMovedDown)
95 events.onPump.connect(self.pump) 135 events.onPump.connect(self.pump)
96 136
97 def _clear(self): 137 def _clear(self):
138 """ Remove any functionality set up by _init """
98 self._clearToolbarButtons() 139 self._clearToolbarButtons()
99 140
100 events.keyPressed.disconnect(self.keyPressed) 141 events.keyPressed.disconnect(self.keyPressed)
101 events.keyReleased.disconnect(self.keyReleased) 142 events.keyReleased.disconnect(self.keyReleased)
102 143
109 events.mouseWheelMovedUp.disconnect(self.mouseWheelMovedUp) 150 events.mouseWheelMovedUp.disconnect(self.mouseWheelMovedUp)
110 events.mouseWheelMovedDown.disconnect(self.mouseWheelMovedDown) 151 events.mouseWheelMovedDown.disconnect(self.mouseWheelMovedDown)
111 events.onPump.disconnect(self.pump) 152 events.onPump.disconnect(self.pump)
112 153
113 def _mapChanged(self, sender, mapview): 154 def _mapChanged(self, sender, mapview):
155 """ Called when a new map is selected.
156 Sets the mapeditor to control the mapcontroller in the new map
157 """
114 self.setController(mapview.getController()) 158 self.setController(mapview.getController())
115 159
116 def _mapClosed(self, sender, mapview): 160 def _mapClosed(self, sender, mapview):
117 self.setController(None) 161 """ Called when a map is closed. """
118 162 if mapview.getMap().getId() == self._controller.getMap().getId():
119 def _setCursor(self): 163 self.setController(None)
164
165 def _updateCursor(self):
166 """ Updates the cursor to reflect the mode of the editor """
120 engine = self._editor.getEngine() 167 engine = self._editor.getEngine()
121 cursor = engine.getCursor() 168 cursor = engine.getCursor()
122 169
123 id = -1 170 id = -1
124 if self._mode == SELECTING: 171 if self._mode == MapEditor.SELECTING:
125 id = engine.getImagePool().addResourceFromFile("gui/icons/select_instance.png") 172 id = engine.getImagePool().addResourceFromFile("gui/icons/select_instance.png")
126 image = engine.getImagePool().getImage(id) 173 image = engine.getImagePool().getImage(id)
127 image.setXShift(-7) 174 image.setXShift(-7)
128 image.setYShift(-7) 175 image.setYShift(-7)
129 elif self._mode == INSERTING: 176
177 elif self._mode == MapEditor.INSERTING:
130 id = engine.getImagePool().addResourceFromFile("gui/icons/add_instance.png") 178 id = engine.getImagePool().addResourceFromFile("gui/icons/add_instance.png")
131 image = engine.getImagePool().getImage(id) 179 image = engine.getImagePool().getImage(id)
132 image.setXShift(-2) 180 image.setXShift(-2)
133 image.setYShift(-20) 181 image.setYShift(-20)
134 elif self._mode == REMOVING: 182
183 elif self._mode == MapEditor.REMOVING:
135 id = engine.getImagePool().addResourceFromFile("gui/icons/erase_instance.png") 184 id = engine.getImagePool().addResourceFromFile("gui/icons/erase_instance.png")
136 image = engine.getImagePool().getImage(id) 185 image = engine.getImagePool().getImage(id)
137 image.setXShift(-2) 186 image.setXShift(-2)
138 image.setYShift(-19) 187 image.setYShift(-19)
139 elif self._mode == MOVING: 188
189 elif self._mode == MapEditor.MOVING:
140 id = engine.getImagePool().addResourceFromFile("gui/icons/move_instance.png") 190 id = engine.getImagePool().addResourceFromFile("gui/icons/move_instance.png")
141 image = engine.getImagePool().getImage(id) 191 image = engine.getImagePool().getImage(id)
142 image.setXShift(-11) 192 image.setXShift(-11)
143 image.setYShift(-11) 193 image.setYShift(-11)
144 elif self._mode == OBJECTPICKER: 194
195 elif self._mode == MapEditor.OBJECTPICKER:
145 id = engine.getImagePool().addResourceFromFile("gui/icons/objectpicker.png") 196 id = engine.getImagePool().addResourceFromFile("gui/icons/objectpicker.png")
146 image = engine.getImagePool().getImage(id) 197 image = engine.getImagePool().getImage(id)
147 image.setXShift(-0) 198 image.setXShift(-0)
148 image.setYShift(-22) 199 image.setYShift(-22)
149 200
151 self._resetCursor() 202 self._resetCursor()
152 else: 203 else:
153 cursor.set(fife.CURSOR_IMAGE, id) 204 cursor.set(fife.CURSOR_IMAGE, id)
154 205
155 def _resetCursor(self): 206 def _resetCursor(self):
207 """ Reset the cursor to the standard native one """
156 cursor = self._editor.getEngine().getCursor() 208 cursor = self._editor.getEngine().getCursor()
157 cursor.set(fife.CURSOR_NATIVE, fife.NC_ARROW) 209 cursor.set(fife.CURSOR_NATIVE, fife.NC_ARROW)
158 210
159 def setObject(self, object): 211 def _initToolboxButtons(self):
160 self._object = object 212 """ Sets up and connects buttons related to the toolbox """
161 213
162 def setController(self, controller):
163 if self._controller is not None:
164 self._clear()
165
166 if controller is not None:
167 self._init()
168
169 self._controller = controller
170
171 def _initToolbuttons(self):
172 self._selectAction = Action(text=u"Select", icon="gui/icons/select_instance.png", checkable=True) 214 self._selectAction = Action(text=u"Select", icon="gui/icons/select_instance.png", checkable=True)
173 self._drawAction = Action(text=u"Draw", icon="gui/icons/add_instance.png", checkable=True) 215 self._drawAction = Action(text=u"Draw", icon="gui/icons/add_instance.png", checkable=True)
174 self._removeAction = Action(text=u"Remove", icon="gui/icons/erase_instance.png", checkable=True) 216 self._removeAction = Action(text=u"Remove", icon="gui/icons/erase_instance.png", checkable=True)
175 self._moveAction = Action(text=u"Move", icon="gui/icons/move_instance.png", checkable=True) 217 self._moveAction = Action(text=u"Move", icon="gui/icons/move_instance.png", checkable=True)
176 self._objectpickerAction = Action(text=u"Pick object", icon="gui/icons/objectpicker.png", checkable=True) 218 self._objectpickerAction = Action(text=u"Pick object", icon="gui/icons/objectpicker.png", checkable=True)
192 self._toolgroup.addAction(self._moveAction) 234 self._toolgroup.addAction(self._moveAction)
193 self._toolgroup.addAction(self._drawAction) 235 self._toolgroup.addAction(self._drawAction)
194 self._toolgroup.addAction(self._removeAction) 236 self._toolgroup.addAction(self._removeAction)
195 self._toolgroup.addAction(self._objectpickerAction) 237 self._toolgroup.addAction(self._objectpickerAction)
196 238
197
198 self._toolbox.addAction(self._toolgroup) 239 self._toolbox.addAction(self._toolgroup)
199 self._toolbox.adaptLayout() 240 self._toolbox.adaptLayout()
200 241
201 self._editor._edit_menu.addAction(self._toolgroup) 242 self._editor._edit_menu.addAction(self._toolgroup)
202 243
203 def _initToolbarbuttons(self): 244 def _initToolbarbuttons(self):
245 """ Sets up and connects buttons related to the toolbar """
246
204 rotateLeftAction = Action(text=u"Rotate counterclockwise", icon="gui/icons/rotate_countercw.png") 247 rotateLeftAction = Action(text=u"Rotate counterclockwise", icon="gui/icons/rotate_countercw.png")
205 rotateRightAction = Action(text=u"Rotate clockwise", icon="gui/icons/rotate_clockwise.png") 248 rotateRightAction = Action(text=u"Rotate clockwise", icon="gui/icons/rotate_clockwise.png")
206 zoomInAction = Action(text=u"Zoom in", icon="gui/icons/zoom_in.png") 249 zoomInAction = Action(text=u"Zoom in", icon="gui/icons/zoom_in.png")
207 zoomOutAction = Action(text=u"Zoom out", icon="gui/icons/zoom_out.png") 250 zoomOutAction = Action(text=u"Zoom out", icon="gui/icons/zoom_out.png")
208 zoomResetAction = Action(text=u"Reset zoom", icon="gui/icons/zoom_default.png") 251 zoomResetAction = Action(text=u"Reset zoom", icon="gui/icons/zoom_default.png")
213 zoomInAction.helptext = u"Zoom in (CTRL + Mousewheel up)" 256 zoomInAction.helptext = u"Zoom in (CTRL + Mousewheel up)"
214 zoomOutAction.helptext = u"Zoom out (CTRL + Mousewheel down)" 257 zoomOutAction.helptext = u"Zoom out (CTRL + Mousewheel down)"
215 zoomResetAction.helptext = u"Reset zoom to default level" 258 zoomResetAction.helptext = u"Reset zoom to default level"
216 screenshotAction.helptext = u"Take screenshot (F7)" 259 screenshotAction.helptext = u"Take screenshot (F7)"
217 260
218 action.activated.connect(self.rotateCounterClockwise, sender=rotateLeftAction) 261 action.activated.connect(self._rotateCounterClockwise, sender=rotateLeftAction)
219 action.activated.connect(self.rotateClockwise, sender=rotateRightAction) 262 action.activated.connect(self._rotateClockwise, sender=rotateRightAction)
220 action.activated.connect(self.zoomIn, sender=zoomInAction) 263 action.activated.connect(self._zoomIn, sender=zoomInAction)
221 action.activated.connect(self.zoomOut, sender=zoomOutAction) 264 action.activated.connect(self._zoomOut, sender=zoomOutAction)
222 action.activated.connect(self.resetZoom, sender=zoomResetAction) 265 action.activated.connect(self._resetZoom, sender=zoomResetAction)
223 action.activated.connect(self.captureScreen, sender=screenshotAction) 266 action.activated.connect(self._captureScreen, sender=screenshotAction)
224 267
225 self._viewGroup = ActionGroup(name=u"View group") 268 self._viewGroup = ActionGroup(name=u"View group")
226 self._viewGroup.addAction(rotateLeftAction) 269 self._viewGroup.addAction(rotateLeftAction)
227 self._viewGroup.addAction(rotateRightAction) 270 self._viewGroup.addAction(rotateRightAction)
228 self._viewGroup.addAction(zoomInAction) 271 self._viewGroup.addAction(zoomInAction)
232 275
233 self._toolbar.addAction(self._viewGroup) 276 self._toolbar.addAction(self._viewGroup)
234 self._toolbar.adaptLayout() 277 self._toolbar.adaptLayout()
235 278
236 def _clearToolbarButtons(self): 279 def _clearToolbarButtons(self):
280 """ Remove toolbar buttons """
237 self._toolbar.removeAction(self._viewGroup) 281 self._toolbar.removeAction(self._viewGroup)
238 self._toolbar.adaptLayout() 282 self._toolbar.adaptLayout()
239 self._viewGroup = None 283 self._viewGroup = None
240 284
241
242 def _setMode(self, mode): 285 def _setMode(self, mode):
243 if (mode == INSERTING) and (not self._object): 286 """ Set the editor mode """
287 if (mode == MapEditor.INSERTING) and (not self._object):
244 self._statusbar.setText(u'Please select object first') 288 self._statusbar.setText(u'Please select object first')
245 mode = self._mode 289 mode = self._mode
246 290
247 self._ignoreToggles = True 291 self._ignoreToggles = True
248 # Update toolbox buttons 292 # Update toolbox buttons
249 if (mode == INSERTING): 293 if (mode == MapEditor.INSERTING):
250 self._drawAction.setChecked(True) 294 self._drawAction.setChecked(True)
251 elif mode == REMOVING: 295 elif mode == MapEditor.REMOVING:
252 self._removeAction.setChecked(True) 296 self._removeAction.setChecked(True)
253 elif mode == MOVING: 297 elif mode == MapEditor.MOVING:
254 self._moveAction.setChecked(True) 298 self._moveAction.setChecked(True)
255 elif mode == OBJECTPICKER: 299 elif mode == MapEditor.OBJECTPICKER:
256 self._objectpickerAction.setChecked(True) 300 self._objectpickerAction.setChecked(True)
257 else: 301 else:
258 self._selectAction.setChecked(True) 302 self._selectAction.setChecked(True)
259 self._ignoreToggles = False 303 self._ignoreToggles = False
260 304
261 self._mode = mode 305 self._mode = mode
262 print "Entered mode " + mode 306 if self._debug: print "Entered mode " + mode
263 self._statusbar.setText(mode.replace('_', ' ').capitalize()) 307 self._statusbar.setText(mode)
264 self._setCursor() 308 self._updateCursor()
309
310 def _zoomIn(self, zoom=1.10):
311 self._controller.setZoom(self._controller.getZoom()*zoom)
312
313 def _zoomOut(self, zoom=1.10):
314 self._controller.setZoom(self._controller.getZoom()/zoom)
315
316 def _resetZoom(self):
317 """ Resets zoom level to 1:1 """
318 self._controller.setZoom(1)
319
320 def _rotateCounterClockwise(self):
321 """ Rotates map counterclockwise """
322 self._controller.rotateCounterClockwise()
323
324 def _rotateClockwise(self):
325 """ Rotates map clockwise """
326 self._controller.rotateClockwise()
327
328 def _captureScreen(self):
329 """ Saves a screenshot to the users data directory """
330 userDir = fife_utils.getUserDataDirectory("fife", "editor")
331 t = userDir+"/screenshots"
332 if not os.path.isdir(t):
333 os.makedirs(t)
334 t += "/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
335 time.strftime('%H-%M-%S'))
336
337 self._editor.getEngine().getRenderBackend().captureScreen(t)
338 print "Saved screenshot to:", t
265 339
266 def _buttonToggled(self, sender, toggled): 340 def _buttonToggled(self, sender, toggled):
341 """ Called when a button controlling the editor mode was activated """
267 if self._controller is None: return 342 if self._controller is None: return
268 if self._ignoreToggles is True: return 343 if self._ignoreToggles is True: return
269 344
270 mode = SELECTING 345 mode = MapEditor.SELECTING
271 346
272 if toggled: 347 if toggled:
273 if sender == self._selectAction: 348 if sender == self._selectAction:
274 mode = SELECTING 349 mode = MapEditor.SELECTING
275 elif sender == self._moveAction: 350 elif sender == self._moveAction:
276 mode = MOVING 351 mode = MapEditor.MOVING
277 elif sender == self._drawAction: 352 elif sender == self._drawAction:
278 mode = INSERTING 353 mode = MapEditor.INSERTING
279 elif sender == self._removeAction: 354 elif sender == self._removeAction:
280 mode = REMOVING 355 mode = MapEditor.REMOVING
281 elif sender == self._objectpickerAction: 356 elif sender == self._objectpickerAction:
282 mode = OBJECTPICKER 357 mode = MapEditor.OBJECTPICKER
283 358
284 self._setMode(mode) 359 self._setMode(mode)
285 360
286 def mousePressed(self, sender, event): 361 def mousePressed(self, sender, event):
287 if event.isConsumedByWidgets(): 362 if event.isConsumedByWidgets():
288 return 363 return
289 364
290 if not self._controller._layer: 365 if not self._controller._layer:
291 if self._controller.debug: print 'No layers active. Cancelling map action' 366 if self._debug: print 'No layers active. Cancelling map action'
292 return 367 return
293 368
294 realCoords = self._getRealCoords(sender, event) 369 realCoords = self._getRealCoords(sender, event)
295 370
296 if event.getButton() == fife.MouseEvent.MIDDLE: 371 if event.getButton() == fife.MouseEvent.MIDDLE:
299 374
300 else: 375 else:
301 if event.getButton() == fife.MouseEvent.RIGHT: 376 if event.getButton() == fife.MouseEvent.RIGHT:
302 self._controller.deselectSelection() 377 self._controller.deselectSelection()
303 378
304 if self._mode == SELECTING: 379 if self._mode == MapEditor.SELECTING:
305 if event.getButton() == fife.MouseEvent.LEFT: 380 if event.getButton() == fife.MouseEvent.LEFT:
306 if self._eventlistener.shiftPressed: 381 if self._eventlistener.shiftPressed:
307 self._controller.deselectCell(realCoords[0], realCoords[1]) 382 self._controller.deselectCell(realCoords[0], realCoords[1])
308 else: 383 else:
309 if self._eventlistener.controlPressed is False: 384 if self._eventlistener.controlPressed is False:
311 self._controller.selectCell(realCoords[0], realCoords[1]) 386 self._controller.selectCell(realCoords[0], realCoords[1])
312 387
313 elif event.getButton() == fife.MouseEvent.RIGHT: 388 elif event.getButton() == fife.MouseEvent.RIGHT:
314 self._controller.deselectSelection() 389 self._controller.deselectSelection()
315 390
316 elif self._mode == INSERTING: 391 elif self._mode == MapEditor.INSERTING:
317 if event.getButton() == fife.MouseEvent.LEFT: 392 if event.getButton() == fife.MouseEvent.LEFT:
318 self._controller.deselectSelection() 393 self._controller.deselectSelection()
319 self._controller.selectCell(realCoords[0], realCoords[1]) 394 self._controller.selectCell(realCoords[0], realCoords[1])
320 self._controller.getUndoManager().startGroup("Inserted instances") 395 self._controller.getUndoManager().startGroup("Inserted instances")
321 self._undogroup = True 396 self._undogroup = True
324 position = self._controller._layer.getCellGrid().toLayerCoordinates(position) 399 position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
325 400
326 self._controller.selectCell(realCoords[0], realCoords[1]) 401 self._controller.selectCell(realCoords[0], realCoords[1])
327 self._controller.placeInstance(position, self._object) 402 self._controller.placeInstance(position, self._object)
328 403
329 elif self._mode == REMOVING: 404 elif self._mode == MapEditor.REMOVING:
330 if event.getButton() == fife.MouseEvent.LEFT: 405 if event.getButton() == fife.MouseEvent.LEFT:
331 self._controller.deselectSelection() 406 self._controller.deselectSelection()
332 self._controller.selectCell(realCoords[0], realCoords[1]) 407 self._controller.selectCell(realCoords[0], realCoords[1])
333 self._controller.getUndoManager().startGroup("Removed instances") 408 self._controller.getUndoManager().startGroup("Removed instances")
334 self._undogroup = True 409 self._undogroup = True
335 410
336 self._controller.removeInstances(self._controller.getInstancesFromSelection()) 411 self._controller.removeInstances(self._controller.getInstancesFromSelection())
337 412
338 elif self._mode == MOVING: 413 elif self._mode == MapEditor.MOVING:
339 if event.getButton() == fife.MouseEvent.LEFT: 414 if event.getButton() == fife.MouseEvent.LEFT:
340 415
341 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) 416 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
342 417
343 self._lastDragPos = self._controller._layer.getCellGrid().toLayerCoordinates(position) 418 self._last_drag_pos = self._controller._layer.getCellGrid().toLayerCoordinates(position)
344 self._lastDragPosExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) 419 self._last_drag_pos_exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
345 420
346 for loc in self._controller._selection: 421 for loc in self._controller._selection:
347 if loc.getLayerCoordinates() == self._lastDragPos: 422 if loc.getLayerCoordinates() == self._last_drag_pos:
348 break 423 break
349 else: 424 else:
350 self._controller.deselectSelection() 425 self._controller.deselectSelection()
351 self._controller.selectCell(realCoords[0], realCoords[1]) 426 self._controller.selectCell(realCoords[0], realCoords[1])
352 427
353 self._instances = self._controller.getInstancesFromSelection() 428 self._selected_instances = self._controller.getInstancesFromSelection()
354 429
355 self._controller.getUndoManager().startGroup("Moved instances") 430 self._controller.getUndoManager().startGroup("Moved instances")
356 self._undogroup = True 431 self._undogroup = True
357 432
358 elif self._mode == OBJECTPICKER: 433 elif self._mode == MapEditor.OBJECTPICKER:
359 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) 434 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
360 exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) 435 exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
361 instances = self._controller.getInstancesFromPosition(exact) 436 instances = self._controller.getInstancesFromPosition(exact)
362 if len(instances) >= 1: 437 if len(instances) >= 1:
363 object = instances[0].getObject() 438 object = instances[0].getObject()
367 def mouseDragged(self, sender, event): 442 def mouseDragged(self, sender, event):
368 if event.isConsumedByWidgets(): 443 if event.isConsumedByWidgets():
369 return 444 return
370 445
371 if not self._controller._layer: 446 if not self._controller._layer:
372 if self._controller.debug: print 'No layers active. Cancelling map action' 447 if self._debug: print 'No layers active. Cancelling map action'
373 return 448 return
374 449
375 realCoords = self._getRealCoords(sender, event) 450 realCoords = self._getRealCoords(sender, event)
376 451
377 if event.getButton() == fife.MouseEvent.MIDDLE: 452 if event.getButton() == fife.MouseEvent.MIDDLE:
378 self._scrollX = (self._dragx-realCoords[0])/10.0 453 self._scrollX = (self._dragx-realCoords[0])/10.0
379 self._scrollY = (self._dragy-realCoords[1])/10.0 454 self._scrollY = (self._dragy-realCoords[1])/10.0
455
380 else: 456 else:
381 if self._mode != SELECTING: 457 if self._mode != MapEditor.SELECTING:
382 self._controller.deselectSelection() 458 self._controller.deselectSelection()
383 459
384 if self._mode == SELECTING: 460 if self._mode == MapEditor.SELECTING:
385 if event.getButton() == fife.MouseEvent.LEFT: 461 if event.getButton() == fife.MouseEvent.LEFT:
386 if self._eventlistener.shiftPressed: 462 if self._eventlistener.shiftPressed:
387 self._controller.deselectCell(realCoords[0], realCoords[1]) 463 self._controller.deselectCell(realCoords[0], realCoords[1])
388 else: 464 else:
389 self._controller.selectCell(realCoords[0], realCoords[1]) 465 self._controller.selectCell(realCoords[0], realCoords[1])
390 466
391 elif self._mode == INSERTING: 467 elif self._mode == MapEditor.INSERTING:
392 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) 468 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
393 position = self._controller._layer.getCellGrid().toLayerCoordinates(position) 469 position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
394 470
395 self._controller.selectCell(realCoords[0], realCoords[1]) 471 self._controller.selectCell(realCoords[0], realCoords[1])
396 self._controller.placeInstance(position, self._object) 472 self._controller.placeInstance(position, self._object)
397 473
398 elif self._mode == REMOVING: 474 elif self._mode == MapEditor.REMOVING:
399 self._controller.selectCell(realCoords[0], realCoords[1]) 475 self._controller.selectCell(realCoords[0], realCoords[1])
400 self._controller.removeInstances(self._controller.getInstancesFromSelection()) 476 self._controller.removeInstances(self._controller.getInstancesFromSelection())
401 477
402 elif self._mode == MOVING: 478 elif self._mode == MapEditor.MOVING:
403 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) 479 position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
404 480
405 positionExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) 481 positionExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
406 position = self._controller._layer.getCellGrid().toLayerCoordinates(position) 482 position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
407 483
408 if self._eventlistener.shiftPressed: 484 if self._eventlistener.shiftPressed:
409 self._controller.moveInstances(self._instances, positionExact-self._lastDragPosExact, True) 485 self._controller.moveInstances(self._selected_instances, positionExact-self._last_drag_pos_exact, True)
410 else: 486 else:
411 self._controller.moveInstances(self._instances, position-self._lastDragPos, False) 487 self._controller.moveInstances(self._selected_instances, position-self._last_drag_pos, False)
412 self._lastDragPos = position 488 self._last_drag_pos = position
413 self._lastDragPosExact = positionExact 489 self._last_drag_pos_exact = positionExact
414 490
415 # Update selection 491 # Update selection
416 self._controller.deselectSelection() 492 self._controller.deselectSelection()
417 493
418 for i in self._instances: 494 for i in self._selected_instances:
419 pos = i.getLocation().getMapCoordinates() 495 pos = i.getLocation().getMapCoordinates()
420 pos = self._controller._camera.toScreenCoordinates(pos) 496 pos = self._controller._camera.toScreenCoordinates(pos)
421 self._controller.selectCell(pos.x, pos.y) 497 self._controller.selectCell(pos.x, pos.y)
422 elif self._mode == OBJECTPICKER: 498
499 elif self._mode == MapEditor.OBJECTPICKER:
423 pass 500 pass
424 501
425 def mouseReleased(self, sender, event): 502 def mouseReleased(self, sender, event):
426 if event.isConsumedByWidgets(): 503 if event.isConsumedByWidgets():
427 return 504 return
428 505
429 if not self._controller._layer: 506 if not self._controller._layer:
430 if self._controller.debug: print 'No layers active. Cancelling map action' 507 if self._debug: print 'No layers active. Cancelling map action'
431 return 508 return
432 509
433 if self._mode == SELECTING or self._mode == MOVING: 510 if self._mode == MapEditor.SELECTING or self._mode == MapEditor.MOVING:
434 instances = self._controller.getInstancesFromSelection() 511 instances = self._controller.getInstancesFromSelection()
435 if len(instances) > 0: 512 if len(instances) > 0:
436 events.onInstancesSelected.send(sender=self, instances=instances) 513 events.onInstancesSelected.send(sender=self, instances=instances)
437 514
438 if event.getButton() == fife.MouseEvent.MIDDLE: 515 if event.getButton() == fife.MouseEvent.MIDDLE:
443 520
444 if self._undogroup: 521 if self._undogroup:
445 self._controller.getUndoManager().endGroup() 522 self._controller.getUndoManager().endGroup()
446 self._undogroup = False 523 self._undogroup = False
447 524
448 self._dragx = NOT_INITIALIZED
449 self._dragy = NOT_INITIALIZED
450
451 def mouseMoved(self, sender, event): 525 def mouseMoved(self, sender, event):
452 pass 526 pass
453 527
454 def mouseEntered(self, sender, event): 528 def mouseEntered(self, sender, event):
455 self._setCursor() 529 # Mouse has entered map area. Set cursor to reflect current mode
530 self._updateCursor()
456 531
457 def mouseExited(self, sender, event): 532 def mouseExited(self, sender, event):
533 # Mouse has exited the map area. Set the cursor to native arrow
458 self._resetCursor() 534 self._resetCursor()
459 535
460 def mouseWheelMovedUp(self, event): 536 def mouseWheelMovedUp(self, event):
537 # Zoom in
461 if self._eventlistener.controlPressed and self._controller._camera: 538 if self._eventlistener.controlPressed and self._controller._camera:
462 self._controller._camera.setZoom(self._controller._camera.getZoom() * 1.10) 539 self._controller._camera.setZoom(self._controller._camera.getZoom() * 1.10)
463 540
464 def mouseWheelMovedDown(self, event): 541 def mouseWheelMovedDown(self, event):
542 # Zoom out
465 if self._eventlistener.controlPressed and self._controller._camera: 543 if self._eventlistener.controlPressed and self._controller._camera:
466 self._controller._camera.setZoom(self._controller._camera.getZoom() / 1.10) 544 self._controller._camera.setZoom(self._controller._camera.getZoom() / 1.10)
467
468 545
469 def keyPressed(self, event): 546 def keyPressed(self, event):
470 keyval = event.getKey().getValue() 547 keyval = event.getKey().getValue()
471 keystr = event.getKey().getAsString().lower() 548 keystr = event.getKey().getAsString().lower()
472 549
487 564
488 elif keyval == fife.Key.F7: 565 elif keyval == fife.Key.F7:
489 self.captureScreen() 566 self.captureScreen()
490 567
491 elif keystr == "s": 568 elif keystr == "s":
492 self._setMode(SELECTING) 569 self._setMode(MapEditor.SELECTING)
493 570
494 elif keystr == "i": 571 elif keystr == "i":
495 if self._mode != INSERTING: 572 if self._mode != MapEditor.INSERTING:
496 self._setMode(INSERTING) 573 self._setMode(INSERTING)
497 else: 574 else:
498 self._setMode(SELECTING) 575 self._setMode(MapEditor.SELECTING)
499 576
500 elif keystr == "r": 577 elif keystr == "r":
501 if self._mode != REMOVING: 578 if self._mode != MapEditor.REMOVING:
502 self._setMode(REMOVING) 579 self._setMode(MapEditor.REMOVING)
503 else: 580 else:
504 self._setMode(SELECTING) 581 self._setMode(MapEditor.SELECTING)
505 582
506 elif keystr == 'm': 583 elif keystr == 'm':
507 if self._mode != MOVING: 584 if self._mode != MapEditor.MOVING:
508 self._setMode(MOVING) 585 self._setMode(MapEditor.MOVING)
509 else: 586 else:
510 self._setMode(SELECTING) 587 self._setMode(MapEditor.SELECTING)
511 588
512 elif keystr == 't': 589 elif keystr == 't':
513 gridrenderer = self._controller._camera.getRenderer('GridRenderer') 590 gridrenderer = self._controller._camera.getRenderer('GridRenderer')
514 gridrenderer.setEnabled(not gridrenderer.isEnabled()) 591 gridrenderer.setEnabled(not gridrenderer.isEnabled())
515 592
532 609
533 610
534 def keyReleased(self, event): 611 def keyReleased(self, event):
535 pass 612 pass
536 613
537 def zoomIn(self, zoom=1.10):
538 self._controller.setZoom(self._controller.getZoom()*zoom)
539
540 def zoomOut(self, zoom=1.10):
541 self._controller.setZoom(self._controller.getZoom()/zoom)
542
543 def resetZoom(self):
544 self._controller.setZoom(1)
545
546 def rotateCounterClockwise(self):
547 self._controller.rotateCounterClockwise()
548
549 def rotateClockwise(self):
550 self._controller.rotateClockwise()
551
552 def _getRealCoords(self, sender, event): 614 def _getRealCoords(self, sender, event):
615 """ Converts relative widget coordinate to absolute coordinates """
553 cw = sender 616 cw = sender
554 offsetX = event.getX() 617 offsetX = event.getX()
555 offsetY = event.getY() 618 offsetY = event.getY()
556 619
557 parent = cw 620 parent = cw
563 else: 626 else:
564 break 627 break
565 628
566 return (offsetX, offsetY) 629 return (offsetX, offsetY)
567 630
568 def captureScreen(self):
569 userDir = fife_utils.getUserDataDirectory("fife", "editor")
570 t = userDir+"/screenshots"
571 if not os.path.isdir(t):
572 os.makedirs(t)
573 t += "/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
574 time.strftime('%H-%M-%S'))
575
576 self._editor.getEngine().getRenderBackend().captureScreen(t)
577 print "Saved screenshot to:", t
578
579 def pump(self): 631 def pump(self):
632 """ Called each frame """
633 # Scroll camera
580 self._controller.moveCamera(self._scrollX, self._scrollY) 634 self._controller.moveCamera(self._scrollX, self._scrollY)