comparison clients/editor/plugins/ObjectEdit.py @ 307:22253b2c9b14

- added LightEdit editor plugin (needs light branch to work; deactivated if lighting renderer is not available) - added animation viewer to ObjectEdit - several bugfixes for ObjectEdit plugin FEATURES: - ObjectEdit - viewing and rotating animated instances (rotations are hardcoded for now, FIFE needs to expose available angles to python in order to make animation rotation work for every client) - LightEdit - test global light values
author chewie@33b003aa-7bff-0310-803a-e67f0ece8222
date Tue, 11 Aug 2009 15:32:54 +0000
parents 07709bffab8f
children af0b233e246f
comparison
equal deleted inserted replaced
306:6177cdf72489 307:22253b2c9b14
1 #!/usr/bin/env python
1 # coding: utf-8 2 # coding: utf-8
2 # ################################################### 3 # ###################################################
3 # Copyright (C) 2008 The Zero-Projekt team 4 # Copyright (C) 2008 The Zero-Projekt team
4 # http://zero-projekt.net 5 # http://zero-projekt.net
5 # info@zero-projekt.net 6 # info@zero-projekt.net
26 import fife 27 import fife
27 import pychan 28 import pychan
28 import pychan.widgets as widgets 29 import pychan.widgets as widgets
29 from pychan.tools import callbackWithArguments as cbwa 30 from pychan.tools import callbackWithArguments as cbwa
30 31
32 from fife_timer import Timer
33
31 import scripts 34 import scripts
32 import scripts.plugin as plugin 35 import scripts.plugin as plugin
33 from scripts.events import * 36 from scripts.events import *
34 from scripts.gui.action import Action 37 from scripts.gui.action import Action
35 38
39
40 import os
41 try:
42 import xml.etree.cElementTree as ET
43 except:
44 import xml.etree.ElementTree as ET
45
36 import math 46 import math
47
48 WHITE = {
49 "r" : 205,
50 "g" : 205,
51 "b" : 205
52 }
53 OUTLINE_SIZE = 1
37 54
38 class ObjectEdit(plugin.Plugin): 55 class ObjectEdit(plugin.Plugin):
39 """ The B{ObjectEdit} module is a plugin for FIFedit and allows to edit 56 """ The B{ObjectEdit} module is a plugin for FIFedit and allows to edit
40 attributes of an selected instance - like instance id or rotation 57 attributes of an selected instance - like offset, instance id or rotation
41 (namespaces and object id editing is excluded) 58 (namespaces and object id editing is excluded)
42 59
43 current features: 60 current features:
44 - click instance and get all known data 61 - click instance and get all known data
45 - edit rotation, instance id 62 - edit offsets, rotation, instance id
63 - save offsets to object file
46 - outline highlighting of the selected object 64 - outline highlighting of the selected object
47 65 - animation viewer
48 missing features: 66
49 - blocking flag (flag doesn't work yet from FIFE side) 67 FIXME:
50 - static flag (flag doesn't work yet from FIFE side) 68 - add static and blocking flag to save routine
51 - object saving 69 - fix animation rotation (FIFE has no method yet to export all
52 - a lot of bug fixing concerning the rotation 70 angles of an animation to python)
53 - the module should be able to use the editors global undo history
54 """ 71 """
55 def __init__(self): 72 def __init__(self):
56 self.active = False 73 self.active = False
57 self._camera = None 74 self._camera = None
58 self._layer = None 75 self._layer = None
76 self._anim_timer = None
59 77
60 self._enabled = False 78 self._enabled = False
61 79
62 self.imagepool = None 80 self.imagepool = None
63 self.animationpool = None 81 self._animationpool = None
64 82
65 self.guidata = {} 83 self.guidata = {}
66 self.objectdata = {} 84 self.objectdata = {}
67 85
68 def _reset(self): 86 def _reset(self):
69 """ 87 """
70 resets all dynamic vars, but leaves out static ones (e.g. camera, layer) 88 resets all dynamic vars, but leaves out static ones (e.g. camera, layer)
71 89
72 """ 90 """
91 if self._anim_timer:
92 self._anim_timer.stop()
93 # reset the ToggleButton
94 if self._gui_anim_playback._isToggled():
95 self._gui_anim_playback._setToggled(0)
96 self._anim_timer = None
97
98 self._object = None
73 self._instances = None 99 self._instances = None
74 self._image = None 100 self._image = None
101 self._image_default_x_offset = None
102 self._image_default_y_offset = None
75 self._animation = False 103 self._animation = False
104 self._anim_data = {}
76 self._rotation = None 105 self._rotation = None
77 self._avail_rotations = [] 106 self._avail_rotations = []
78 self._namespace = None 107 self._namespace = None
79 self._blocking = 0 108 self._blocking = 0
80 self._static = 0 109 self._static = 0
81 self._object_id = None 110 self._object_id = None
82 self._instance_id = None 111 self._instance_id = None
83 self._fixed_rotation = None 112 self._fixed_rotation = None
84 113
85 if self._camera is not None: 114 if self._camera is not None:
86 self.renderer.removeAllOutlines() 115 self.renderer.removeAllOutlines()
87
88 116
89 def enable(self): 117 def enable(self):
118 """ plugin method """
90 if self._enabled is True: 119 if self._enabled is True:
91 return 120 return
92 121
93 self._editor = scripts.editor.getEditor() 122 self._editor = scripts.editor.getEditor()
94 self.engine = self._editor.getEngine() 123 self.engine = self._editor.getEngine()
95 124
96 self.imagepool = self.engine.getImagePool() 125 self.imagepool = self.engine.getImagePool()
97 self.animationpool = self.engine.getAnimationPool() 126 self._animationpool = self.engine.getAnimationPool()
98 127
99 self._showAction = Action(u"Object editor", checkable=True) 128 self._showAction = Action(unicode(self.getName(),"utf-8"), checkable=True)
100 scripts.gui.action.activated.connect(self.toggle_gui, sender=self._showAction) 129 scripts.gui.action.activated.connect(self.toggle_gui, sender=self._showAction)
101 130
102 self._editor._toolsMenu.addAction(self._showAction) 131 self._editor._toolsMenu.addAction(self._showAction)
103 132
104 events.onInstancesSelected.connect(self.input) 133 events.onInstancesSelected.connect(self.input)
105 134
106 self._reset() 135 self._reset()
107 self.create_gui() 136 self.create_gui()
108 137
109 def disable(self): 138 def disable(self):
139 """ plugin method """
110 if self._enabled is False: 140 if self._enabled is False:
111 return 141 return
112 142
113 self._reset() 143 self._reset()
114 self.container.hide() 144 self.container.hide()
117 events.onInstancesSelected.disconnect(self.input) 147 events.onInstancesSelected.disconnect(self.input)
118 148
119 self._editor._toolsMenu.removeAction(self._showAction) 149 self._editor._toolsMenu.removeAction(self._showAction)
120 150
121 def isEnabled(self): 151 def isEnabled(self):
152 """ plugin method """
122 return self._enabled; 153 return self._enabled;
123 154
124 def getName(self): 155 def getName(self):
125 return "Object editor" 156 """ plugin method """
157 return "Object editor v2"
126 158
127 def create_gui(self): 159 def create_gui(self):
128 """ 160 """
129 - creates the gui skeleton by loading the xml file 161 - creates the gui skeleton by loading the xml file
130 - finds some important childs and saves their widget in the object 162 - finds some important childs and saves their widget in the object
163
164 FIXME:
165 - move all dynamic widgets to dict
131 """ 166 """
132 self.container = pychan.loadXML('gui/objectedit.xml') 167 self.container = pychan.loadXML('gui/objectedit.xml')
133 self.container.mapEvents({ 168 self.container.mapEvents({
134 'use_data' : self.use_user_data, 169 'x_offset_up' : cbwa(self.change_offset_x, 1),
135 170 'x_offset_dn' : cbwa(self.change_offset_x, -1),
171
172 'y_offset_up' : cbwa(self.change_offset_y, 1),
173 'y_offset_dn' : cbwa(self.change_offset_y, -1),
174
175 'use_data' : self.use_user_data,
176 'change_data' : self.save_user_data,
177
178 'anim_left' : self.previous_anim_frame,
179 'anim_right' : self.next_anim_frame,
180 'anim_start_pos' : self.anim_start_frame,
181 'anim_end_pos' : self.anim_end_frame,
136 }) 182 })
137 183
138 self._gui_anim_panel_wrapper = self.container.findChild(name="animation_panel_wrapper") 184 self._gui_anim_panel_wrapper = self.container.findChild(name="animation_panel_wrapper")
139 self._gui_anim_panel = self._gui_anim_panel_wrapper.findChild(name="animation_panel") 185 self._gui_anim_panel = self._gui_anim_panel_wrapper.findChild(name="animation_panel")
140 186
141 self._gui_anim_panel_wrapper.removeChild(self._gui_anim_panel)
142
143 self._gui_rotation_dropdown = self.container.findChild(name="select_rotations") 187 self._gui_rotation_dropdown = self.container.findChild(name="select_rotations")
144 188 self._gui_rotation_dropdown.capture(self.gui_rotate_instance,"mouseWheelMovedUp")
189 self._gui_rotation_dropdown.capture(self.gui_rotate_instance,"mouseWheelMovedDown")
190 self._gui_rotation_dropdown.capture(self.gui_rotate_instance,"action")
191
192 self._gui_anim_actions_dropdown = self._gui_anim_panel_wrapper.findChild(name="select_actions")
193 self._gui_anim_actions_dropdown.capture(self.eval_gui_anim_action,"mouseWheelMovedUp")
194 self._gui_anim_actions_dropdown.capture(self.eval_gui_anim_action,"mouseWheelMovedDown")
195 self._gui_anim_actions_dropdown.capture(self.eval_gui_anim_action,"action")
196
197 self._gui_anim_playback = self._gui_anim_panel_wrapper.findChild(name="anim_playback")
198 self._gui_anim_playback.capture(self.anim_playback, "mousePressed")
199 self._gui_anim_loop = self._gui_anim_panel_wrapper.findChild(name="anim_loop")
200
201 self._gui_current_frame = self._gui_anim_panel_wrapper.findChild(name="anim_current_frame")
202 self._gui_current_frame.capture(self.previous_anim_frame,"mouseWheelMovedUp")
203 self._gui_current_frame.capture(self.next_anim_frame,"mouseWheelMovedDown")
204
205 self._gui_xoffset_textfield = self.container.findChild(name="x_offset")
206 self._gui_yoffset_textfield = self.container.findChild(name="y_offset")
207
145 self._gui_instance_id_textfield = self.container.findChild(name="instance_id") 208 self._gui_instance_id_textfield = self.container.findChild(name="instance_id")
146 209
147 def _get_gui_size(self): 210 def anim_playback(self, widget):
148 """ 211 """ start / stop playback of an animation due to status of a gui ToggleButton
149 gets the current size of the gui window and calculates new position 212 Sets also two ivars of timer object (active & loop)
150 (atm top right corner) 213 """
151 """ 214 if widget._isToggled():
152 size = self.container.size 215 self._anim_timer.stop()
153 self.position = ((pychan.internal.screen_width() - 50 - size[0]), 50) 216 self._anim_timer.active = False
154 217 else:
218 frame_delay = self._anim_data['obj'].getFrameDuration(self._anim_data['current'])
219 self._anim_timer = Timer(delay=frame_delay,callback=self.next_anim_frame)
220 self._anim_timer.active = True
221 self._anim_timer.loop = self._gui_anim_loop._isMarked()
222 self._anim_timer.start()
223
224 def previous_anim_frame(self):
225 """ show previous anim frame """
226 if self._anim_data['current'] > 0:
227 self._anim_data['current'] -= 1
228 self.update_gui()
229
230 def next_anim_frame(self):
231 """ show next anim frame and reset animation frame to 0 if playback looping is active"""
232 if self._anim_timer.loop and (self._anim_data['current'] == self._anim_data['frames']):
233 self._anim_data['current'] = 0
234
235 if self._anim_data['current'] < self._anim_data['frames']:
236 self._anim_data['current'] += 1
237 self.update_gui()
238
239 def anim_start_frame(self):
240 """ set start frame of animation """
241 self._anim_data['current'] = 0
242 self.update_gui()
243
244 def anim_end_frame(self):
245 """ set end frame of animation """
246 self._anim_data['current'] = self._anim_data['frames']
247 self.update_gui()
248
249 def set_default_offset(self, axis):
250 """ set default image offset for given axis """
251 if axis == 'x':
252 self.set_offset(x=self._image_default_x_offset)
253 elif axis == 'y':
254 self.set_offset(y=self._image_default_y_offset)
255
155 def update_gui(self): 256 def update_gui(self):
156 """ 257 """
157 updates the gui widgets with current instance data 258 updates the gui widgets with current instance data
158 259
159 FIXME: 260 """
160 - drop animation support or turn it into something useful 261 # show the image we retrieved from an animated object
161 """ 262 if self._animation:
162 #if self._animation is False: 263 if not self._gui_anim_panel_wrapper.findChild(name="animation_panel"):
163 #try: 264 self._gui_anim_panel_wrapper.addChild(self._gui_anim_panel)
164 #self._gui_anim_panel_wrapper.removeChild(self._gui_anim_panel) 265
165 #except: 266 # get current selected image and update the icon widget
166 #pass 267 dur = 0
167 #elif self._animation is True: 268 for i in range(self._anim_data['frames']):
168 #try: 269 dur += self._anim_data['obj'].getFrameDuration(i)
169 #self._gui_anim_panel_wrapper.resizeToContent() 270
170 #self._gui_anim_panel_wrapper.addChild(self._gui_anim_panel) 271 # set new duration for the playback timer
171 #self._gui_anim_panel_wrapper.resizeToContent() 272 if self._anim_timer:
172 #except: 273 frame_delay = self._anim_data['obj'].getFrameDuration(self._anim_data['current'])
173 #pass 274
174 275 if i == self._anim_data['current']:
276 # set new duration for the playback timer
277 if self._anim_timer and self._anim_timer.active:
278 self._anim_timer.setPeriod(self._anim_data['obj'].getFrameDuration(self._anim_data['current']))
279 break
280
281 image = self._anim_data['obj'].getFrameByTimestamp(dur)
282 self.container.findChild(name="animTest").image = image.getResourceFile()
283 self.container.findChild(name="animTest").size= (250,250)
284 self.container.findChild(name="animTest").min_size= (250,250)
285
286 self.container.distributeInitialData({
287 'anim_current_frame' : unicode(str(self._anim_data['current'])),
288 'anim_rotation' : unicode(str(self._anim_data['obj'].getDirection())),
289 })
290
291 else:
292 if self._gui_anim_panel_wrapper.findChild(name="animation_panel"):
293 self._gui_anim_panel_wrapper.removeChild(self._gui_anim_panel)
294
295 if self._image is not None:
296 x_offset = unicode( self._image.getXShift() )
297 y_offset = unicode( self._image.getYShift() )
298 else:
299 x_offset = unicode( 0 )
300 y_offset = unicode( 0 )
301
175 self.container.distributeInitialData({ 302 self.container.distributeInitialData({
176 'select_rotations' : self._avail_rotations, 303 'select_rotations' : self._avail_rotations,
177 'instance_id' : unicode( self._instances[0].getId() ), 304 'instance_id' : unicode( self._instances[0].getId() ),
178 'object_id' : unicode( self._object_id ), 305 'object_id' : unicode( self._object_id ),
306 'x_offset' : x_offset,
307 'y_offset' : y_offset,
179 'instance_rotation' : unicode( self._instances[0].getRotation() ), 308 'instance_rotation' : unicode( self._instances[0].getRotation() ),
180 'object_namespace' : unicode( self._namespace ), 309 'object_namespace' : unicode( self._namespace ),
181 'object_blocking' : unicode( self._blocking ), 310 'object_blocking' : unicode( self._blocking ),
182 'object_static' : unicode( self._static ), 311 'object_static' : unicode( self._static ),
183 }) 312 })
184 try: 313
185 print self._avail_rotations 314 if not self._animation:
186 print self._fixed_rotation 315 index = self._avail_rotations.index( self._fixed_rotation )
187 index = self._avail_rotations.index( str(self._fixed_rotation) )
188 self._gui_rotation_dropdown._setSelected(index) 316 self._gui_rotation_dropdown._setSelected(index)
189 except: 317
190 # pass 318 self.container.adaptLayout()
191 print "Angle (", self._fixed_rotation, ") not supported by this instance"
192 self.container.adaptLayout()
193 319
194 def toggle_gui(self): 320 def toggle_gui(self):
195 """ 321 """
196 show / hide the gui 322 show / hide the gui
197 """ 323 """
204 else: 330 else:
205 self.active = True 331 self.active = True
206 self._showAction.setChecked(True) 332 self._showAction.setChecked(True)
207 333
208 def highlight_selected_instance(self): 334 def highlight_selected_instance(self):
209 """ 335 """ highlights selected instance """
210 just highlights selected instance
211 """
212 self.renderer.removeAllOutlines() 336 self.renderer.removeAllOutlines()
213 self.renderer.addOutlined(self._instances[0], 205, 205, 205, 1) 337 self.renderer.addOutlined(self._instances[0], WHITE["r"], WHITE["g"], WHITE["b"], OUTLINE_SIZE)
338
339 def change_offset_x(self, value=1):
340 """
341 - callback for changing x offset
342 - changes x offset of current instance (image)
343 - updates gui
344
345 @type value: int
346 @param value: the modifier for the x offset
347 """
348 if self._animation:
349 print "Offset changes of animations are not supported yet"
350 return
351
352 if self._image is not None:
353 self._image.setXShift(self._image.getXShift() + value)
354 self.update_gui()
355
356 def change_offset_y(self, value=1):
357 """
358 - callback for changing y offset
359 - changes y offset of current instance (image)
360 - updates gui
361
362 @type value: int
363 @param value: the modifier for the y offset
364 """
365 if self._animation:
366 print "Offset changes of animations are not supported yet"
367 return
368
369 if self._image is not None:
370 self._image.setYShift(self._image.getYShift() + value)
371 self.update_gui()
214 372
215 def use_user_data(self): 373 def use_user_data(self):
216 """ 374 """
217 - takes the users values and applies them directly to the current ._instance 375 - takes the users values and applies them directly to the current ._instance
218 - writes current data record 376 - writes current data record
219 - writes previous data record 377 - writes previous data record
220 - updates gui 378 - updates gui
221 """ 379
380 FIXME:
381 - parse user data in case user think strings are considered to be integer offset values...
382 """
383 if self._animation:
384 print "Editing animated instances is not supported yet"
385 return
386
387 xoffset = self._gui_xoffset_textfield._getText()
388 yoffset = self._gui_yoffset_textfield._getText()
389
222 instance_id = str(self._gui_instance_id_textfield._getText()) 390 instance_id = str(self._gui_instance_id_textfield._getText())
391
392 if instance_id == "":
393 instance_id = "None"
394
223 if instance_id is not None and instance_id is not "None": 395 if instance_id is not None and instance_id is not "None":
224 existing_instances = self._editor.getActiveMapView().getController()._layer.getInstances(instance_id) 396 existing_instances = self._editor.getActiveMapView().getController()._layer.getInstances(instance_id)
225 if len(existing_instances) <= 0: 397 if len(existing_instances) <= 0:
226 self._instances[0].setId(instance_id) 398 self._instances[0].setId(instance_id)
227 print "Set new instance id: ", instance_id 399 print "Set new instance id: ", instance_id
228 else: 400 else:
229 print "Instance ID is already in use." 401 print "Instance ID is already in use."
230 402
231 # workaround - dropdown list only has 2 entries, but sends 3 -> pychan bug? 403 # update rotation
232 if len(self._avail_rotations) < self._gui_rotation_dropdown._getSelected(): 404 angle = self.eval_gui_rotation()
233 index = len(self._avail_rotations) 405 self.set_rotation(angle)
234 else: 406
235 index = self._gui_rotation_dropdown._getSelected() 407 # update offsets
236 408 self.set_offset(int(xoffset), int(yoffset))
237 # strange, but this helps to rotate the image correctly to the value the user selected 409
410 self.update_gui()
411
412 def save_user_data(self):
413 """ saves the current object to its xml file
414
415 NOTE:
416 - animations can't be saved for now
417
418 FIXME:
419 - add missing object attributes to saving routine
420 """
421 if self._object is None:
422 return
423 if self._animation:
424 return
425
426 file = self._object.getResourceFile()
427 self.tree = ET.parse(file)
428
429 img_lst = self.tree.findall("image")
430
431 # apply changes to the XML structure due to current user settings in the gui
432 for img_tag in img_lst:
433 if img_tag.attrib["direction"] == self._avail_rotations[self._gui_rotation_dropdown._getSelected()]:
434 img_tag.attrib["x_offset"] = self._gui_xoffset_textfield._getText()
435 img_tag.attrib["y_offset"] = self._gui_yoffset_textfield._getText()
436 break
437
438 xmlcontent = ET.tostring(self.tree.getroot())
439
440 # save xml data beneath the <?fife type="object"?> definition into the object file
441 tmp = open(file, 'w')
442 tmp.write('<?fife type="object"?>\n')
443 tmp.write(xmlcontent + "\n")
444 tmp.close()
445
446 def gui_rotate_instance(self):
447 """ rotate an instance due to selected angle """
448 angle = self.eval_gui_rotation()
449 self.set_rotation(angle)
450
451 def eval_gui_rotation(self):
452 """ prepare rotation from gui and apply it to the current selected instance """
453 index = self._gui_rotation_dropdown._getSelected()
238 angle = int( self._avail_rotations[index] ) 454 angle = int( self._avail_rotations[index] )
239 angle = int(angle - abs( self._camera.getTilt() ) ) 455
240 if angle == 360: 456 if angle == 360:
241 angle = 0 457 angle = 0
242 458
459 return angle
460
461 def eval_gui_anim_action(self):
462 """ check the selected action of an animation and update the gui accordingly """
463 if not self._anim_data['actions']: return
464
465 index = self._gui_anim_actions_dropdown._getSelected()
466 action = self._anim_data['actions'][index]
467
468 self.update_anim_data(action)
469 self.update_gui()
470
471 def set_rotation(self, angle):
472 """ set the rotation of the current instance """
473 # print "...setting instance rotation from %s to %s" % (self._rotation, angle)
243 self._instances[0].setRotation(angle) 474 self._instances[0].setRotation(angle)
244 self.get_instance_data(None, None, angle) 475 self.get_instance_data(None, None, angle)
245 476 self.update_gui()
246 self.update_gui() 477 # print "...new internal FIFE rotation ", int(self._instances[0].getRotation())
478
479 def set_offset(self, x=None, y=None):
480 """ set x/y offset of current selected instance """
481 if x is not None:
482 self._image.setXShift(x)
483 if y is not None:
484 self._image.setYShift(y)
485
486 def update_anim_data(self, action=None):
487 """ update animation data for the current selected instance from FIFE's data structure
488
489 @type animation FIFE animation
490 @return animation current selected animation
491 """
492 if action:
493 animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(self._fixed_rotation)
494 animation = self._animationpool.getAnimation(animation_id)
495
496 action_ids = []
497 actions = []
498
499 try:
500 action_ids = self._object.getActionIds()
501 for id in action_ids:
502 actions.append(self._object.getAction(id))
503 except:
504 pass
505
506 self._anim_data = {}
507 self._anim_data['obj'] = animation
508 self._anim_data['id'] = animation_id
509 self._anim_data['frames'] = animation.getNumFrames()
510 self._anim_data['current'] = 0
511 self._anim_data['actions'] = actions
512 self._anim_data['action_ids'] = action_ids
513 self._anim_data['default_action'] = self._object.getDefaultAction()
514 self._anim_data['action'] = action
515
516 return animation
247 517
248 def get_instance_data(self, timestamp=None, frame=None, angle=-1, instance=None): 518 def get_instance_data(self, timestamp=None, frame=None, angle=-1, instance=None):
249 """ 519 """
250 - grabs all available data from both object and instance 520 - grabs all available data from both object and instance
251 - checks if we already hold a record (namespace + object id) 521
252
253 FIXME: 522 FIXME:
254 1.) we need to fix the instance rotation / rotation issue 523 1.) we need to fix the instance rotation / rotation issue
255 2.) use correct instance rotations to store data for _each_ available rotation
256 3.) move record code out of this method
257 """ 524 """
258 visual = None 525 visual = None
259 self._avail_rotations = [] 526 self._avail_rotations = []
260 527
261 if instance is None: 528 if instance is None:
262 instance = self._instances[0] 529 instance = self._instances[0]
263 530
264 object = instance.getObject() 531 object = instance.getObject()
532 self._object = object
265 self._namespace = object.getNamespace() 533 self._namespace = object.getNamespace()
266 self._object_id = object.getId() 534 self._object_id = object.getId()
267 535
268 self._instance_id = instance.getId() 536 self._instance_id = instance.getId()
269 537
270 if self._instance_id == '': 538 if self._instance_id == '':
271 self._instance_id = 'None' 539 self._instance_id = 'None'
272 540
287 visual = object.get2dGfxVisual() 555 visual = object.get2dGfxVisual()
288 except: 556 except:
289 print 'Fetching visual of object - failed. :/' 557 print 'Fetching visual of object - failed. :/'
290 raise 558 raise
291 559
292 # print "Camera Tilt: ", self._camera.getTilt() 560 # print "Camera tilt: ", self._camera.getTilt()
293 # print "Camera Rotation: ", self._camera.getRotation() 561 # print "Camera rotation: ", self._camera.getRotation()
562 # print "Instance rotation: ", instance.getRotation()
294 563
295 self._fixed_rotation = int(instance.getRotation() + abs( self._camera.getTilt() ) ) 564 self._fixed_rotation = int(instance.getRotation() + abs( self._camera.getTilt() ) )
296 self._fixed_rotation = visual.getClosestMatchingAngle(self._fixed_rotation) 565 self._fixed_rotation = instance.getRotation()
566 # self._fixed_rotation = visual.getClosestMatchingAngle(self._fixed_rotation)
297 567
298 index = visual.getStaticImageIndexByAngle(self._fixed_rotation) 568 index = visual.getStaticImageIndexByAngle(self._fixed_rotation)
299 569
300 if index == -1: 570 if index is -1:
301 # object is an animation 571 # object is an animation
302 self._animation = True 572 self._animation = True
573 self._image = None
574
303 # no static image available, try default action 575 # no static image available, try default action
304 action = object.getDefaultAction() 576 action = object.getDefaultAction()
577
305 if action: 578 if action:
306 animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(self._fixed_rotation) 579 animation = self.update_anim_data(action)
307 animation = self.animationpool.getAnimation(animation_id) 580
308 # if timestamp is None and frame is not None: 581 # update gui
309 # self._image = animation.getFrame(frame) 582 if animation:
310 # elif timestamp is not None and frame is None: 583 self._gui_anim_actions_dropdown._setItems(self._anim_data['action_ids'])
311 # self._image = animation.getFrameByTimestamp(timestamp) 584 self._gui_anim_actions_dropdown._setSelected(0)
312 # else: 585
313 self._image = animation.getFrameByTimestamp(0) 586 if timestamp is None and frame is not None:
314 index = self._image.getPoolId() 587 self._image = animation.getFrame(frame)
315 elif index != -1: 588 elif timestamp is not None and frame is None:
589 self._image = animation.getFrameByTimestamp(timestamp)
590 else:
591 self._image = animation.getFrameByTimestamp(0)
592 elif index is not -1:
316 # object is a static image 593 # object is a static image
317 self._animation = False 594 self._animation = False
318 self._image = self.imagepool.getImage(index) 595 self._image = self.imagepool.getImage(index)
319 596
320 if not self._animation: 597 if not self._animation:
321 rotation_tuple = visual.getStaticImageAngles() 598 rotations = visual.getStaticImageAngles()
322 for angle in rotation_tuple: 599 for angle in rotations:
323 self._avail_rotations.append( str(angle) ) 600 self._avail_rotations.append(angle)
324 601
325 602 self._image_default_x_offset = self._image.getXShift()
326 # FIXME: see l. 40 603 self._image_default_y_offset = self._image.getYShift()
327 self._editor.getActiveMapView().getController()._objectedit_rotations = self._avail_rotations 604 else:
328 # end FIXME 605 # these doesn't work correctly
329 606 # rotations = [0,60,120,180,240,300]
607
608 # testbench to get valid angles
609 # angle = 0
610 # rotations = []
611 # while angle != 360:
612 # angle += 10
613 # rotations.append(angle)
614
615 # estimated angles (for hex!) to make things work - use testbench to test
616 # various angles and note down the working ones (watch instance
617 # rotation and the animation rotations shown in the gui; valid
618 # angles are given once the rotations are in sync
619 self._avail_rotations = [9,69,139,169,249,319]
620
330 def input(self, instances): 621 def input(self, instances):
331 """ 622 """
332 if called _and_ the objectedit is active, 623 if called _and_ the user wishes to edit offsets,
333 gets instance data and show gui 624 gets instance data and show gui
334 625
335 (see run.py, pump() )
336 """ 626 """
337 if instances != self._instances: 627 if instances != self._instances:
338 if self.active is True: 628 if self.active is True:
339 self._reset() 629 self._reset()
340 self._instances = instances 630 self._instances = instances
349 self.highlight_selected_instance() 639 self.highlight_selected_instance()
350 self.get_instance_data() 640 self.get_instance_data()
351 self.update_gui() 641 self.update_gui()
352 self.container.adaptLayout() 642 self.container.adaptLayout()
353 self.container.show() 643 self.container.show()
354 self._get_gui_size()
355 self.container._setPosition(self.position)
356 else: 644 else:
357 self._reset() 645 self._reset()
358 self.container.hide() 646 self.container.hide()
647
648 self.container.adaptLayout()