source: trunk/tools/editor/scripts/gui/mapeditor.py @ 3513

Revision 3513, 21.9 KB checked in by helios2000, 3 years ago (diff)
  • Property svn:eol-style set to native
  • Property svn:mergeinfo set to (toggle deleted branches)
    /branches/active/build_system_rework/tools/editor/scripts/gui/mapeditor.py3096-3157
    /branches/active/editor_rewrite/clients/editor/scripts/gui/mapeditor.py2781-2903
    /trunk/clients/editor/scripts/gui/mapeditor.py2779-2780
Line 
1# -*- coding: utf-8 -*-
2
3# ####################################################################
4#  Copyright (C) 2005-2009 by the FIFE team
5#  http://www.fifengine.de
6#  This file is part of FIFE.
7#
8#  FIFE is free software; you can redistribute it and/or
9#  modify it under the terms of the GNU Lesser General Public
10#  License as published by the Free Software Foundation; either
11#  version 2.1 of the License, or (at your option) any later version.
12#
13#  This library is distributed in the hope that it will be useful,
14#  but WITHOUT ANY WARRANTY; without even the implied warranty of
15#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16#  Lesser General Public License for more details.
17#
18#  You should have received a copy of the GNU Lesser General Public
19#  License along with this library; if not, write to the
20#  Free Software Foundation, Inc.,
21#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22# ####################################################################
23
24"""
25Visual Map Editor
26=================
27
28The map editor provides the user with an interface for editing
29maps visually.
30
31To edit a map through code, use MapController.
32
33"""
34
35import math
36import os
37import time
38from datetime import date
39
40from fife import fife
41from fife.extensions import pychan
42import fife.extensions.pychan.widgets as widgets
43from fife.extensions import fife_utils
44
45import scripts
46import scripts.events as events
47import action
48from toolbar import ToolBar
49from menubar import Menu, MenuBar
50from action import Action, ActionGroup
51from scripts.mapcontroller import MapController
52
53class MapEditor:
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 """
67      self._ignoreToggles = False # A hack to avoid infinite recursion when toggling a button
68      self._controller = None
69      self._mode = MapEditor.SELECTING
70      self._debug = False # TODO: We should have a central system for activating debug messages
71     
72      # GUI
73      self._editor = scripts.editor.getEditor()
74      self._eventlistener = self._editor.getEventListener()
75      self._statusbar = self._editor.getStatusBar()
76      self._toolbar = self._editor.getToolBar()
77      self._toolbox = self._editor.getToolbox()
78     
79      # Currently selected object type
80      self._object = None
81     
82      # Variables used for moving instances
83      self._last_drag_pos = None
84      self._last_drag_pos_exact = None
85     
86      self._selected_instances = []
87     
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()
97      self._toolbox.show()
98     
99      events.postMapShown.connect(self._mapChanged)
100      events.preMapClosed.connect(self._mapClosed)
101      events.onObjectSelected.connect(self.setObject)
102     
103   def setObject(self, object):
104      """ Set the object type to be paint onto map """
105      self._object = object
106
107   def getObject(self):
108      """ Return the current object """
109      return self._object
110
111   def setController(self, controller):
112      """ Set the controller to use. """
113      if self._controller is not None:
114         self._clear()
115         
116      self._controller = controller
117
118      if self._controller is not None:
119         self._init()
120     
121   def _init(self):
122      """ Sets up the mapeditor to work with the selected controller """
123      self._debug = self._controller.debug
124      self._setMode(MapEditor.SELECTING)
125     
126      self._initToolbarbuttons()
127     
128      events.keyPressed.connect(self.keyPressed)
129      events.keyReleased.connect(self.keyReleased)
130     
131      events.mousePressed.connect(self.mousePressed)
132      events.mouseDragged.connect(self.mouseDragged)
133      events.mouseReleased.connect(self.mouseReleased)
134      events.mouseMoved.connect(self.mouseMoved)
135      events.mouseEntered.connect(self.mouseEntered)
136      events.mouseExited.connect(self.mouseExited)
137      events.mouseWheelMovedUp.connect(self.mouseWheelMovedUp)
138      events.mouseWheelMovedDown.connect(self.mouseWheelMovedDown)
139      events.onPump.connect(self.pump)
140     
141   def _clear(self):
142      """ Remove any functionality set up by _init """
143      self._clearToolbarButtons()
144     
145      events.keyPressed.disconnect(self.keyPressed)
146      events.keyReleased.disconnect(self.keyReleased)
147     
148      events.mousePressed.disconnect(self.mousePressed)
149      events.mouseDragged.disconnect(self.mouseDragged)
150      events.mouseReleased.disconnect(self.mouseReleased)
151      events.mouseMoved.disconnect(self.mouseMoved)
152      events.mouseExited.disconnect(self.mouseExited)
153      events.mouseEntered.disconnect(self.mouseEntered)
154      events.mouseWheelMovedUp.disconnect(self.mouseWheelMovedUp)
155      events.mouseWheelMovedDown.disconnect(self.mouseWheelMovedDown)
156      events.onPump.disconnect(self.pump)
157     
158   def _mapChanged(self, sender, mapview):
159      """ Called when a new map is selected.
160         Sets the mapeditor to control the mapcontroller in the new map
161      """
162      self.setController(mapview.getController())
163     
164   def _mapClosed(self, sender, mapview):
165      """ Called when a map is closed. """
166      if mapview.getMap().getId() == self._controller.getMap().getId():
167         self.setController(None)
168     
169   def _updateCursor(self):
170      """ Updates the cursor to reflect the mode of the editor """
171      engine = self._editor.getEngine()
172      cursor = engine.getCursor()
173     
174      id = -1
175      if self._mode == MapEditor.SELECTING:
176         id = engine.getImagePool().addResourceFromFile("gui/icons/select_instance.png")
177         image = engine.getImagePool().getImage(id)
178         image.setXShift(-7)
179         image.setYShift(-7)
180         
181      elif self._mode == MapEditor.INSERTING:
182         id = engine.getImagePool().addResourceFromFile("gui/icons/add_instance.png")
183         image = engine.getImagePool().getImage(id)
184         image.setXShift(-2)
185         image.setYShift(-20)
186         
187      elif self._mode == MapEditor.REMOVING:
188         id = engine.getImagePool().addResourceFromFile("gui/icons/erase_instance.png")
189         image = engine.getImagePool().getImage(id)
190         image.setXShift(-2)
191         image.setYShift(-19)
192         
193      elif self._mode == MapEditor.MOVING:
194         id = engine.getImagePool().addResourceFromFile("gui/icons/move_instance.png")
195         image = engine.getImagePool().getImage(id)
196         image.setXShift(-11)
197         image.setYShift(-11)
198         
199      elif self._mode == MapEditor.OBJECTPICKER:
200         id = engine.getImagePool().addResourceFromFile("gui/icons/objectpicker.png")
201         image = engine.getImagePool().getImage(id)
202         image.setXShift(-0)
203         image.setYShift(-22)
204         
205      if id < 0:
206         self._resetCursor()
207      else:
208         cursor.set(fife.CURSOR_IMAGE, id)
209         
210   def _resetCursor(self):
211      """ Reset the cursor to the standard native one """
212      cursor = self._editor.getEngine().getCursor()
213      cursor.set(fife.CURSOR_NATIVE, fife.NC_ARROW)
214     
215   def _initToolboxButtons(self):
216      """ Sets up and connects buttons related to the toolbox """
217     
218      self._selectAction = Action(text=u"Select", icon="gui/icons/select_instance.png", checkable=True)
219      self._drawAction = Action(text=u"Draw", icon="gui/icons/add_instance.png", checkable=True)
220      self._removeAction = Action(text=u"Remove", icon="gui/icons/erase_instance.png", checkable=True)
221      self._moveAction = Action(text=u"Move", icon="gui/icons/move_instance.png", checkable=True)
222      self._objectpickerAction = Action(text=u"Pick object", icon="gui/icons/objectpicker.png", checkable=True)
223     
224      self._selectAction.helptext = u"Select cells on layer  (S)"
225      self._moveAction.helptext = u"Moves instances   (M)"
226      self._drawAction.helptext = u"Adds new instances based on currently selected object   (I)"
227      self._removeAction.helptext = u"Deletes instances   (R)"
228      self._objectpickerAction.helptext = u"Click an instance to set the current object to the one used by instance"
229     
230      action.toggled.connect(self._buttonToggled, sender=self._selectAction)
231      action.toggled.connect(self._buttonToggled, sender=self._moveAction)
232      action.toggled.connect(self._buttonToggled, sender=self._drawAction)
233      action.toggled.connect(self._buttonToggled, sender=self._removeAction)
234      action.toggled.connect(self._buttonToggled, sender=self._objectpickerAction)
235     
236      self._toolgroup = ActionGroup(exclusive=True, name=u"Tool group")
237      self._toolgroup.addAction(self._selectAction)
238      self._toolgroup.addAction(self._moveAction)
239      self._toolgroup.addAction(self._drawAction)
240      self._toolgroup.addAction(self._removeAction)
241      self._toolgroup.addAction(self._objectpickerAction)
242     
243      self._toolbox.addAction(self._toolgroup)
244      self._toolbox.adaptLayout()
245     
246      self._editor._edit_menu.addAction(self._toolgroup)
247     
248   def _initToolbarbuttons(self):
249      """ Sets up and connects buttons related to the toolbar """
250   
251      rotateLeftAction = Action(text=u"Rotate counterclockwise", icon="gui/icons/rotate_countercw.png")
252      rotateRightAction = Action(text=u"Rotate clockwise", icon="gui/icons/rotate_clockwise.png")
253      zoomInAction = Action(text=u"Zoom in", icon="gui/icons/zoom_in.png")
254      zoomOutAction = Action(text=u"Zoom out", icon="gui/icons/zoom_out.png")
255      zoomResetAction = Action(text=u"Reset zoom", icon="gui/icons/zoom_default.png")
256      screenshotAction = Action(text=u"Take screenshot", icon="gui/icons/take_screenshot.png")
257     
258      rotateLeftAction.helptext = u"Rotate counterclockwise by 90 degrees"
259      rotateRightAction.helptext = u"Rotate clockwise by 90 degrees"
260      zoomInAction.helptext = u"Zoom in   (CTRL + Mousewheel up)"
261      zoomOutAction.helptext = u"Zoom out   (CTRL + Mousewheel down)"
262      zoomResetAction.helptext = u"Reset zoom to default level"
263      screenshotAction.helptext = u"Take screenshot   (F7)"
264     
265      action.activated.connect(self._rotateCounterClockwise, sender=rotateLeftAction)
266      action.activated.connect(self._rotateClockwise, sender=rotateRightAction)
267      action.activated.connect(self._zoomIn, sender=zoomInAction)
268      action.activated.connect(self._zoomOut, sender=zoomOutAction)
269      action.activated.connect(self._resetZoom, sender=zoomResetAction)
270      action.activated.connect(self._captureScreen, sender=screenshotAction)
271   
272      self._viewGroup = ActionGroup(name=u"View group")
273      self._viewGroup.addAction(rotateLeftAction)
274      self._viewGroup.addAction(rotateRightAction)
275      self._viewGroup.addAction(zoomInAction)
276      self._viewGroup.addAction(zoomOutAction)
277      self._viewGroup.addAction(zoomResetAction)
278      self._viewGroup.addAction(screenshotAction)
279     
280      self._toolbar.addAction(self._viewGroup)
281      self._toolbar.adaptLayout()
282     
283   def _clearToolbarButtons(self):
284      """ Remove toolbar buttons """
285      self._toolbar.removeAction(self._viewGroup)
286      self._toolbar.adaptLayout()
287      self._viewGroup = None
288     
289   def _setMode(self, mode):
290      """ Set the editor mode """
291      if (mode == MapEditor.INSERTING) and (not self._object):
292         self._statusbar.setText(u'Please select object first')
293         mode = self._mode
294
295      self._ignoreToggles = True
296      # Update toolbox buttons
297      if (mode == MapEditor.INSERTING):
298         self._drawAction.setChecked(True)
299      elif mode == MapEditor.REMOVING:
300         self._removeAction.setChecked(True)
301      elif mode == MapEditor.MOVING:
302         self._moveAction.setChecked(True)
303      elif mode == MapEditor.OBJECTPICKER:
304         self._objectpickerAction.setChecked(True)
305      else:
306         self._selectAction.setChecked(True)
307      self._ignoreToggles = False
308
309      self._mode = mode
310      if self._debug: print "Entered mode " + mode
311      self._statusbar.setText(mode)
312      self._updateCursor()
313     
314   def _zoomIn(self, zoom=1.10):
315      self._controller.setZoom(self._controller.getZoom()*zoom)
316     
317   def _zoomOut(self, zoom=1.10):
318      self._controller.setZoom(self._controller.getZoom()/zoom)
319     
320   def _resetZoom(self):
321      """ Resets zoom level to 1:1 """
322      self._controller.setZoom(1)
323     
324   def _rotateCounterClockwise(self):
325      """ Rotates map counterclockwise """
326      self._controller.rotateCounterClockwise()
327     
328   def _rotateClockwise(self):
329      """ Rotates map clockwise """
330      self._controller.rotateClockwise()
331     
332   def _captureScreen(self):
333      """ Saves a screenshot to the users data directory """
334      userDir = fife_utils.getUserDataDirectory("fife", "editor")
335      t = userDir+"/screenshots"
336      if not os.path.isdir(t):
337         os.makedirs(t)
338      t += "/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
339                           time.strftime('%H-%M-%S'))
340     
341      self._editor.getEngine().getRenderBackend().captureScreen(t)
342      print "Saved screenshot to:", t     
343     
344   def _buttonToggled(self, sender, toggled):
345      """ Called when a button controlling the editor mode was activated """
346      if self._controller is None: return
347      if self._ignoreToggles is True: return
348   
349      mode = MapEditor.SELECTING
350     
351      if toggled:
352         if sender == self._selectAction:
353            mode = MapEditor.SELECTING
354         elif sender == self._moveAction:
355            mode = MapEditor.MOVING
356         elif sender == self._drawAction:
357            mode = MapEditor.INSERTING
358         elif sender == self._removeAction:
359            mode = MapEditor.REMOVING
360         elif sender == self._objectpickerAction:
361            mode = MapEditor.OBJECTPICKER
362
363      self._setMode(mode)
364     
365   def mousePressed(self, sender, event):
366      if event.isConsumedByWidgets():
367         return
368         
369      if not self._controller._layer:
370         if self._debug: print 'No layers active. Cancelling map action'
371         return
372
373      realCoords = self._getRealCoords(sender, event)
374
375      if event.getButton() == fife.MouseEvent.MIDDLE:
376         self._dragx = realCoords[0]
377         self._dragy = realCoords[1]
378         
379      else:
380         if event.getButton() == fife.MouseEvent.RIGHT:
381            self._controller.deselectSelection()
382           
383         if self._mode == MapEditor.SELECTING:
384            if event.getButton() == fife.MouseEvent.LEFT:
385               if self._eventlistener.shiftPressed:
386                  self._controller.deselectCell(realCoords[0], realCoords[1])
387               else:
388                  if self._eventlistener.controlPressed is False:
389                     self._controller.deselectSelection()
390                  self._controller.selectCell(realCoords[0], realCoords[1])
391               
392            elif event.getButton() == fife.MouseEvent.RIGHT:
393               self._controller.deselectSelection()
394               
395         elif self._mode == MapEditor.INSERTING:
396            if event.getButton() == fife.MouseEvent.LEFT:
397               self._controller.deselectSelection()
398               self._controller.selectCell(realCoords[0], realCoords[1])
399               self._controller.getUndoManager().startGroup("Inserted instances")
400               self._undogroup = True
401               
402               position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
403               position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
404               
405               self._controller.selectCell(realCoords[0], realCoords[1])
406               self._controller.placeInstance(position, self._object)
407           
408         elif self._mode == MapEditor.REMOVING:
409            if event.getButton() == fife.MouseEvent.LEFT:
410               self._controller.deselectSelection()
411               self._controller.selectCell(realCoords[0], realCoords[1])
412               self._controller.getUndoManager().startGroup("Removed instances")
413               self._undogroup = True
414               
415               self._controller.removeInstances(self._controller.getInstancesFromSelection())
416           
417         elif self._mode == MapEditor.MOVING:
418            if event.getButton() == fife.MouseEvent.LEFT:
419           
420               position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
421
422               self._last_drag_pos = self._controller._layer.getCellGrid().toLayerCoordinates(position)
423               self._last_drag_pos_exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
424   
425               for loc in self._controller._selection:
426                  if loc.getLayerCoordinates() == self._last_drag_pos:
427                     break
428               else:
429                  self._controller.deselectSelection()
430                  self._controller.selectCell(realCoords[0], realCoords[1])
431                 
432               self._selected_instances = self._controller.getInstancesFromSelection()
433               
434               self._controller.getUndoManager().startGroup("Moved instances")
435               self._undogroup = True
436               
437         elif self._mode == MapEditor.OBJECTPICKER:
438            position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
439            exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
440            instances = self._controller.getInstancesFromPosition(exact)
441            if len(instances) >= 1:
442               object = instances[0].getObject()
443               if object.getId() != self._object.getId() or object.getNamespace() != self._object.getNamespace():
444                  events.onObjectSelected.send(sender=self, object=object)
445
446   def mouseDragged(self, sender, event):
447      if event.isConsumedByWidgets():
448         return
449         
450      if not self._controller._layer:
451         if self._debug: print 'No layers active. Cancelling map action'
452         return
453         
454      realCoords = self._getRealCoords(sender, event)
455         
456      if event.getButton() == fife.MouseEvent.MIDDLE:
457         self._scrollX = (self._dragx-realCoords[0])/10.0
458         self._scrollY = (self._dragy-realCoords[1])/10.0
459         
460      else:
461         if self._mode != MapEditor.SELECTING:
462            self._controller.deselectSelection()
463           
464         if self._mode == MapEditor.SELECTING:
465            if event.getButton() == fife.MouseEvent.LEFT:
466               if self._eventlistener.shiftPressed:
467                  self._controller.deselectCell(realCoords[0], realCoords[1])
468               else:
469                  self._controller.selectCell(realCoords[0], realCoords[1])
470               
471         elif self._mode == MapEditor.INSERTING:
472            position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
473            position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
474           
475            self._controller.selectCell(realCoords[0], realCoords[1])
476            self._controller.placeInstance(position, self._object)
477           
478         elif self._mode == MapEditor.REMOVING:
479            self._controller.selectCell(realCoords[0], realCoords[1])
480            self._controller.removeInstances(self._controller.getInstancesFromSelection())
481           
482         elif self._mode == MapEditor.MOVING:
483            position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False)
484           
485            positionExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position)
486            position = self._controller._layer.getCellGrid().toLayerCoordinates(position)
487           
488            if self._eventlistener.shiftPressed:
489               self._controller.moveInstances(self._selected_instances, positionExact-self._last_drag_pos_exact, True)
490            else:
491               self._controller.moveInstances(self._selected_instances, position-self._last_drag_pos, False)
492            self._last_drag_pos = position
493            self._last_drag_pos_exact = positionExact
494           
495            # Update selection
496            self._controller.deselectSelection()
497           
498            for i in self._selected_instances:
499               pos = i.getLocation().getMapCoordinates()
500               pos = self._controller._camera.toScreenCoordinates(pos)
501               self._controller.selectCell(pos.x, pos.y)
502               
503         elif self._mode == MapEditor.OBJECTPICKER:
504            pass
505
506   def mouseReleased(self, sender, event):
507      if event.isConsumedByWidgets():
508         return
509         
510      if not self._controller._layer:
511         if self._debug: print 'No layers active. Cancelling map action'
512         return
513         
514      if self._mode == MapEditor.SELECTING or self._mode == MapEditor.MOVING:
515         instances = self._controller.getInstancesFromSelection()
516         if len(instances) > 0:
517            events.onInstancesSelected.send(sender=self, instances=instances)
518         
519      if event.getButton() == fife.MouseEvent.MIDDLE:
520         self._scrollX = 0
521         self._scrollY = 0
522         
523      realCoords = self._getRealCoords(sender, event)
524
525      if self._undogroup:
526         self._controller.getUndoManager().endGroup()
527         self._undogroup = False
528
529   def mouseMoved(self, sender, event):
530      pass
531     
532   def mouseEntered(self, sender, event):
533      # Mouse has entered map area. Set cursor to reflect current mode
534      self._updateCursor()
535     
536   def mouseExited(self, sender, event):
537      # Mouse has exited the map area. Set the cursor to native arrow
538      self._resetCursor()
539           
540   def mouseWheelMovedUp(self, event):
541      # Zoom in
542      if self._eventlistener.controlPressed and self._controller._camera:
543         self._controller._camera.setZoom(self._controller._camera.getZoom() * 1.10)
544
545   def mouseWheelMovedDown(self, event):
546      # Zoom out
547      if self._eventlistener.controlPressed and self._controller._camera:
548         self._controller._camera.setZoom(self._controller._camera.getZoom() / 1.10)
549
550   def keyPressed(self, event):
551      keyval = event.getKey().getValue()
552      keystr = event.getKey().getAsString().lower()
553     
554      if keyval == fife.Key.LEFT:
555         self._controller.moveCamera(50, 0)
556      elif keyval == fife.Key.RIGHT:
557         self._controller.moveCamera(-50, 0)
558      elif keyval == fife.Key.UP:
559         self._controller.moveCamera(0, 50)
560      elif keyval == fife.Key.DOWN:
561         self._controller.moveCamera(0, -50)
562     
563      elif keyval == fife.Key.INSERT:
564         self._controller.fillSelection(self._object)
565
566      elif keyval == fife.Key.DELETE:
567         self._controller.clearSelection()
568         
569      elif keyval == fife.Key.F7:
570         self.captureScreen()
571         
572      elif keystr == "s":
573         self._setMode(MapEditor.SELECTING)
574         
575      elif keystr == "i":
576         if self._mode != MapEditor.INSERTING:
577            self._setMode(MapEditor.INSERTING)
578         else:
579            self._setMode(MapEditor.SELECTING)
580         
581      elif keystr == "r":
582         if self._mode != MapEditor.REMOVING:
583            self._setMode(MapEditor.REMOVING)
584         else:
585            self._setMode(MapEditor.SELECTING)
586
587      elif keystr == 'm':
588         if self._mode != MapEditor.MOVING:
589            self._setMode(MapEditor.MOVING)
590         else:
591            self._setMode(MapEditor.SELECTING)
592
593      elif keystr == 't':
594         gridrenderer = self._controller._camera.getRenderer('GridRenderer')
595         gridrenderer.setEnabled(not gridrenderer.isEnabled())
596
597      elif keystr == 'b':
598         blockrenderer = self._controller._camera.getRenderer('BlockingInfoRenderer')
599         blockrenderer.setEnabled(not blockrenderer.isEnabled())
600
601      elif keystr == 'c':
602         self._editor.toggleCoordinates("Toggle Coordinates")
603         
604      elif keystr == 'z':
605         if self._eventlistener.controlPressed:
606            if self._eventlistener.altPressed:
607               if self._eventlistener.shiftPressed:
608                  self._controller.getUndoManager().previousBranch()
609               else:
610                  self._controller.getUndoManager().nextBranch()
611            else:
612               if self._eventlistener.shiftPressed:
613                  self._controller.redo()
614               else:
615                  self._controller.undo()
616         
617
618   def keyReleased(self, event):   
619      pass
620     
621   def _getRealCoords(self, sender, event):
622      """ Converts relative widget coordinate to absolute coordinates """
623      cw = sender
624      offsetX = event.getX()
625      offsetY = event.getY()
626     
627      parent = cw
628      while parent is not None:
629         if isinstance(parent, widgets.Widget):
630            offsetX += parent.x
631            offsetY += parent.y
632            parent = parent.parent
633         else:
634            break
635         
636      return (offsetX, offsetY)
637     
638   def pump(self):
639      """ Called each frame """
640      # Scroll camera
641      self._controller.moveCamera(self._scrollX, self._scrollY)
Note: See TracBrowser for help on using the repository browser.