ya2 · news · projects · code · about

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