ya2 · news · projects · code · about

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