Mercurial > fife-parpg
view clients/editor/plugins/objectedit.py @ 254:10b5f7f36dd4
* Fixed a small unicode bug for the dropdown menu
author | nihathrael@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Wed, 03 Jun 2009 19:29:52 +0000 |
parents | f10a2e78a0e1 |
children |
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 plugin import pychan import pychan.widgets as widgets from pychan.tools import callbackWithArguments as cbwa import settings as Settings 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 offset, instance id or rotation (namespaces and object id editing is excluded) current features: - click instance and get all known data - edit offsets, 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 - use sliders to allow offset changes - the module should be able to use the editors global undo history FIXME: - this module owns a pointer to the mapedit module - this shouldn't be necessary; a better plugin system of fifedit should only hand over the needed data (selected instance) - we also need to edit run.py of the editor core to make this plugin work (shouldn't be necessary, too) """ def __init__(self, engine, mapedit): # Fifedit plugin data self.menu_items = { 'ObjectEdit' : self.toggle_offsetedit } self._mapedit = mapedit # this is _very bad_ - but I need to change the current rotation code by providing # project specific rotation angles. FIFE later should provide a list of the loaded # object rotations (they are provided by the xml files, so we just need to use them...) self._mapedit._objectedit_rotations = None self.active = False self._camera = None self._layer = None self.offset_slider = {} self.offset_slider['x'] = False self.offset_slider['y'] = False self.imagepool = engine.getImagePool() self.animationpool = engine.getAnimationPool() self.guidata = {} self.objectdata = {} self._reset() self.create_gui() def _reset(self): """ resets all dynamic vars, but leaves out static ones (e.g. camera, layer) """ self._instances = None self._image = None self._image_default_x_offset = None self._image_default_y_offset = 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 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({ 'x_offset_up' : cbwa(self.change_offset_x, 1), 'x_offset_dn' : cbwa(self.change_offset_x, -1), 'y_offset_up' : cbwa(self.change_offset_y, 1), 'y_offset_dn' : cbwa(self.change_offset_y, -1), 'x_offset_slider' : cbwa(self.get_slider_value, "x"), 'y_offset_slider' : cbwa(self.get_slider_value, "y"), '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_xoffset_textfield = self.container.findChild(name="x_offset") self._gui_yoffset_textfield = self.container.findChild(name="y_offset") self._gui_instance_id_textfield = self.container.findChild(name="instance_id") print "Steplength x slider", self.container.findChild(name="x_offset_slider").getStepLength() print "Steplength y slider", self.container.findChild(name="y_offset_slider").getStepLength() self.container.findChild(name="x_offset_slider").setStepLength(0.01) self.container.findChild(name="y_offset_slider").setStepLength(0.01) print "New steplength x slider", self.container.findChild(name="x_offset_slider").getStepLength() print "New steplength y slider", self.container.findChild(name="y_offset_slider").getStepLength() def get_slider_value(self, orientation): """ get current slider value for offset manipulation """ slider_name = orientation + "_offset_slider" widget = self.container.findChild(name=slider_name) value = widget.getValue() print "%s slider value: %s" % (orientation, str(value)) if value < 0: self.offset_slider[orientation] = False return callback = getattr(self, "change_offset_" + orientation) if self.offset_slider[orientation] == widget.getScaleStart(): self.set_default_offset(orientation) self.offset_slider[orientation] = False return elif self.offset_slider[orientation] >= widget.getScaleEnd(): pass elif self.offset_slider[orientation] < value: callback(1) elif self.offset_slider[orientation] > value : callback(-1) self.offset_slider[orientation] = value def set_default_offset(self, axis): """ set default image offset for given axis """ if axis == 'x': self._image.setXShift(self._image_default_x_offset) elif axis == 'y': self._image.setYShift(self._image_default_y_offset) def _get_gui_size(self): """ gets the current size of the gui window and calculates new position (atm top right corner) """ size = self.container._getSize() self.position = ((Settings.ScreenWidth - 10 - size[0]), 10) 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' : str( self._instances[0].getId() ), 'object_id' : str( self._object_id ), 'x_offset' : str( self._image.getXShift() ), 'y_offset' : str( self._image.getYShift() ), 'instance_rotation' : str( self._instances[0].getRotation() ), 'object_namespace' : str( self._namespace ), 'object_blocking' : str( self._blocking ), 'object_static' : str( 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" def toggle_gui(self): """ show / hide the gui FIXME: - ATM not in use, needs some additional code when showing / hiding the gui (see input() ) """ if self.container.isVisible(): self.container.hide() else: self.container.show() def toggle_offsetedit(self): """ - toggles the object editor activ / inactiv - just in case the user don't want to have the gui popping up all the time while mapping :-) - hides gui """ if self.active is True: self.active = False if self.container.isVisible(): self.container.hide() else: self.active = True def highlight_selected_instance(self): """ just highlights selected instance """ self.renderer.removeAllOutlines() self.renderer.addOutlined(self._instances[0], 205, 205, 205, 1) def change_offset_x(self, value=1): """ - callback for changing x offset - changes x offset of current instance (image) - updates gui @type value: int @param value: the modifier for the x offset """ if self._image is not None: self._image.setXShift(self._image.getXShift() + value) self.update_gui() def change_offset_y(self, value=1): """ - callback for changing y offset - changes y offset of current instance (image) - updates gui @type value: int @param value: the modifier for the y offset """ if self._image is not None: self._image.setYShift(self._image.getYShift() + value) self.update_gui() 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 FIXME: - parse user data in case user think strings are considered to be integer offset values... """ xoffset = self._gui_xoffset_textfield._getText() yoffset = self._gui_yoffset_textfield._getText() instance_id = self._gui_instance_id_textfield._getText() if instance_id is not None and instance_id is not "None": existing_instances = self._mapedit._layer.getInstances(instance_id) if existing_instances == (): self._instances[0].setId(instance_id) print "Set new instance id: ", instance_id else: for i in existing_instances: print i # 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) try: self._image.setXShift( int(xoffset) ) except: pass # print "x offset must me of type int!" try: self._image.setYShift( int(yoffset) ) except: pass # print "y offset must be of type int!" 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) ) self._image_default_x_offset = self._image.getXShift() self._image_default_y_offset = self._image.getYShift() # FIXME: see l. 40 self._mapedit._objectedit_rotations = self._avail_rotations # end FIXME def input(self): """ if called _and_ the user wishes to edit offsets, gets instance data and show gui (see run.py, pump() ) """ if self._mapedit._instances != self._instances: if self.active is True: self._reset() self._instances = self._mapedit._instances if self._camera is None: self._camera = self._mapedit._camera self.renderer = fife.InstanceRenderer.getInstance(self._camera) self._layer = self._mapedit._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()