Mercurial > fife-parpg
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clients/editor/scripts/gui/mapeditor.py Mon Jun 08 16:00:02 2009 +0000 @@ -0,0 +1,470 @@ +# 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) \ No newline at end of file