ya2 · news · projects · code · about

fixes for building
[pmachines.git] / pmachines / editor / inspector.py
1 from collections import namedtuple
2 from logging import info
3 from panda3d.core import Texture, TextNode, LPoint3f
4 from direct.gui.OnscreenImage import OnscreenImage
5 from direct.gui.DirectGui import DirectButton, DirectFrame, DirectEntry, DirectOptionMenu, OkDialog
6 from direct.gui.DirectGuiGlobals import FLAT, NORMAL
7 from direct.gui.OnscreenText import OnscreenText
8 from direct.showbase.DirectObject import DirectObject
9 from pmachines.items.item import FixedStrategy, StillStrategy
10 from pmachines.items.box import HitStrategy
11 from pmachines.items.domino import DownStrategy, UpStrategy
12 from pmachines.editor.augmented_frame import AugmentedDirectFrame
13 from ya2.utils.gui.base_page import DirectOptionMenuTestable
14 from ya2.utils.gfx import DirectGuiMixin
15
16
17 class Inspector(DirectObject):
18
19 def __init__(self, item, all_items, pos_mgr, strategy_items):
20 super().__init__()
21 self.__item = item
22 self.__all_items = all_items
23 self.__pos_mgr = pos_mgr
24 self._font = base.loader.load_font(
25 'assets/fonts/Hanken-Book.ttf')
26 self._font.clear()
27 self._font.set_pixels_per_unit(60)
28 self._font.set_minfilter(Texture.FTLinearMipmapLinear)
29 self._font.set_outline((0, 0, 0, 1), .8, .2)
30 self._common = {
31 'scale': .046,
32 'text_font': self._font,
33 'text_fg': (.9, .9, .9, 1),
34 'relief': FLAT,
35 'frameColor': (.4, .4, .4, .14),
36 'rolloverSound': loader.load_sfx(
37 'assets/audio/sfx/rollover.ogg'),
38 'clickSound': loader.load_sfx(
39 'assets/audio/sfx/click.ogg')}
40 tooltip_args = self._common['text_font'], self._common['scale'], self._common['text_fg']
41 w, h = .8, 1.04
42 self._frm = AugmentedDirectFrame(frameColor=(.4, .4, .4, .06),
43 frameSize=(0, w, -h, 0),
44 parent=base.a2dTopRight,
45 pos=(-w, 0, 0),
46 delta_drag=LPoint3f(-w, 0, -h),
47 collapse_pos=(w - .06, 1, -h + .06),
48 pos_mgr=pos_mgr,
49 frame_name='inspector')
50 self.__z = -.08
51 p = self.__item._np.get_pos()
52 r = self.__item._np.get_r()
53 s = self.__item._np.get_scale()[0]
54 m = self.__item._mass
55 restitution = self.__item._restitution
56 f = self.__item._friction
57 _id = ''
58 if 'id' in self.__item.json:
59 _id = self.__item.json['id']
60 _strategy = ''
61 if 'strategy' in self.__item.json:
62 _strategy = self.__item.json['strategy']
63 _strategy_args = ''
64 if 'strategy_args' in self.__item.json:
65 _strategy_args = ' '.join(map(str, self.__item.json['strategy_args']))
66 t, pos_entry = self.__add_row('position', _('position'), f'{round(p.x, 3)} {round(p.z, 3)}', self.on_edit_position, _('position (e.g. 0.1 2.3 4.5)'))
67 t, rot_entry = self.__add_row('roll', _('roll'), f'{round(r, 3)}', self.on_edit_roll, _('roll (e.g. 90)'))
68 t, scale_entry = self.__add_row('scale', _('scale'), f'{round(s, 3)}', self.on_edit_scale, _('scale (e.g. 1.2)'))
69 t, mass_entry = self.__add_row('mass', _('mass'), f'{round(m, 3)}', self.on_edit_mass, _('mass (default 1; 0 if fixed)'))
70 t, restitution_entry = self.__add_row('restitution', _('restitution'), f'{round(restitution, 3)}', self.on_edit_restitution, _('restitution (default 0.5)'))
71 t, friction_entry = self.__add_row('friction', _('friction'), f'{round(f, 3)}', self.on_edit_friction, _('friction (default 0.5)'))
72 t, id_entry = self.__add_row('id', _('id'), _id, self.on_edit_id, _('id of the item (for the strategies)'))
73 # item_modules = glob('pmachines/items/*.py')
74 # item_modules = [basename(i)[:-3] for i in item_modules]
75 # strategy_items = ['']
76 # for item_module in item_modules:
77 # mod_name = 'pmachines.items.' + item_module
78 # for member in import_module(mod_name).__dict__.values():
79 # if isclass(member) and issubclass(member, ItemStrategy) and \
80 # member != ItemStrategy:
81 # strategy_items = list(set(strategy_items + [member.__name__]))
82 strategy_names = [s.__name__ for s in strategy_items]
83 t, strategy_entry = self.__add_row_option(_('strategy'), _strategy, strategy_names, self.on_edit_strategy, _('the strategy of the item'))
84
85 def strategy_set(comps):
86 strategy_labels = [f'inspector_strategy_{i.lower()}' for i in strategy_names]
87 for i in strategy_labels:
88 if i in self.__pos_mgr:
89 del self.__pos_mgr[i]
90 for l, b in zip(strategy_labels, comps):
91 b.__class__ = type('DirectFrameMixed', (DirectFrame, DirectGuiMixin), {})
92 p = b.pos_pixel()
93 self.__pos_mgr[l] = (p[0] + 5, p[1] + 10)
94 strategy_entry._show_cb = strategy_set
95 p = strategy_entry.pos_pixel()
96 self.__pos_mgr['editor_inspector_strategy'] = (p[0] + 5, p[1])
97
98 t, strategy_args_entry = self.__add_row('strategy_args', _('strategy_args'), _strategy_args, self.on_edit_strategy_args, _('the arguments of the strategy'))
99 fields = ['position', 'roll', 'scale', 'mass', 'restitution', 'friction', 'id', 'strategy', 'strategy_args']
100 Entries = namedtuple('Entries', fields)
101 self.__entries = Entries(pos_entry, rot_entry, scale_entry, mass_entry, restitution_entry, friction_entry, id_entry, strategy_entry, strategy_args_entry)
102 def load_images_btn(path, col):
103 colors = {
104 'gray': [
105 (.6, .6, .6, 1), # ready
106 (1, 1, 1, 1), # press
107 (.8, .8, .8, 1), # rollover
108 (.4, .4, .4, .4)],
109 'green': [
110 (.1, .68, .1, 1),
111 (.1, 1, .1, 1),
112 (.1, .84, .1, 1),
113 (.4, .1, .1, .4)]}[col]
114 return [self.__load_img_btn(path, col) for col in colors]
115 fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
116 b = DirectButton(
117 image=load_images_btn('exitRight', 'gray'), scale=.05,
118 pos=(.06, 1, -h + .06),
119 parent=self._frm, command=self.destroy, state=NORMAL, relief=FLAT,
120 frameColor=fcols[0],
121 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
122 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
123 b.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
124 pos_mgr['editor_inspector_close'] = b.pos_pixel()
125 b.set_tooltip(_('Close'), *tooltip_args)
126 self.accept('item-rototranslated', self.__on_item_rototranslated)
127 b = DirectButton(
128 image=load_images_btn('trashcan', 'gray'), scale=.05,
129 pos=(.18, 1, -h + .06),
130 parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
131 frameColor=fcols[0],
132 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
133 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
134 b.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
135 pos_mgr['editor_inspector_delete'] = b.pos_pixel()
136 b.set_tooltip(_('Delete the item'), *tooltip_args)
137
138 def __add_row(self, id_, label, text, callback, tooltip):
139 tw = 10
140 tooltip_args = self._common['text_font'], self._common['scale'], self._common['text_fg']
141 t = OnscreenText(
142 label,
143 pos=(.03, self.__z), parent=self._frm,
144 font=self._common['text_font'],
145 scale=self._common['scale'],
146 fg=self._common['text_fg'],
147 wordwrap=20, align=TextNode.ALeft)
148 e = DirectEntry(
149 scale=self._common['scale'],
150 pos=(.30, 1, self.__z),
151 entryFont=self._font,
152 width=tw,
153 cursorKeys=True,
154 frameColor=self._common['frameColor'],
155 initialText=text,
156 parent=self._frm,
157 text_fg=self._common['text_fg'],
158 command=callback)
159 e.__class__ = type('DirectEntryMixed', (DirectEntry, DirectGuiMixin), {})
160 e.set_tooltip(tooltip, *tooltip_args)
161 self.__pos_mgr[f'editor_inspector_{id_}'] = e.pos_pixel()
162 self.__z -= .1
163 return t, e
164
165 def __add_row_option(self, label, text, items, callback, tooltip):
166 tooltip_args = self._common['text_font'], self._common['scale'], self._common['text_fg']
167 t = OnscreenText(
168 label,
169 pos=(.03, self.__z), parent=self._frm,
170 font=self._common['text_font'],
171 scale=self._common['scale'],
172 fg=self._common['text_fg'],
173 wordwrap=20, align=TextNode.ALeft)
174 e = DirectOptionMenuTestable(
175 scale=self._common['scale'],
176 initialitem=text,
177 pos=(.30, 1, self.__z),
178 items=items,
179 parent=self._frm,
180 command=callback,
181 state=NORMAL,
182 relief=FLAT,
183 item_relief=FLAT,
184 frameColor=self._common['frameColor'],
185 item_frameColor=self._common['frameColor'],
186 popupMenu_frameColor=self._common['frameColor'],
187 popupMarker_frameColor=self._common['frameColor'],
188 text_font=self._font,
189 text_fg=self._common['text_fg'],
190 highlightColor=(.9, .9, .9, .9),
191 item_text_font=self._font,
192 item_text_fg=self._common['text_fg'],
193 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
194 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
195 e.__class__ = type('DirectOptionMenuMixed', (DirectOptionMenu, DirectGuiMixin), {})
196 e.set_tooltip(tooltip, *tooltip_args)
197 self.__z -= .1
198 return t, e
199
200 def __load_img_btn(self, path, col):
201 img = OnscreenImage('assets/images/buttons/%s.dds' % path)
202 img.set_transparency(True)
203 img.set_color(col)
204 img.detach_node()
205 return img
206
207 def __on_item_rototranslated(self, np):
208 pos = np.get_pos()
209 r = np.get_r()
210 self.__entries.position.set('%s %s' % (str(round(pos.x, 3)), str(round(pos.z, 3))))
211 self.__entries.roll.set('%s' % str(round(r, 3)))
212 self.__item.json['position'] = list(pos)
213 self.__item.json['roll'] = round(r, 3)
214
215 def __delete_item(self):
216 messenger.send('editor-inspector-delete', [self.__item])
217 self.destroy()
218
219 @property
220 def item(self):
221 return self.__item
222
223 def on_edit_position(self, txt):
224 x, z = map(float, txt.split())
225 self.__item.position = [x, 0, z]
226
227 def on_edit_roll(self, txt):
228 self.__item.roll = float(txt)
229
230 def on_edit_scale(self, txt):
231 self.__item.scale = float(txt)
232
233 def on_edit_mass(self, txt):
234 self.__item.mass = float(txt)
235
236 def on_edit_restitution(self, txt):
237 self.__item.restitution = float(txt)
238
239 def on_edit_friction(self, txt):
240 self.__item.friction = float(txt)
241
242 def on_edit_id(self, txt):
243 self.__item.id = txt
244
245 def on_edit_strategy(self, txt):
246 if not txt:
247 self.__entries.strategy_args.set('')
248 return
249 name2class = {
250 'StillStrategy': StillStrategy,
251 'UpStrategy': UpStrategy,
252 'HitStrategy': HitStrategy,
253 'DownStrategy': DownStrategy,
254 'FixedStrategy': FixedStrategy}
255 class_ = name2class[txt]
256 args = []
257 error = False
258 if txt == 'StillStrategy':
259 args += [self.__item._np]
260 if txt in ['UpStrategy', 'DownStrategy']:
261 args += [self.__item._np]
262 try:
263 args += [float(self.__entries.strategy_args.get())]
264 except ValueError:
265 error = True
266 if txt == 'HitStrategy':
267 for item in self.__all_items:
268 if item.id == self.__entries.strategy_args.get():
269 args += [item]
270 args += [self.__item.node]
271 args += [self.__item._world]
272 if not error:
273 self.__item.strategy = class_(*args)
274 self.__item.strategy_json = txt
275 else:
276 self.__show_error_popup()
277
278 def on_edit_strategy_args(self, txt):
279 self.__item.strategy_args_json = txt
280
281 def __show_error_popup(self):
282 self.__dialog = OkDialog(dialogName='Strategy args errors',
283 text=_('There are errors in the strategy args.'),
284 command=self.__actually_close)
285 self.__dialog['frameColor'] = (.4, .4, .4, .14)
286 self.__dialog['relief'] = FLAT
287 self.__dialog.component('text0')['fg'] = (.9, .9, .9, 1)
288 self.__dialog.component('text0')['font'] = self._font
289 for b in self.__dialog.buttonList:
290 b['frameColor'] = (.4, .4, .4, .14)
291 b.component('text0')['fg'] = (.9, .9, .9, 1)
292 b.component('text0')['font'] = self._font
293 b.component('text1')['fg'] = (.9, .1, .1, 1)
294 b.component('text1')['font'] = self._font
295 b.component('text2')['fg'] = (.9, .9, .1, 1)
296 b.component('text2')['font'] = self._font
297
298 def __actually_close(self, arg):
299 self.__entries.strategy.set('')
300 self.__entries.strategy_args.set('')
301 self.__dialog.cleanup()
302
303 def destroy(self):
304 self._frm.destroy()
305 self.ignore('item-rototranslated')
306 messenger.send('editor-inspector-destroy')
307
308
309 class PixelSpaceInspector(DirectObject):
310
311 def __init__(self, item, all_items):
312 info('PixelSpaceInspector')
313 super().__init__()
314 self.__item = item
315 self.__all_items = all_items
316 self._font = base.loader.load_font(
317 'assets/fonts/Hanken-Book.ttf')
318 self._font.clear()
319 self._font.set_pixels_per_unit(60)
320 self._font.set_minfilter(Texture.FTLinearMipmapLinear)
321 self._font.set_outline((0, 0, 0, 1), .8, .2)
322 self._common = {
323 'scale': .046,
324 'text_font': self._font,
325 'text_fg': (.9, .9, .9, 1),
326 'relief': FLAT,
327 'frameColor': (.4, .4, .4, .14),
328 'rolloverSound': loader.load_sfx(
329 'assets/audio/sfx/rollover.ogg'),
330 'clickSound': loader.load_sfx(
331 'assets/audio/sfx/click.ogg')}
332 w, h = .8, .36
333 self._frm = DirectFrame(frameColor=(.4, .4, .4, .06),
334 frameSize=(0, w, -h, 0),
335 parent=base.a2dTopRight,
336 pos=(-w, 0, 0))
337 self.__z = -.08
338 p = self.__item._np.get_pos()
339 _id = ''
340 if 'id' in self.__item.json:
341 _id = self.__item.json['id']
342 t, pos_entry = self.__add_row(_('position'), f'{round(p.x, 3)}, {round(p.z, 3)}', self.on_edit_position)
343 t, id_entry = self.__add_row(_('id'), _id, self.on_edit_id)
344 fields = ['position', 'id']
345 Entries = namedtuple('Entries', fields)
346 self.__entries = Entries(pos_entry, id_entry)
347 def load_images_btn(path, col):
348 colors = {
349 'gray': [
350 (.6, .6, .6, 1), # ready
351 (1, 1, 1, 1), # press
352 (.8, .8, .8, 1), # rollover
353 (.4, .4, .4, .4)],
354 'green': [
355 (.1, .68, .1, 1),
356 (.1, 1, .1, 1),
357 (.1, .84, .1, 1),
358 (.4, .1, .1, .4)]}[col]
359 return [self.__load_img_btn(path, col) for col in colors]
360 fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
361 DirectButton(
362 image=load_images_btn('exitRight', 'gray'), scale=.05,
363 pos=(.06, 1, -h + .06),
364 parent=self._frm, command=self.destroy, state=NORMAL, relief=FLAT,
365 frameColor=fcols[0],
366 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
367 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
368 self.accept('item-rototranslated', self.__on_item_rototranslated)
369 DirectButton(
370 image=load_images_btn('trashcan', 'gray'), scale=.05,
371 pos=(.18, 1, -h + .06),
372 parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
373 frameColor=fcols[0],
374 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
375 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
376
377 def __add_row(self, label, text, callback):
378 tw = 10
379 t = OnscreenText(
380 label,
381 pos=(.03, self.__z), parent=self._frm,
382 font=self._common['text_font'],
383 scale=self._common['scale'],
384 fg=self._common['text_fg'],
385 wordwrap=20, align=TextNode.ALeft)
386 e = DirectEntry(
387 scale=self._common['scale'],
388 pos=(.30, 1, self.__z),
389 entryFont=self._font,
390 width=tw,
391 cursorKeys=True,
392 frameColor=self._common['frameColor'],
393 initialText=text,
394 parent=self._frm,
395 text_fg=self._common['text_fg'],
396 command=callback)
397 self.__pos_mgr[f'editor_inspector_test_{id_}'] = e.pos_pixel()
398 self.__z -= .1
399 return t, e
400
401 def __load_img_btn(self, path, col):
402 img = OnscreenImage('assets/images/buttons/%s.dds' % path)
403 img.set_transparency(True)
404 img.set_color(col)
405 img.detach_node()
406 return img
407
408 def __on_item_rototranslated(self, np):
409 pos = np.pos2d_pixel()
410 self.__entries.position.set('%s %s' % (str(round(pos[0], 3)), str(round(pos[1], 3))))
411 self.__item.json['position'] = list(pos)
412
413 def __delete_item(self):
414 messenger.send('editor-inspector-delete', [self.__item])
415 self.destroy()
416
417 @property
418 def item(self):
419 return self.__item
420
421 def on_edit_position(self, txt):
422 x, z = map(float, txt.split())
423 self.__item.position = [x, 0, z]
424
425 def on_edit_id(self, txt):
426 self.__item.id = txt
427
428 def __actually_close(self, arg):
429 self.__entries.strategy.set('')
430 self.__entries.strategy_args.set('')
431 self.__dialog.cleanup()
432
433 def destroy(self):
434 self._frm.destroy()
435 self.ignore('item-rototranslated')
436 messenger.send('editor-inspector-destroy')
437
438
439 class WorldSpaceInspector(DirectObject):
440
441 def __init__(self, item, all_items, pos_mgr):
442 info('WorldSpaceInspector')
443 super().__init__()
444 self.__item = item
445 self.__all_items = all_items
446 self.__pos_mgr = pos_mgr
447 self._font = base.loader.load_font(
448 'assets/fonts/Hanken-Book.ttf')
449 self._font.clear()
450 self._font.set_pixels_per_unit(60)
451 self._font.set_minfilter(Texture.FTLinearMipmapLinear)
452 self._font.set_outline((0, 0, 0, 1), .8, .2)
453 self._common = {
454 'scale': .046,
455 'text_font': self._font,
456 'text_fg': (.9, .9, .9, 1),
457 'relief': FLAT,
458 'frameColor': (.4, .4, .4, .14),
459 'rolloverSound': loader.load_sfx(
460 'assets/audio/sfx/rollover.ogg'),
461 'clickSound': loader.load_sfx(
462 'assets/audio/sfx/click.ogg')}
463 tooltip_args = self._common['text_font'], self._common['scale'], self._common['text_fg']
464 w, h = .8, .36
465 self._frm = DirectFrame(frameColor=(.4, .4, .4, .06),
466 frameSize=(0, w, -h, 0),
467 parent=base.a2dTopRight,
468 pos=(-w, 0, 0))
469 self.__z = -.08
470 p = self.__item._np.get_pos()
471 _id = ''
472 if 'id' in self.__item.json:
473 _id = self.__item.json['id']
474 t, pos_entry = self.__add_row('position', _('position'), f'{round(p.x, 3)} {round(p.z, 3)}', self.on_edit_position, _('position (e.g. 0.1 2.3 4.5)'))
475 t, id_entry = self.__add_row('id', _('id'), _id, self.on_edit_id, _('id of the item (for the strategies)'))
476 fields = ['position', 'id']
477 Entries = namedtuple('Entries', fields)
478 self.__entries = Entries(pos_entry, id_entry)
479 def load_images_btn(path, col):
480 colors = {
481 'gray': [
482 (.6, .6, .6, 1), # ready
483 (1, 1, 1, 1), # press
484 (.8, .8, .8, 1), # rollover
485 (.4, .4, .4, .4)],
486 'green': [
487 (.1, .68, .1, 1),
488 (.1, 1, .1, 1),
489 (.1, .84, .1, 1),
490 (.4, .1, .1, .4)]}[col]
491 return [self.__load_img_btn(path, col) for col in colors]
492 fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
493 b = DirectButton(
494 image=load_images_btn('exitRight', 'gray'), scale=.05,
495 pos=(.06, 1, -h + .06),
496 parent=self._frm, command=self.destroy, state=NORMAL, relief=FLAT,
497 frameColor=fcols[0],
498 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
499 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
500 b.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
501 pos_mgr['editor_inspector_test_close'] = b.pos_pixel()
502 b.set_tooltip(_('Close'), *tooltip_args)
503 self.accept('item-rototranslated', self.__on_item_rototranslated)
504 b = DirectButton(
505 image=load_images_btn('trashcan', 'gray'), scale=.05,
506 pos=(.18, 1, -h + .06),
507 parent=self._frm, command=self.__delete_item, state=NORMAL, relief=FLAT,
508 frameColor=fcols[0],
509 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
510 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
511 b.__class__ = type('DirectButtonMixed', (DirectButton, DirectGuiMixin), {})
512 pos_mgr['editor_inspector_test_delete'] = b.pos_pixel()
513 b.set_tooltip(_('Delete the item'), *tooltip_args)
514
515 def __add_row(self, id_, label, text, callback, tooltip):
516 tw = 10
517 tooltip_args = self._common['text_font'], self._common['scale'], self._common['text_fg']
518 t = OnscreenText(
519 label,
520 pos=(.03, self.__z), parent=self._frm,
521 font=self._common['text_font'],
522 scale=self._common['scale'],
523 fg=self._common['text_fg'],
524 wordwrap=20, align=TextNode.ALeft)
525 e = DirectEntry(
526 scale=self._common['scale'],
527 pos=(.30, 1, self.__z),
528 entryFont=self._font,
529 width=tw,
530 cursorKeys=True,
531 frameColor=self._common['frameColor'],
532 initialText=text,
533 parent=self._frm,
534 text_fg=self._common['text_fg'],
535 command=callback)
536 e.__class__ = type('DirectEntryMixed', (DirectEntry, DirectGuiMixin), {})
537 e.set_tooltip(tooltip, *tooltip_args)
538 self.__pos_mgr[f'editor_inspector_test_{id_}'] = e.pos_pixel()
539 self.__z -= .1
540 return t, e
541
542 def __load_img_btn(self, path, col):
543 img = OnscreenImage('assets/images/buttons/%s.dds' % path)
544 img.set_transparency(True)
545 img.set_color(col)
546 img.detach_node()
547 return img
548
549 def __on_item_rototranslated(self, np):
550 pos = np.get_pos()
551 self.__entries.position.set('%s %s' % (str(round(pos.x, 3)), str(round(pos.z, 3))))
552 self.__item.json['position'] = list(pos)
553
554 def __delete_item(self):
555 messenger.send('editor-inspector-delete', [self.__item])
556 self.destroy()
557
558 @property
559 def item(self):
560 return self.__item
561
562 def on_edit_position(self, txt):
563 x, z = map(float, txt.split())
564 self.__item.position = [x, 0, z]
565
566 def on_edit_id(self, txt):
567 self.__item.id = txt
568
569 def __actually_close(self, arg):
570 self.__entries.strategy.set('')
571 self.__entries.strategy_args.set('')
572 self.__dialog.cleanup()
573
574 def destroy(self):
575 self._frm.destroy()
576 self.ignore('item-rototranslated')
577 messenger.send('editor-inspector-destroy')