1 from panda3d
.core
import AmbientLight
, DirectionalLight
, Point3
, Texture
, \
2 TextPropertiesManager
, TextNode
3 from panda3d
.bullet
import BulletPlaneShape
, BulletGhostNode
4 from direct
.gui
.OnscreenImage
import OnscreenImage
5 from direct
.gui
.OnscreenText
import OnscreenText
6 from direct
.gui
.DirectGui
import DirectButton
, DirectFrame
7 from direct
.gui
.DirectGuiGlobals
import FLAT
, DISABLED
, NORMAL
8 from direct
.showbase
.DirectObject
import DirectObject
9 from pmachines
.items
.background
import Background
10 from pmachines
.items
.box
import Box
11 from pmachines
.sidepanel
import SidePanel
12 from lib
.engine
.gui
.cursor
import MouseCursor
13 from lib
.lib
.p3d
.gfx
import P3dGfxMgr
16 class Scene(DirectObject
):
18 def __init__(self
, world
):
22 self
._cursor
= MouseCursor(
23 'assets/buttons/arrowUpLeft.png', (.04, 1, .04), (.5, .5, .5, 1),
28 self
._set
_mouse
_plane
()
29 self
.items
= [Box(world
, self
._mouse
_plane
_node
, 3, self
.cb_inst
)]
32 self
._set
_instructions
()
34 self
._side
_panel
= SidePanel(world
, self
._mouse
_plane
_node
, (-5, 4), (-3, 1), 1)
35 taskMgr
.add(self
.on_frame
, 'on_frame')
37 def _set_camera(self
):
38 base
.camera
.set_pos(0, -20, 0)
39 base
.camera
.look_at(0, 0, 0)
41 def __load_img_btn(self
, path
, col
):
42 img
= OnscreenImage('assets/buttons/%s.png' % path
)
43 img
.set_transparency(True)
49 def load_images_btn(path
, col
):
52 (.6, .6, .6, 1), # ready
54 (.8, .8, .8, 1), # rollover
60 (.4, .1, .1, .4)]}[col
]
61 return [self
.__load
_img
_btn
(path
, col
) for col
in colors
]
62 abl
, abr
= base
.a2dBottomLeft
, base
.a2dBottomRight
64 ('home', self
.on_home
, DISABLED
, abl
, 'gray'),
65 ('information', self
.on_information
, DISABLED
, abl
, 'gray'),
66 ('right', self
.on_play
, NORMAL
, abr
, 'green'),
67 ('next', self
.on_next
, DISABLED
, abr
, 'gray'),
68 ('previous', self
.on_prev
, DISABLED
, abr
, 'gray'),
69 ('rewind', self
.on_rewind
, DISABLED
, abr
, 'gray')]
72 for binfo
in btn_info
:
73 imgs
= load_images_btn(binfo
[0], binfo
[4])
74 if binfo
[3] == base
.a2dBottomLeft
:
80 fcols
= (.4, .4, .4, .14), (.3, .3, .3, .05)
82 image
=imgs
, scale
=.05, pos
=(sign
* (.06 + .11 * num
), 1, .06),
83 parent
=binfo
[3], command
=binfo
[1], state
=binfo
[2], relief
=FLAT
,
84 frameColor
=fcols
[0] if binfo
[2] == NORMAL
else fcols
[1],
85 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
86 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
87 btn
.set_transparency(True)
89 self
.__home
_btn
, self
.__info
_btn
, self
.__right
_btn
, self
.__next
_btn
, \
90 self
.__prev
_btn
, self
.__rewind
_btn
= btns
92 def _set_directional_light(self
, name
, hpr
, color
):
93 light
= DirectionalLight(name
)
94 light_np
= render
.attach_new_node(light
)
95 light_np
.set_hpr(*hpr
)
96 light
.set_color(color
)
97 render
.set_light(light_np
)
99 def _set_lights(self
):
100 alight
= AmbientLight('alight') # for ao
101 alight
.set_color((.4, .4, .4, 1))
102 alnp
= render
.attach_new_node(alight
)
103 render
.set_light(alnp
)
104 self
._set
_directional
_light
('key light', (315, -60, 0),
106 self
._set
_directional
_light
('fill light', (195, -30, 0),
108 self
._set
_directional
_light
('rim light', (75, -30, 0), (.3, .3, .3, 1))
110 def _set_input(self
):
111 self
.accept('mouse1', self
.on_click_l
)
112 self
.accept('mouse1-up', self
.on_release
)
113 self
.accept('mouse3', self
.on_click_r
)
114 self
.accept('mouse3-up', self
.on_release
)
116 def _set_mouse_plane(self
):
117 shape
= BulletPlaneShape((0, -1, 0), 0)
118 #self._mouse_plane_node = BulletRigidBodyNode('mouse plane')
119 self
._mouse
_plane
_node
= BulletGhostNode('mouse plane')
120 self
._mouse
_plane
_node
.addShape(shape
)
121 #np = render.attachNewNode(self._mouse_plane_node)
122 #self._world.attachRigidBody(self._mouse_plane_node)
123 self
._world
.attach_ghost(self
._mouse
_plane
_node
)
126 if not base
.mouseWatcherNode
.has_mouse(): return []
127 p_from
, p_to
= P3dGfxMgr
.world_from_to(base
.mouseWatcherNode
.get_mouse())
128 return self
._world
.ray_test_all(p_from
, p_to
).get_hits()
130 def _on_click(self
, method
):
133 for hit
in self
._get
_hits
():
134 if hit
.get_node() == self
._mouse
_plane
_node
:
135 pos
= hit
.get_hit_pos()
136 for hit
in self
._get
_hits
():
137 for item
in [i
for i
in self
.items
if hit
.get_node() == i
.node
]:
138 getattr(item
, method
)(pos
)
139 img
= 'move' if method
== 'on_click_l' else 'rotate'
140 self
._cursor
.set_image('assets/buttons/%s.png' % img
)
142 def on_click_l(self
):
143 self
._on
_click
('on_click_l')
145 def on_click_r(self
):
146 self
._on
_click
('on_click_r')
148 def on_release(self
):
149 [item
.on_release() for item
in self
.items
]
150 self
._cursor
.set_image('assets/buttons/arrowUpLeft.png')
152 def on_aspect_ratio_changed(self
):
153 [item
.on_aspect_ratio_changed() for item
in self
.items
]
154 self
._side
_panel
.update(self
.items
)
156 def on_frame(self
, task
):
157 hits
= self
._get
_hits
()
159 for hit
in self
._get
_hits
():
160 if hit
.get_node() == self
._mouse
_plane
_node
:
161 pos
= hit
.get_hit_pos()
162 hit_nodes
= [hit
.get_node() for hit
in hits
]
163 items_hit
= [itm
for itm
in self
.items
if itm
.node
in hit_nodes
]
164 items_no_hit
= [itm
for itm
in self
.items
if itm
not in items_hit
]
165 [itm
.on_mouse_on() for itm
in items_hit
]
166 [itm
.on_mouse_off() for itm
in items_no_hit
]
168 [itm
.on_mouse_move(pos
) for itm
in self
.items
]
171 def cb_inst(self
, item
):
175 [itm
.play() for itm
in self
.items
]
189 def on_information(self
):
190 print('on_information')
192 def _set_instructions(self
):
193 mgr
= TextPropertiesManager
.get_global_ptr()
194 for name
in ['mouse_l', 'mouse_r']:
195 graphic
= OnscreenImage('assets/buttons/%s.png' % name
)
196 graphic
.set_scale(.5)
197 graphic
.get_texture().set_minfilter(Texture
.FTLinearMipmapLinear
)
198 graphic
.get_texture().set_anisotropic_degree(2)
199 mgr
.set_graphic(name
, graphic
)
201 graphic
.set_transparency(True)
202 graphic
.detach_node()
203 frm
= DirectFrame(frameColor
=(.4, .4, .4, .06),
204 frameSize
=(-.6, .6, -.3, .3))
205 font
= base
.loader
.load_font('assets/fonts/Hanken-Book.ttf')
207 font
.set_pixels_per_unit(60)
208 font
.set_minfilter(Texture
.FTLinearMipmapLinear
)
209 font
.set_outline((0, 0, 0, 1), .8, .2)
210 txt
= _('keep \5mouse_l\5 pressed to drag an item\n\n'
211 'keep \5mouse_r\5 pressed to rotate an item')
212 self
._txt
= OnscreenText(
213 txt
, parent
=frm
, font
=font
, scale
=0.06, fg
=(.9, .9, .9, 1),
214 align
=TextNode
.A_left
)
215 u_l
= self
._txt
.textNode
.get_upper_left_3d()
216 l_r
= self
._txt
.textNode
.get_lower_right_3d()
217 w
, h
= l_r
[0] - u_l
[0], u_l
[2] - l_r
[2]
220 z
= h
/ 2 - font
.get_line_height() * self
._txt
['scale'][1]
221 z
+= (btn_scale
+ 2 * mar
) / 2
222 self
._txt
['pos'] = -w
/ 2, z
223 u_l
= self
._txt
.textNode
.get_upper_left_3d()
224 l_r
= self
._txt
.textNode
.get_lower_right_3d()
225 c_l_r
= l_r
[0], l_r
[1], l_r
[2] - 2 * mar
- btn_scale
226 fsz
= u_l
[0] - mar
, l_r
[0] + mar
, c_l_r
[2] - mar
, u_l
[2] + mar
227 frm
['frameSize'] = fsz
229 (.6, .6, .6, 1), # ready
230 (1, 1, 1, 1), # press
231 (.8, .8, .8, 1), # rollover
233 imgs
= [self
.__load
_img
_btn
('exitRight', col
) for col
in colors
]
235 image
=imgs
, scale
=btn_scale
,
236 pos
=(l_r
[0] - btn_scale
, 1, l_r
[2] - mar
- btn_scale
),
237 parent
=frm
, command
=self
.__on
_close
_instructions
, extraArgs
=[frm
],
238 relief
=FLAT
, frameColor
=(.6, .6, .6, .08),
239 rolloverSound
=loader
.load_sfx('assets/audio/sfx/rollover.ogg'),
240 clickSound
=loader
.load_sfx('assets/audio/sfx/click.ogg'))
241 btn
.set_transparency(True)
243 def __store_state(self
):
245 self
.__home
_btn
, self
.__info
_btn
, self
.__right
_btn
,
246 self
.__next
_btn
, self
.__prev
_btn
, self
.__rewind
_btn
]
247 self
.__btn
_state
= [btn
['state'] for btn
in btns
]
249 btn
['state'] = DISABLED
250 [itm
.store_state() for itm
in self
.items
]
252 def __restore_state(self
):
254 self
.__home
_btn
, self
.__info
_btn
, self
.__right
_btn
,
255 self
.__next
_btn
, self
.__prev
_btn
, self
.__rewind
_btn
]
256 for btn
, state
in zip(btns
, self
.__btn
_state
):
258 [itm
.restore_state() for itm
in self
.items
]
261 def __on_close_instructions(self
, frm
):
263 self
.__restore
_state
()