Mercurial > fife-parpg
view clients/editor/scripts/gui/mapeditor.py @ 255:51cc05d862f2
Merged editor_rewrite branch to trunk.
This contains changes that may break compatibility against existing clients.
For a list of changes that may affect your client, see: http://wiki.fifengine.de/Changes_to_pychan_and_FIFE_in_editor_rewrite_branch
author | cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 08 Jun 2009 16:00:02 +0000 |
parents | |
children | f2195628947b |
line wrap: on
line source
# MapEditor is a plugin for Fifedit. It allows for selection and visual editing of maps. import math import fife import pychan import pychan.widgets as widgets import scripts import scripts.events as events import action from toolbar import ToolBar from menubar import Menu, MenuBar from action import Action, ActionGroup from scripts.mapcontroller import MapController 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): self._ignoreToggles = False # A hack to avoid infinite recursion when toggling a button self._controller = None self._mode = SELECTING 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() self._toolbox.show() self._instances = [] events.postMapShown.connect(self._mapChanged) events.onObjectSelected.connect(self.setObject) self._undogroup = False self._scrollX = 0 self._scrollY = 0 def _init(self): self._dragx = NOT_INITIALIZED self._dragy = NOT_INITIALIZED self._setMode(SELECTING) self._initToolbarbuttons() events.keyPressed.connect(self.keyPressed) events.keyReleased.connect(self.keyReleased) events.mousePressed.connect(self.mousePressed) events.mouseDragged.connect(self.mouseDragged) events.mouseReleased.connect(self.mouseReleased) events.mouseMoved.connect(self.mouseMoved) events.mouseWheelMovedUp.connect(self.mouseWheelMovedUp) events.mouseWheelMovedDown.connect(self.mouseWheelMovedDown) events.mouseExited.connect(self.mouseExited) events.onPump.connect(self.pump) def _clear(self): self._clearToolbarButtons() events.keyPressed.disconnect(self.keyPressed) events.keyReleased.disconnect(self.keyReleased) events.mousePressed.disconnect(self.mousePressed) events.mouseDragged.disconnect(self.mouseDragged) events.mouseReleased.disconnect(self.mouseReleased) events.mouseMoved.disconnect(self.mouseMoved) events.mouseWheelMovedUp.disconnect(self.mouseWheelMovedUp) events.mouseWheelMovedDown.disconnect(self.mouseWheelMovedDown) events.mouseExited.disconnect(self.mouseExited) events.onPump.disconnect(self.pump) def _mapChanged(self, sender, mapview): self.setController(mapview.getController()) def setObject(self, object): self._object = object 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) self._moveAction = Action(text=u"Move", icon="gui/icons/move_instance.png", checkable=True) self._objectpickerAction = Action(text=u"Pick object", icon="gui/icons/objectpicker.png", checkable=True) self._selectAction.helptext = u"Select cells on layer" self._moveAction.helptext = u"Moves instances" self._drawAction.helptext = u"Adds new instances based on currently selected object" self._removeAction.helptext = u"Deletes instances" self._objectpickerAction.helptext = u"Click an instance to set the current object to the one used by instance" action.toggled.connect(self._buttonToggled, sender=self._selectAction) action.toggled.connect(self._buttonToggled, sender=self._moveAction) action.toggled.connect(self._buttonToggled, sender=self._drawAction) action.toggled.connect(self._buttonToggled, sender=self._removeAction) action.toggled.connect(self._buttonToggled, sender=self._objectpickerAction) self._toolgroup = ActionGroup(exclusive=True, name=u"Tool group") self._toolgroup.addAction(self._selectAction) self._toolgroup.addAction(self._moveAction) self._toolgroup.addAction(self._drawAction) self._toolgroup.addAction(self._removeAction) self._toolgroup.addAction(self._objectpickerAction) self._toolbox.addAction(self._toolgroup) self._toolbox.adaptLayout() self._editor._editMenu.addAction(self._toolgroup) def _initToolbarbuttons(self): 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") zoomOutAction = Action(text=u"Zoom out", icon="gui/icons/zoom_out.png") zoomResetAction = Action(text=u"Reset zoom", icon="gui/icons/zoom_default.png") 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) self._viewGroup = ActionGroup(name=u"View group") self._viewGroup.addAction(rotateLeftAction) self._viewGroup.addAction(rotateRightAction) self._viewGroup.addAction(zoomInAction) self._viewGroup.addAction(zoomOutAction) self._viewGroup.addAction(zoomResetAction) self._toolbar.addAction(self._viewGroup) self._toolbar.adaptLayout() def _clearToolbarButtons(self): self._toolbar.removeAction(self._viewGroup) self._toolbar.adaptLayout() self._viewGroup = None def _setMode(self, mode): if (mode == 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): self._drawAction.setChecked(True) elif mode == REMOVING: self._removeAction.setChecked(True) elif mode == MOVING: self._moveAction.setChecked(True) elif mode == 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()) def _buttonToggled(self, sender, toggled): if self._controller is None: return if self._ignoreToggles is True: return mode = SELECTING if toggled: if sender == self._selectAction: mode = SELECTING elif sender == self._moveAction: mode = MOVING elif sender == self._drawAction: mode = INSERTING elif sender == self._removeAction: mode = REMOVING elif sender == self._objectpickerAction: mode = OBJECTPICKER self._setMode(mode) def mouseExited(self, sender, event): pass def mousePressed(self, sender, event): if event.isConsumedByWidgets(): return realCoords = self._getRealCoords(sender, event) if event.getButton() == fife.MouseEvent.MIDDLE: self._dragx = realCoords[0] self._dragy = realCoords[1] else: if event.getButton() == fife.MouseEvent.RIGHT: self._controller.deselectSelection() if self._mode == SELECTING: if event.getButton() == fife.MouseEvent.LEFT: if self._eventlistener.shiftPressed: self._controller.deselectCell(realCoords[0], realCoords[1]) else: if self._eventlistener.controlPressed is False: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) elif event.getButton() == fife.MouseEvent.RIGHT: self._controller.deselectSelection() elif self._mode == INSERTING: if event.getButton() == fife.MouseEvent.LEFT: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.getUndoManager().startGroup("Inserted instances") self._undogroup = True 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: if event.getButton() == fife.MouseEvent.LEFT: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.getUndoManager().startGroup("Removed instances") self._undogroup = True self._controller.removeInstances(self._controller.getInstancesFromSelection()) elif self._mode == 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) for loc in self._controller._selection: if loc.getLayerCoordinates() == self._lastDragPos: break else: self._controller.deselectSelection() self._controller.selectCell(realCoords[0], realCoords[1]) self._instances = self._controller.getInstancesFromSelection() self._controller.getUndoManager().startGroup("Moved instances") self._undogroup = True elif self._mode == 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) if len(instances) >= 1: object = instances[0].getObject() if object.getId() != self._object.getId() or object.getNamespace() != self._object.getNamespace(): events.onObjectSelected.send(sender=self, object=object) def mouseDragged(self, sender, event): if event.isConsumedByWidgets(): return realCoords = self._getRealCoords(sender, event) 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: self._controller.deselectSelection() if self._mode == 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: 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: self._controller.selectCell(realCoords[0], realCoords[1]) self._controller.removeInstances(self._controller.getInstancesFromSelection()) elif self._mode == 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) else: self._controller.moveInstances(self._instances, position-self._lastDragPos, False) self._lastDragPos = position self._lastDragPosExact = positionExact # Update selection self._controller.deselectSelection() for i in self._instances: pos = i.getLocation().getMapCoordinates() pos = self._controller._camera.toScreenCoordinates(pos) self._controller.selectCell(pos.x, pos.y) elif self._mode == OBJECTPICKER: pass def mouseReleased(self, sender, event): if event.isConsumedByWidgets(): return if self._mode == SELECTING or self._mode == MOVING: instances = self._controller.getInstancesFromSelection() if len(instances) > 0: events.onInstancesSelected.send(sender=self, instances=instances) if event.getButton() == fife.MouseEvent.MIDDLE: self._scrollX = 0 self._scrollY = 0 realCoords = self._getRealCoords(sender, event) if self._undogroup: self._controller.getUndoManager().endGroup() self._undogroup = False self._dragx = NOT_INITIALIZED self._dragy = NOT_INITIALIZED def mouseMoved(self, sender, event): pass def mouseWheelMovedUp(self, event): if self._eventlistener.controlPressed and self._controller._camera: self._controller._camera.setZoom(self._controller._camera.getZoom() * 1.10) def mouseWheelMovedDown(self, event): 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() if keyval == fife.Key.LEFT: self._controller.moveCamera(50, 0) elif keyval == fife.Key.RIGHT: self._controller.moveCamera(-50, 0) elif keyval == fife.Key.UP: self._controller.moveCamera(0, 50) elif keyval == fife.Key.DOWN: self._controller.moveCamera(0, -50) elif keyval == fife.Key.INSERT: self._controller.fillSelection(self._object) elif keyval == fife.Key.DELETE: self._controller.clearSelection() elif keystr == "s": self._setMode(SELECTING) elif keystr == "i": if self._mode != INSERTING: self._setMode(INSERTING) else: self._setMode(SELECTING) elif keystr == "r": if self._mode != REMOVING: self._setMode(REMOVING) else: self._setMode(SELECTING) elif keystr == 'm': if self._mode != MOVING: self._setMode(MOVING) else: self._setMode(SELECTING) elif keystr == 't': gridrenderer = self._controller._camera.getRenderer('GridRenderer') gridrenderer.setEnabled(not gridrenderer.isEnabled()) elif keystr == 'b': blockrenderer = self._controller._camera.getRenderer('BlockingInfoRenderer') blockrenderer.setEnabled(not blockrenderer.isEnabled()) elif keystr == 'z': if self._eventlistener.controlPressed: if self._eventlistener.altPressed: if self._eventlistener.shiftPressed: self._controller.getUndoManager().previousBranch() else: self._controller.getUndoManager().nextBranch() else: if self._eventlistener.shiftPressed: self._controller.redo() else: self._controller.undo() 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): cw = sender offsetX = event.getX() offsetY = event.getY() parent = cw while parent is not None: if isinstance(parent, widgets.Widget): offsetX += parent.x offsetY += parent.y parent = parent.parent else: break return (offsetX, offsetY) def pump(self): self._controller.moveCamera(self._scrollX, self._scrollY)