Mercurial > fife-parpg
changeset 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 | 14e8087cde2c |
children | 6dace911ac2d |
files | tools/editor/scripts/gui/mapeditor.py |
diffstat | 1 files changed, 183 insertions(+), 129 deletions(-) [+] |
line wrap: on
line diff
--- a/tools/editor/scripts/gui/mapeditor.py Wed Feb 03 20:04:39 2010 +0000 +++ b/tools/editor/scripts/gui/mapeditor.py Sat Feb 06 18:50:36 2010 +0000 @@ -21,14 +21,27 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # #################################################################### -# MapEditor is a plugin for Fifedit. It allows for selection and visual editing of maps. +""" +Visual Map Editor +================= + +The map editor provides the user with an interface for editing +maps visually. -import math, os, time +To edit a map through code, use MapController. + +""" + +import math +import os +import time from datetime import date from fife import fife from fife.extensions import pychan import fife.extensions.pychan.widgets as widgets +from fife.extensions import fife_utils + import scripts import scripts.events as events import action @@ -36,48 +49,75 @@ from menubar import Menu, MenuBar from action import Action, ActionGroup from scripts.mapcontroller import MapController -from fife.extensions import fife_utils - -states = (u'SELECTING', u'INSERTING', u'REMOVING', u'MOVING', u'OBJECTPICKER') -for s in states: - globals()[s] = s -NOT_INITIALIZED = -9999999 class MapEditor: - def __init__(self): + """ This class provides a basic user interface for map editing. It allows the user + to visually edit a map. + """ + + # Editor states + SELECTING = u"Selecting" + INSERTING = u"Inserting" + REMOVING = u"Removing" + MOVING = u"Moving" + OBJECTPICKER = u"Objectpicking" + + def __init__(self): + """ Set up all variables and call some initial functions """ self._ignoreToggles = False # A hack to avoid infinite recursion when toggling a button self._controller = None - self._mode = SELECTING + self._mode = MapEditor.SELECTING + self._debug = False # TODO: We should have a central system for activating debug messages + # GUI self._editor = scripts.editor.getEditor() self._eventlistener = self._editor.getEventListener() self._statusbar = self._editor.getStatusBar() self._toolbar = self._editor.getToolBar() - self._object = None - self._startDragPos = None - self._lastDragPos = None - self._lastDragPosExact = None - self._toolbox = self._editor.getToolbox() - self._initToolbuttons() + # Currently selected object type + self._object = None + + # Variables used for moving instances + self._last_drag_pos = None + self._last_drag_pos_exact = None + + self._selected_instances = [] + self._undogroup = False + + # Variables for scrolling the map + self._dragx = 0 + self._dragy = 0 + self._scrollX = 0 + self._scrollY = 0 + + self._initToolboxButtons() self._toolbox.show() - self._instances = [] events.postMapShown.connect(self._mapChanged) events.preMapClosed.connect(self._mapClosed) events.onObjectSelected.connect(self.setObject) - self._undogroup = False + + def setObject(self, object): + """ Set the object type to be paint onto map """ + self._object = object - self._scrollX = 0 - self._scrollY = 0 + def setController(self, controller): + """ Set the controller to use. """ + if self._controller is not None: + self._clear() + + self._controller = controller + + if self._controller is not None: + self._init() def _init(self): - self._dragx = NOT_INITIALIZED - self._dragy = NOT_INITIALIZED - - self._setMode(SELECTING) + """ Sets up the mapeditor to work with the selected controller """ + self._debug = self._controller.debug + self._setMode(MapEditor.SELECTING) self._initToolbarbuttons() @@ -95,6 +135,7 @@ events.onPump.connect(self.pump) def _clear(self): + """ Remove any functionality set up by _init """ self._clearToolbarButtons() events.keyPressed.disconnect(self.keyPressed) @@ -111,37 +152,47 @@ events.onPump.disconnect(self.pump) def _mapChanged(self, sender, mapview): + """ Called when a new map is selected. + Sets the mapeditor to control the mapcontroller in the new map + """ self.setController(mapview.getController()) def _mapClosed(self, sender, mapview): - self.setController(None) + """ Called when a map is closed. """ + if mapview.getMap().getId() == self._controller.getMap().getId(): + self.setController(None) - def _setCursor(self): + def _updateCursor(self): + """ Updates the cursor to reflect the mode of the editor """ engine = self._editor.getEngine() cursor = engine.getCursor() id = -1 - if self._mode == SELECTING: + if self._mode == MapEditor.SELECTING: id = engine.getImagePool().addResourceFromFile("gui/icons/select_instance.png") image = engine.getImagePool().getImage(id) image.setXShift(-7) image.setYShift(-7) - elif self._mode == INSERTING: + + elif self._mode == MapEditor.INSERTING: id = engine.getImagePool().addResourceFromFile("gui/icons/add_instance.png") image = engine.getImagePool().getImage(id) image.setXShift(-2) image.setYShift(-20) - elif self._mode == REMOVING: + + elif self._mode == MapEditor.REMOVING: id = engine.getImagePool().addResourceFromFile("gui/icons/erase_instance.png") image = engine.getImagePool().getImage(id) image.setXShift(-2) image.setYShift(-19) - elif self._mode == MOVING: + + elif self._mode == MapEditor.MOVING: id = engine.getImagePool().addResourceFromFile("gui/icons/move_instance.png") image = engine.getImagePool().getImage(id) image.setXShift(-11) image.setYShift(-11) - elif self._mode == OBJECTPICKER: + + elif self._mode == MapEditor.OBJECTPICKER: id = engine.getImagePool().addResourceFromFile("gui/icons/objectpicker.png") image = engine.getImagePool().getImage(id) image.setXShift(-0) @@ -153,22 +204,13 @@ cursor.set(fife.CURSOR_IMAGE, id) def _resetCursor(self): + """ Reset the cursor to the standard native one """ cursor = self._editor.getEngine().getCursor() cursor.set(fife.CURSOR_NATIVE, fife.NC_ARROW) - def setObject(self, object): - self._object = object + def _initToolboxButtons(self): + """ Sets up and connects buttons related to the toolbox """ - def setController(self, controller): - if self._controller is not None: - self._clear() - - if controller is not None: - self._init() - - self._controller = controller - - def _initToolbuttons(self): self._selectAction = Action(text=u"Select", icon="gui/icons/select_instance.png", checkable=True) self._drawAction = Action(text=u"Draw", icon="gui/icons/add_instance.png", checkable=True) self._removeAction = Action(text=u"Remove", icon="gui/icons/erase_instance.png", checkable=True) @@ -194,13 +236,14 @@ self._toolgroup.addAction(self._removeAction) self._toolgroup.addAction(self._objectpickerAction) - self._toolbox.addAction(self._toolgroup) self._toolbox.adaptLayout() self._editor._edit_menu.addAction(self._toolgroup) def _initToolbarbuttons(self): + """ Sets up and connects buttons related to the toolbar """ + rotateLeftAction = Action(text=u"Rotate counterclockwise", icon="gui/icons/rotate_countercw.png") rotateRightAction = Action(text=u"Rotate clockwise", icon="gui/icons/rotate_clockwise.png") zoomInAction = Action(text=u"Zoom in", icon="gui/icons/zoom_in.png") @@ -215,12 +258,12 @@ zoomResetAction.helptext = u"Reset zoom to default level" screenshotAction.helptext = u"Take screenshot (F7)" - action.activated.connect(self.rotateCounterClockwise, sender=rotateLeftAction) - action.activated.connect(self.rotateClockwise, sender=rotateRightAction) - action.activated.connect(self.zoomIn, sender=zoomInAction) - action.activated.connect(self.zoomOut, sender=zoomOutAction) - action.activated.connect(self.resetZoom, sender=zoomResetAction) - action.activated.connect(self.captureScreen, sender=screenshotAction) + action.activated.connect(self._rotateCounterClockwise, sender=rotateLeftAction) + action.activated.connect(self._rotateClockwise, sender=rotateRightAction) + action.activated.connect(self._zoomIn, sender=zoomInAction) + action.activated.connect(self._zoomOut, sender=zoomOutAction) + action.activated.connect(self._resetZoom, sender=zoomResetAction) + action.activated.connect(self._captureScreen, sender=screenshotAction) self._viewGroup = ActionGroup(name=u"View group") self._viewGroup.addAction(rotateLeftAction) @@ -234,52 +277,84 @@ self._toolbar.adaptLayout() def _clearToolbarButtons(self): + """ Remove toolbar buttons """ self._toolbar.removeAction(self._viewGroup) self._toolbar.adaptLayout() self._viewGroup = None - def _setMode(self, mode): - if (mode == INSERTING) and (not self._object): + """ Set the editor mode """ + if (mode == MapEditor.INSERTING) and (not self._object): self._statusbar.setText(u'Please select object first') mode = self._mode self._ignoreToggles = True # Update toolbox buttons - if (mode == INSERTING): + if (mode == MapEditor.INSERTING): self._drawAction.setChecked(True) - elif mode == REMOVING: + elif mode == MapEditor.REMOVING: self._removeAction.setChecked(True) - elif mode == MOVING: + elif mode == MapEditor.MOVING: self._moveAction.setChecked(True) - elif mode == OBJECTPICKER: + elif mode == MapEditor.OBJECTPICKER: self._objectpickerAction.setChecked(True) else: self._selectAction.setChecked(True) self._ignoreToggles = False self._mode = mode - print "Entered mode " + mode - self._statusbar.setText(mode.replace('_', ' ').capitalize()) - self._setCursor() + if self._debug: print "Entered mode " + mode + self._statusbar.setText(mode) + self._updateCursor() + + def _zoomIn(self, zoom=1.10): + self._controller.setZoom(self._controller.getZoom()*zoom) + + def _zoomOut(self, zoom=1.10): + self._controller.setZoom(self._controller.getZoom()/zoom) + + def _resetZoom(self): + """ Resets zoom level to 1:1 """ + self._controller.setZoom(1) + + def _rotateCounterClockwise(self): + """ Rotates map counterclockwise """ + self._controller.rotateCounterClockwise() + + def _rotateClockwise(self): + """ Rotates map clockwise """ + self._controller.rotateClockwise() + + def _captureScreen(self): + """ Saves a screenshot to the users data directory """ + userDir = fife_utils.getUserDataDirectory("fife", "editor") + t = userDir+"/screenshots" + if not os.path.isdir(t): + os.makedirs(t) + t += "/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'), + time.strftime('%H-%M-%S')) + + self._editor.getEngine().getRenderBackend().captureScreen(t) + print "Saved screenshot to:", t def _buttonToggled(self, sender, toggled): + """ Called when a button controlling the editor mode was activated """ if self._controller is None: return if self._ignoreToggles is True: return - mode = SELECTING + mode = MapEditor.SELECTING if toggled: if sender == self._selectAction: - mode = SELECTING + mode = MapEditor.SELECTING elif sender == self._moveAction: - mode = MOVING + mode = MapEditor.MOVING elif sender == self._drawAction: - mode = INSERTING + mode = MapEditor.INSERTING elif sender == self._removeAction: - mode = REMOVING + mode = MapEditor.REMOVING elif sender == self._objectpickerAction: - mode = OBJECTPICKER + mode = MapEditor.OBJECTPICKER self._setMode(mode) @@ -288,7 +363,7 @@ return if not self._controller._layer: - if self._controller.debug: print 'No layers active. Cancelling map action' + if self._debug: print 'No layers active. Cancelling map action' return realCoords = self._getRealCoords(sender, event) @@ -301,7 +376,7 @@ if event.getButton() == fife.MouseEvent.RIGHT: self._controller.deselectSelection() - if self._mode == SELECTING: + if self._mode == MapEditor.SELECTING: if event.getButton() == fife.MouseEvent.LEFT: if self._eventlistener.shiftPressed: self._controller.deselectCell(realCoords[0], realCoords[1]) @@ -313,7 +388,7 @@ elif event.getButton() == fife.MouseEvent.RIGHT: self._controller.deselectSelection() - elif self._mode == INSERTING: + elif self._mode == MapEditor.INSERTING: if event.getButton() == fife.MouseEvent.LEFT: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) @@ -326,7 +401,7 @@ self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.placeInstance(position, self._object) - elif self._mode == REMOVING: + elif self._mode == MapEditor.REMOVING: if event.getButton() == fife.MouseEvent.LEFT: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) @@ -335,27 +410,27 @@ self._controller.removeInstances(self._controller.getInstancesFromSelection()) - elif self._mode == MOVING: + elif self._mode == MapEditor.MOVING: if event.getButton() == fife.MouseEvent.LEFT: position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) - self._lastDragPos = self._controller._layer.getCellGrid().toLayerCoordinates(position) - self._lastDragPosExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) + self._last_drag_pos = self._controller._layer.getCellGrid().toLayerCoordinates(position) + self._last_drag_pos_exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) for loc in self._controller._selection: - if loc.getLayerCoordinates() == self._lastDragPos: + if loc.getLayerCoordinates() == self._last_drag_pos: break else: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) - self._instances = self._controller.getInstancesFromSelection() + self._selected_instances = self._controller.getInstancesFromSelection() self._controller.getUndoManager().startGroup("Moved instances") self._undogroup = True - elif self._mode == OBJECTPICKER: + elif self._mode == MapEditor.OBJECTPICKER: position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) exact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) instances = self._controller.getInstancesFromPosition(exact) @@ -369,7 +444,7 @@ return if not self._controller._layer: - if self._controller.debug: print 'No layers active. Cancelling map action' + if self._debug: print 'No layers active. Cancelling map action' return realCoords = self._getRealCoords(sender, event) @@ -377,49 +452,51 @@ if event.getButton() == fife.MouseEvent.MIDDLE: self._scrollX = (self._dragx-realCoords[0])/10.0 self._scrollY = (self._dragy-realCoords[1])/10.0 + else: - if self._mode != SELECTING: + if self._mode != MapEditor.SELECTING: self._controller.deselectSelection() - if self._mode == SELECTING: + if self._mode == MapEditor.SELECTING: if event.getButton() == fife.MouseEvent.LEFT: if self._eventlistener.shiftPressed: self._controller.deselectCell(realCoords[0], realCoords[1]) else: self._controller.selectCell(realCoords[0], realCoords[1]) - elif self._mode == INSERTING: + elif self._mode == MapEditor.INSERTING: position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) position = self._controller._layer.getCellGrid().toLayerCoordinates(position) self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.placeInstance(position, self._object) - elif self._mode == REMOVING: + elif self._mode == MapEditor.REMOVING: self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.removeInstances(self._controller.getInstancesFromSelection()) - elif self._mode == MOVING: + elif self._mode == MapEditor.MOVING: position = self._controller._camera.toMapCoordinates(fife.ScreenPoint(realCoords[0], realCoords[1]), False) positionExact = self._controller._layer.getCellGrid().toExactLayerCoordinates(position) position = self._controller._layer.getCellGrid().toLayerCoordinates(position) if self._eventlistener.shiftPressed: - self._controller.moveInstances(self._instances, positionExact-self._lastDragPosExact, True) + self._controller.moveInstances(self._selected_instances, positionExact-self._last_drag_pos_exact, True) else: - self._controller.moveInstances(self._instances, position-self._lastDragPos, False) - self._lastDragPos = position - self._lastDragPosExact = positionExact + self._controller.moveInstances(self._selected_instances, position-self._last_drag_pos, False) + self._last_drag_pos = position + self._last_drag_pos_exact = positionExact # Update selection self._controller.deselectSelection() - for i in self._instances: + for i in self._selected_instances: pos = i.getLocation().getMapCoordinates() pos = self._controller._camera.toScreenCoordinates(pos) self._controller.selectCell(pos.x, pos.y) - elif self._mode == OBJECTPICKER: + + elif self._mode == MapEditor.OBJECTPICKER: pass def mouseReleased(self, sender, event): @@ -427,10 +504,10 @@ return if not self._controller._layer: - if self._controller.debug: print 'No layers active. Cancelling map action' + if self._debug: print 'No layers active. Cancelling map action' return - if self._mode == SELECTING or self._mode == MOVING: + if self._mode == MapEditor.SELECTING or self._mode == MapEditor.MOVING: instances = self._controller.getInstancesFromSelection() if len(instances) > 0: events.onInstancesSelected.send(sender=self, instances=instances) @@ -445,27 +522,27 @@ self._controller.getUndoManager().endGroup() self._undogroup = False - self._dragx = NOT_INITIALIZED - self._dragy = NOT_INITIALIZED - def mouseMoved(self, sender, event): pass def mouseEntered(self, sender, event): - self._setCursor() + # Mouse has entered map area. Set cursor to reflect current mode + self._updateCursor() def mouseExited(self, sender, event): + # Mouse has exited the map area. Set the cursor to native arrow self._resetCursor() def mouseWheelMovedUp(self, event): + # Zoom in if self._eventlistener.controlPressed and self._controller._camera: self._controller._camera.setZoom(self._controller._camera.getZoom() * 1.10) def mouseWheelMovedDown(self, event): + # Zoom out if self._eventlistener.controlPressed and self._controller._camera: self._controller._camera.setZoom(self._controller._camera.getZoom() / 1.10) - def keyPressed(self, event): keyval = event.getKey().getValue() keystr = event.getKey().getAsString().lower() @@ -489,25 +566,25 @@ self.captureScreen() elif keystr == "s": - self._setMode(SELECTING) + self._setMode(MapEditor.SELECTING) elif keystr == "i": - if self._mode != INSERTING: + if self._mode != MapEditor.INSERTING: self._setMode(INSERTING) else: - self._setMode(SELECTING) + self._setMode(MapEditor.SELECTING) elif keystr == "r": - if self._mode != REMOVING: - self._setMode(REMOVING) + if self._mode != MapEditor.REMOVING: + self._setMode(MapEditor.REMOVING) else: - self._setMode(SELECTING) + self._setMode(MapEditor.SELECTING) elif keystr == 'm': - if self._mode != MOVING: - self._setMode(MOVING) + if self._mode != MapEditor.MOVING: + self._setMode(MapEditor.MOVING) else: - self._setMode(SELECTING) + self._setMode(MapEditor.SELECTING) elif keystr == 't': gridrenderer = self._controller._camera.getRenderer('GridRenderer') @@ -534,22 +611,8 @@ def keyReleased(self, event): pass - def zoomIn(self, zoom=1.10): - self._controller.setZoom(self._controller.getZoom()*zoom) - - def zoomOut(self, zoom=1.10): - self._controller.setZoom(self._controller.getZoom()/zoom) - - def resetZoom(self): - self._controller.setZoom(1) - - def rotateCounterClockwise(self): - self._controller.rotateCounterClockwise() - - def rotateClockwise(self): - self._controller.rotateClockwise() - def _getRealCoords(self, sender, event): + """ Converts relative widget coordinate to absolute coordinates """ cw = sender offsetX = event.getX() offsetY = event.getY() @@ -565,16 +628,7 @@ return (offsetX, offsetY) - def captureScreen(self): - userDir = fife_utils.getUserDataDirectory("fife", "editor") - t = userDir+"/screenshots" - if not os.path.isdir(t): - os.makedirs(t) - t += "/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'), - time.strftime('%H-%M-%S')) - - self._editor.getEngine().getRenderBackend().captureScreen(t) - print "Saved screenshot to:", t - def pump(self): + """ Called each frame """ + # Scroll camera self._controller.moveCamera(self._scrollX, self._scrollY) \ No newline at end of file