Mercurial > fife-parpg
view clients/editor/plugins/ObjectEdit.py @ 256:e893afb4963b
* Fixed HistoryManager to work with linear undo
* Set UndoManager to use branched mode by default
author | cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 08 Jun 2009 16:57:39 +0000 |
parents | 51cc05d862f2 |
children | 07709bffab8f |
line wrap: on
line source
#!/usr/bin/env python # coding: utf-8 # ################################################### # Copyright (C) 2008 The Zero-Projekt team # http://zero-projekt.net # info@zero-projekt.net # This file is part of Zero "Was vom Morgen blieb" # # The Zero-Projekt codebase is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # ################################################### """ a tool for FIFEdit to edit object and instance attributes """ import fife import pychan import pychan.widgets as widgets from pychan.tools import callbackWithArguments as cbwa import scripts import scripts.plugin as plugin from scripts.events import * from scripts.gui.action import Action import math class ObjectEdit(plugin.Plugin): """ The B{ObjectEdit} module is a plugin for FIFedit and allows to edit attributes of an selected instance - like instance id or rotation (namespaces and object id editing is excluded) current features: - click instance and get all known data - edit rotation, instance id - outline highlighting of the selected object missing features: - blocking flag (flag doesn't work yet from FIFE side) - static flag (flag doesn't work yet from FIFE side) - object saving - a lot of bug fixing concerning the rotation - the module should be able to use the editors global undo history """ def __init__(self): self.active = False self._camera = None self._layer = None self._enabled = False self.imagepool = None self.animationpool = None self.guidata = {} self.objectdata = {} def _reset(self): """ resets all dynamic vars, but leaves out static ones (e.g. camera, layer) """ self._instances = None self._image = None self._animation = False self._rotation = None self._avail_rotations = [] self._namespace = None self._blocking = 0 self._static = 0 self._object_id = None self._instance_id = None self._fixed_rotation = None if self._camera is not None: self.renderer.removeAllOutlines() def enable(self): if self._enabled is True: return self._editor = scripts.editor.getEditor() self.engine = self._editor.getEngine() self.imagepool = self.engine.getImagePool() self.animationpool = self.engine.getAnimationPool() self._showAction = Action(u"Object editor", checkable=True) scripts.gui.action.activated.connect(self.toggle_gui, sender=self._showAction) self._editor._toolsMenu.addAction(self._showAction) events.onInstancesSelected.connect(self.input) self._reset() self.create_gui() def disable(self): if self._enabled is False: return self._reset() self.container.hide() self.removeAllChildren() events.onInstancesSelected.disconnect(self.input) self._editor._toolsMenu.removeAction(self._showAction) def isEnabled(self): return self._enabled; def getName(self): return "Object editor" def create_gui(self): """ - creates the gui skeleton by loading the xml file - finds some important childs and saves their widget in the object """ self.container = pychan.loadXML('gui/objectedit.xml') self.container.mapEvents({ 'use_data' : self.use_user_data, }) self._gui_anim_panel_wrapper = self.container.findChild(name="animation_panel_wrapper") self._gui_anim_panel = self._gui_anim_panel_wrapper.findChild(name="animation_panel") self._gui_anim_panel_wrapper.removeChild(self._gui_anim_panel) self._gui_rotation_dropdown = self.container.findChild(name="select_rotations") self._gui_instance_id_textfield = self.container.findChild(name="instance_id") def _get_gui_size(self): """ gets the current size of the gui window and calculates new position (atm top right corner) """ size = self.container.size self.position = ((pychan.internal.screen_width() - 50 - size[0]), 50) def update_gui(self): """ updates the gui widgets with current instance data FIXME: - drop animation support or turn it into something useful """ #if self._animation is False: #try: #self._gui_anim_panel_wrapper.removeChild(self._gui_anim_panel) #except: #pass #elif self._animation is True: #try: #self._gui_anim_panel_wrapper.resizeToContent() #self._gui_anim_panel_wrapper.addChild(self._gui_anim_panel) #self._gui_anim_panel_wrapper.resizeToContent() #except: #pass self.container.distributeInitialData({ 'select_rotations' : self._avail_rotations, 'instance_id' : unicode( self._instances[0].getId() ), 'object_id' : unicode( self._object_id ), 'instance_rotation' : unicode( self._instances[0].getRotation() ), 'object_namespace' : unicode( self._namespace ), 'object_blocking' : unicode( self._blocking ), 'object_static' : unicode( self._static ), }) try: print self._avail_rotations print self._fixed_rotation index = self._avail_rotations.index( str(self._fixed_rotation) ) self._gui_rotation_dropdown._setSelected(index) except: # pass print "Angle (", self._fixed_rotation, ") not supported by this instance" self.container.adaptLayout() def toggle_gui(self): """ show / hide the gui """ if self.active is True: self.active = False if self.container.isVisible() or self.container.isDocked(): self.container.setDocked(False) self.container.hide() self._showAction.setChecked(False) else: self.active = True self._showAction.setChecked(True) def highlight_selected_instance(self): """ just highlights selected instance """ self.renderer.removeAllOutlines() self.renderer.addOutlined(self._instances[0], 205, 205, 205, 1) def use_user_data(self): """ - takes the users values and applies them directly to the current ._instance - writes current data record - writes previous data record - updates gui """ instance_id = str(self._gui_instance_id_textfield._getText()) if instance_id is not None and instance_id is not "None": existing_instances = self._editor.getActiveMapView().getController()._layer.getInstances(instance_id) if len(existing_instances) <= 0: self._instances[0].setId(instance_id) print "Set new instance id: ", instance_id else: print "Instance ID is already in use." # workaround - dropdown list only has 2 entries, but sends 3 -> pychan bug? if len(self._avail_rotations) < self._gui_rotation_dropdown._getSelected(): index = len(self._avail_rotations) else: index = self._gui_rotation_dropdown._getSelected() # strange, but this helps to rotate the image correctly to the value the user selected angle = int( self._avail_rotations[index] ) angle = int(angle - abs( self._camera.getTilt() ) ) if angle == 360: angle = 0 self._instances[0].setRotation(angle) self.get_instance_data(None, None, angle) self.update_gui() def get_instance_data(self, timestamp=None, frame=None, angle=-1, instance=None): """ - grabs all available data from both object and instance - checks if we already hold a record (namespace + object id) FIXME: 1.) we need to fix the instance rotation / rotation issue 2.) use correct instance rotations to store data for _each_ available rotation 3.) move record code out of this method """ visual = None self._avail_rotations = [] if instance is None: instance = self._instances[0] object = instance.getObject() self._namespace = object.getNamespace() self._object_id = object.getId() self._instance_id = instance.getId() if self._instance_id == '': self._instance_id = 'None' if angle == -1: angle = int(instance.getRotation()) else: angle = int(angle) self._rotation = angle if object.isBlocking(): self._blocking = 1 if object.isStatic(): self._static = 1 try: visual = object.get2dGfxVisual() except: print 'Fetching visual of object - failed. :/' raise # print "Camera Tilt: ", self._camera.getTilt() # print "Camera Rotation: ", self._camera.getRotation() self._fixed_rotation = int(instance.getRotation() + abs( self._camera.getTilt() ) ) self._fixed_rotation = visual.getClosestMatchingAngle(self._fixed_rotation) index = visual.getStaticImageIndexByAngle(self._fixed_rotation) if index == -1: # object is an animation self._animation = True # no static image available, try default action action = object.getDefaultAction() if action: animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(self._fixed_rotation) animation = self.animationpool.getAnimation(animation_id) # if timestamp is None and frame is not None: # self._image = animation.getFrame(frame) # elif timestamp is not None and frame is None: # self._image = animation.getFrameByTimestamp(timestamp) # else: self._image = animation.getFrameByTimestamp(0) index = self._image.getPoolId() elif index != -1: # object is a static image self._animation = False self._image = self.imagepool.getImage(index) if not self._animation: rotation_tuple = visual.getStaticImageAngles() for angle in rotation_tuple: self._avail_rotations.append( str(angle) ) # FIXME: see l. 40 self._editor.getActiveMapView().getController()._objectedit_rotations = self._avail_rotations # end FIXME def input(self, instances): """ if called _and_ the objectedit is active, gets instance data and show gui (see run.py, pump() ) """ if instances != self._instances: if self.active is True: self._reset() self._instances = instances if self._camera is None: self._camera = self._editor.getActiveMapView().getCamera() self.renderer = fife.InstanceRenderer.getInstance(self._camera) self._layer = self._editor.getActiveMapView().getController()._layer if self._instances != (): self.highlight_selected_instance() self.get_instance_data() self.update_gui() self.container.adaptLayout() self.container.show() self._get_gui_size() self.container._setPosition(self.position) else: self._reset() self.container.hide()