4a5a1d9ffd07970e808b8e7f753744ce661c793f
1 from copy
import deepcopy
4 from panda3d
.core
import Texture
, TextNode
5 from direct
.gui
.OnscreenImage
import OnscreenImage
6 from direct
.gui
.DirectGui
import DirectButton
, DirectFrame
, DirectEntry
, YesNoDialog
7 from direct
.gui
.DirectGuiGlobals
import FLAT
, NORMAL
8 from direct
.gui
.OnscreenText
import OnscreenText
9 from direct
.showbase
.DirectObject
import DirectObject
10 from pmachines
.editor
.scene_list
import SceneList
11 from pmachines
.editor
.inspector
import Inspector
14 class SceneEditor(DirectObject
):
16 def __init__(self
, json
, json_name
):
19 self
.__json
_name
= json_name
20 self
.__inspector
= None
21 self
._font
= base
.loader
.load_font(
22 'assets/fonts/Hanken-Book.ttf')
24 self
._font
.set_pixels_per_unit(60)
25 self
._font
.set_minfilter(Texture
.FTLinearMipmapLinear
)
26 self
._font
.set_outline((0, 0, 0, 1), .8, .2)
29 'text_font': self
._font
,
30 'text_fg': (.9, .9, .9, 1),
32 'frameColor': (.4, .4, .4, .14),
33 'rolloverSound': loader
.load_sfx(
34 'assets/audio/sfx/rollover.ogg'),
35 'clickSound': loader
.load_sfx(
36 'assets/audio/sfx/click.ogg')}
37 w
, h
, tw
, l
= 1.8, .9, 30, .36
38 self
._frm
= DirectFrame(frameColor
=(.4, .4, .4, .06),
39 frameSize
=(0, w
, 0, h
),
40 parent
=base
.a2dBottomCenter
,
43 _('Name'), pos
=(l
- .03, h
- .1), parent
=self
._frm
,
44 font
=self
._common
['text_font'],
45 scale
=self
._common
['scale'],
46 fg
=self
._common
['text_fg'],
47 align
=TextNode
.A_right
)
48 self
.__name
_entry
= DirectEntry(
49 scale
=self
._common
['scale'],
53 frameColor
=self
._common
['frameColor'],
54 initialText
=json
['name'],
56 text_fg
=self
._common
['text_fg'])
58 _('Description'), pos
=(l
- .03, h
- .2), parent
=self
._frm
,
59 font
=self
._common
['text_font'],
60 scale
=self
._common
['scale'],
61 fg
=self
._common
['text_fg'],
62 align
=TextNode
.A_right
)
63 def add_line_break(txt
, entry
):
64 curpos
= entry
.node().getCursorPosition()
65 entry
.set(txt
[:curpos
]+ "\n" + txt
[curpos
:])
66 entry
.node().setCursorPosition(curpos
+1)
68 self
.__instructions
_entry
= DirectEntry(
69 scale
=self
._common
['scale'],
75 frameColor
=self
._common
['frameColor'],
76 initialText
=json
['instructions'].replace('\\n', '\n'),
78 text_fg
=self
._common
['text_fg'])
79 self
.__instructions
_entry
['command'] = add_line_break
80 self
.__instructions
_entry
['extraArgs'] = [self
.__instructions
_entry
]
81 def load_images_btn(path
, col
):
84 (.6, .6, .6, 1), # ready
86 (.8, .8, .8, 1), # rollover
92 (.4, .1, .1, .4)]}[col
]
93 return [self
.__load
_img
_btn
(path
, col
) for col
in colors
]
94 fcols
= (.4, .4, .4, .14), (.3, .3, .3, .05)
96 image
=load_images_btn('exitRight', 'gray'), scale
=.05,
98 parent
=self
._frm
, command
=self
.__on
_close
, state
=NORMAL
, relief
=FLAT
,
100 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
101 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
103 image
=load_images_btn('save', 'gray'), scale
=.05,
105 parent
=self
._frm
, command
=self
.__on
_save
, state
=NORMAL
, relief
=FLAT
,
107 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
108 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
110 image
=load_images_btn('menuList', 'gray'), scale
=.05,
112 parent
=self
._frm
, command
=self
.__on
_scene
_list
, state
=NORMAL
, relief
=FLAT
,
114 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
115 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
116 messenger
.send('editor-start')
117 self
.accept('editor-item-click-l', self
.__on
_item
_click
_l)
118 self
.accept('editor-inspector-destroy', self
.__on
_inspector
_destroy
)
120 def __on_close(self
):
121 self
.__json
['name'] = self
.__name
_entry
.get()
122 self
.__json
['instructions'] = self
.__instructions
_entry
.get()
123 if self
.__compute
_hash
() == self
.__json
['version']:
126 self
.__dialog
= YesNoDialog(dialogName
='Unsaved changes',
127 text
=_('You have unsaved changes. Really quit?'),
128 command
=self
.__actually
_close
)
129 self
.__dialog
['frameColor'] = (.4, .4, .4, .14)
130 self
.__dialog
['relief'] = FLAT
131 self
.__dialog
.component('text0')['fg'] = (.9, .9, .9, 1)
132 self
.__dialog
.component('text0')['font'] = self
._font
133 for b
in self
.__dialog
.buttonList
:
134 b
['frameColor'] = (.4, .4, .4, .14)
135 b
.component('text0')['fg'] = (.9, .9, .9, 1)
136 b
.component('text0')['font'] = self
._font
137 b
.component('text1')['fg'] = (.9, .1, .1, 1)
138 b
.component('text1')['font'] = self
._font
139 b
.component('text2')['fg'] = (.9, .9, .1, 1)
140 b
.component('text2')['font'] = self
._font
142 def __actually_close(self
, arg
):
145 messenger
.send('editor-stop')
146 self
.__dialog
.cleanup()
149 self
.__json
['name'] = self
.__name
_entry
.get()
150 self
.__json
['instructions'] = self
.__instructions
_entry
.get()
151 self
.__json
['version'] = self
.__compute
_hash
()
152 with
open('assets/scenes/%s.json' % self
.__json
_name
, 'w') as f
:
153 f
.write(dumps(self
.__json
, indent
=2, sort_keys
=True))
155 def __on_scene_list(self
):
158 def __load_img_btn(self
, path
, col
):
159 img
= OnscreenImage('assets/images/buttons/%s.dds' % path
)
160 img
.set_transparency(True)
165 def __compute_hash(self
):
166 new_dict
= deepcopy(self
.__json
)
167 del new_dict
['version']
168 new_dict_str
= str(dumps(new_dict
, indent
=2, sort_keys
=True))
169 h
= hashlib
.new('sha256')
170 h
.update(new_dict_str
.encode())
171 return h
.hexdigest()[:12]
173 def __on_item_click_l(self
, item
):
174 if self
.__inspector
and self
.__inspector
.item
== item
: return
176 self
.__inspector
.destroy()
177 self
.__inspector
= Inspector(item
)
179 def __on_inspector_destroy(self
):
180 self
.__inspector
= None