ya2 · news · projects · code · about

77e980aa58d44fb523989bdb50ffb1ed3e2e6213
[pmachines.git] / pmachines / scene.py
1 from panda3d.core import AmbientLight, DirectionalLight, Point3
2 from panda3d.bullet import BulletPlaneShape, BulletGhostNode
3 from direct.gui.OnscreenImage import OnscreenImage
4 from direct.gui.DirectGui import DirectButton
5 from direct.gui.DirectGuiGlobals import FLAT, DISABLED, NORMAL
6 from direct.showbase.DirectObject import DirectObject
7 from pmachines.items.background import Background
8 from pmachines.items.box import Box
9 from pmachines.sidepanel import SidePanel
10 from lib.engine.gui.cursor import MouseCursor
11
12
13 class Scene(DirectObject):
14
15 def __init__(self, world):
16 super().__init__()
17 self._world = world
18 self._set_camera()
19 self._cursor = MouseCursor(
20 'assets/buttons/arrowUpLeft.png', (.04, 1, .04), (.5, .5, .5, 1),
21 (.01, .01))
22 self._set_gui()
23 self._set_lights()
24 self._set_input()
25 self._set_mouse_plane()
26 Background()
27 self.items = [Box(world, self._mouse_plane_node, 3, self.cb_inst)]
28 self._side_panel = SidePanel(world, self._mouse_plane_node, (-5, 4), (-3, 1), 1)
29 taskMgr.add(self.on_frame, 'on_frame')
30
31 def _set_camera(self):
32 base.camera.set_pos(0, -20, 0)
33 base.camera.look_at(0, 0, 0)
34
35 def _set_gui(self):
36 def load_img_btn(path, col):
37 img = OnscreenImage('assets/buttons/%s.png' % path)
38 img.set_transparency(True)
39 img.set_color(col)
40 img.detach_node()
41 return img
42 def load_images_btn(path, col):
43 colors = {
44 'gray': [
45 (.6, .6, .6, 1), # ready
46 (1, 1, 1, 1), # press
47 (.8, .8, .8, 1), # rollover
48 (.4, .4, .4, .4)],
49 'green': [
50 (.1, .68, .1, 1),
51 (.1, 1, .1, 1),
52 (.1, .84, .1, 1),
53 (.4, .1, .1, .4)]}[col]
54 return [load_img_btn(path, col) for col in colors]
55 abl, abr = base.a2dBottomLeft, base.a2dBottomRight
56 btn_info = [
57 ('home', self.on_home, DISABLED, abl, 'gray'),
58 ('information', self.on_information, DISABLED, abl, 'gray'),
59 ('right', self.on_play, NORMAL, abr, 'green'),
60 ('next', self.on_next, DISABLED, abr, 'gray'),
61 ('previous', self.on_prev, DISABLED, abr, 'gray'),
62 ('rewind', self.on_rewind, DISABLED, abr, 'gray')]
63 num_l = num_r = 0
64 for binfo in btn_info:
65 imgs = load_images_btn(binfo[0], binfo[4])
66 if binfo[3] == base.a2dBottomLeft:
67 sign, num = 1, num_l
68 num_l += 1
69 else:
70 sign, num = -1, num_r
71 num_r += 1
72 fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
73 btn = DirectButton(
74 image=imgs, scale=.05, pos=(sign * (.06 + .11 * num), 1, .06),
75 parent=binfo[3], command=binfo[1], state=binfo[2], relief=FLAT,
76 frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1],
77 rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
78 clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
79 btn.set_transparency(True)
80
81 def _set_directional_light(self, name, hpr, color):
82 light = DirectionalLight(name)
83 light_np = render.attach_new_node(light)
84 light_np.set_hpr(*hpr)
85 light.set_color(color)
86 render.set_light(light_np)
87
88 def _set_lights(self):
89 alight = AmbientLight('alight') # for ao
90 alight.set_color((.4, .4, .4, 1))
91 alnp = render.attach_new_node(alight)
92 render.set_light(alnp)
93 self._set_directional_light('key light', (315, -60, 0),
94 (3.6, 3.6, 3.6, 1))
95 self._set_directional_light('fill light', (195, -30, 0),
96 (.4, .4, .4, 1))
97 self._set_directional_light('rim light', (75, -30, 0), (.3, .3, .3, 1))
98
99 def _set_input(self):
100 self.accept('mouse1', self.on_click_l)
101 self.accept('mouse1-up', self.on_release)
102 self.accept('mouse3', self.on_click_r)
103 self.accept('mouse3-up', self.on_release)
104
105 def _set_mouse_plane(self):
106 shape = BulletPlaneShape((0, -1, 0), 0)
107 #self._mouse_plane_node = BulletRigidBodyNode('mouse plane')
108 self._mouse_plane_node = BulletGhostNode('mouse plane')
109 self._mouse_plane_node.addShape(shape)
110 #np = render.attachNewNode(self._mouse_plane_node)
111 #self._world.attachRigidBody(self._mouse_plane_node)
112 self._world.attachGhost(self._mouse_plane_node)
113
114 def _get_hits(self):
115 if not base.mouseWatcherNode.has_mouse(): return []
116 p_from, p_to = Point3(), Point3() # in camera coordinates
117 base.camLens.extrude(base.mouseWatcherNode.get_mouse(), p_from, p_to)
118 p_from = render.get_relative_point(base.cam, p_from) # global coords
119 p_to = render.get_relative_point(base.cam, p_to) # global coords
120 return self._world.ray_test_all(p_from, p_to).get_hits()
121
122 def _on_click(self, method):
123 for hit in self._get_hits():
124 if hit.get_node() == self._mouse_plane_node:
125 pos = hit.get_hit_pos()
126 for hit in self._get_hits():
127 for item in [i for i in self.items if hit.get_node() == i.node]:
128 getattr(item, method)(pos)
129 img = 'move' if method == 'on_click_l' else 'rotate'
130 self._cursor.set_image('assets/buttons/%s.png' % img)
131
132 def on_click_l(self):
133 self._on_click('on_click_l')
134
135 def on_click_r(self):
136 self._on_click('on_click_r')
137
138 def on_release(self):
139 [item.on_release() for item in self.items]
140 self._cursor.set_image('assets/buttons/arrowUpLeft.png')
141
142 def on_aspect_ratio_changed(self):
143 [item.on_aspect_ratio_changed() for item in self.items]
144 self._side_panel.update(self.items)
145
146 def on_frame(self, task):
147 hits = self._get_hits()
148 pos = None
149 for hit in self._get_hits():
150 if hit.get_node() == self._mouse_plane_node:
151 pos = hit.get_hit_pos()
152 hit_nodes = [hit.get_node() for hit in hits]
153 items_hit = [itm for itm in self.items if itm.node in hit_nodes]
154 items_no_hit = [itm for itm in self.items if itm not in items_hit]
155 [itm.on_mouse_on() for itm in items_hit]
156 [itm.on_mouse_off() for itm in items_no_hit]
157 if pos:
158 [itm.on_mouse_move(pos) for itm in self.items]
159 return task.cont
160
161 def cb_inst(self, item):
162 self.items += [item]
163
164 def on_play(self):
165 [itm.play() for itm in self.items]
166
167 def on_next(self):
168 print('on_next')
169
170 def on_prev(self):
171 print('on_prev')
172
173 def on_rewind(self):
174 print('on_rewind')
175
176 def on_home(self):
177 print('on_home')
178
179 def on_information(self):
180 print('on_information')