ya2 · news · projects · code · about

audio
[pmachines.git] / pmachines / scene.py
index 3baf29aed1cac5a8ef6ef1ec3ad8df3df4ad77a7..f67c45b75587804f3ca316eb6455df4e94c548eb 100644 (file)
@@ -1,7 +1,12 @@
 from panda3d.core import AmbientLight, DirectionalLight, Point3
+from panda3d.bullet import BulletPlaneShape, BulletGhostNode
+from direct.gui.OnscreenImage import OnscreenImage
+from direct.gui.DirectGui import DirectButton
+from direct.gui.DirectGuiGlobals import FLAT, DISABLED, NORMAL
 from direct.showbase.DirectObject import DirectObject
 from pmachines.items.background import Background
 from pmachines.items.box import Box
+from lib.engine.gui.cursor import MouseCursor
 
 
 class Scene(DirectObject):
@@ -10,15 +15,67 @@ class Scene(DirectObject):
         super().__init__()
         self._world = world
         self._set_camera()
+        self._cursor = MouseCursor(
+            'assets/buttons/arrowUpLeft.png', (.04, 1, .04), (.5, .5, .5, 1),
+            (.01, .01))
+        self._set_gui()
         self._set_lights()
         self._set_input()
+        self._set_mouse_plane()
         Background()
         self.items = [Box(world)]
+        taskMgr.add(self.on_frame, 'on_frame')
 
     def _set_camera(self):
         base.camera.set_pos(0, -20, 0)
         base.camera.look_at(0, 0, 0)
 
+    def _set_gui(self):
+        def load_img_btn(path, col):
+            img = OnscreenImage('assets/buttons/%s.png' % path)
+            img.set_transparency(True)
+            img.set_color(col)
+            img.detach_node()
+            return img
+        def load_images_btn(path, col):
+            colors = {
+                'gray': [
+                    (.6, .6, .6, 1),  # ready
+                    (1, 1, 1, 1), # press
+                    (.8, .8, .8, 1), # rollover
+                    (.4, .4, .4, .4)],
+                'green': [
+                    (.1, .68, .1, 1),
+                    (.1, 1, .1, 1),
+                    (.1, .84, .1, 1),
+                    (.4, .1, .1, .4)]}[col]
+            return [load_img_btn(path, col) for col in colors]
+        abl, abr = base.a2dBottomLeft, base.a2dBottomRight
+        btn_info = [
+            ('home', self.on_home, DISABLED, abl, 'gray'),
+            ('information', self.on_information, DISABLED, abl, 'gray'),
+            ('right', self.on_play, NORMAL, abr, 'green'),
+            ('next', self.on_next, DISABLED, abr, 'gray'),
+            ('previous', self.on_prev, DISABLED, abr, 'gray'),
+            ('rewind', self.on_rewind, DISABLED, abr, 'gray')]
+        num_l = num_r = 0
+        for binfo in btn_info:
+            imgs = load_images_btn(binfo[0], binfo[4])
+            if binfo[3] == base.a2dBottomLeft:
+                sign, num = 1, num_l
+                num_l += 1
+            else:
+                sign, num = -1, num_r
+                num_r += 1
+            fcols = (.4, .4, .4, .14), (.3, .3, .3, .05)
+            btn = DirectButton(
+                image=imgs, scale=.05, pos=(sign * (.06 + .11 * num), 1, .06),
+                parent=binfo[3], command=binfo[1], state=binfo[2], relief=FLAT,
+                frameColor=fcols[0] if binfo[2] == NORMAL else fcols[1],
+                rolloverSound=loader.load_sfx('assets/audio/sfx/rollover.ogg'),
+                clickSound=loader.load_sfx('assets/audio/sfx/click.ogg'))
+            btn.set_transparency(True)
+
     def _set_directional_light(self, name, hpr, color):
         light = DirectionalLight(name)
         light_np = render.attach_new_node(light)
@@ -38,15 +95,78 @@ class Scene(DirectObject):
         self._set_directional_light('rim light', (75, -30, 0), (.3, .3, .3, 1))
 
     def _set_input(self):
-        self.accept('mouse1-up', self.on_click)
+        self.accept('mouse1', self.on_click_l)
+        self.accept('mouse1-up', self.on_release)
+        self.accept('mouse3', self.on_click_r)
+        self.accept('mouse3-up', self.on_release)
+
+    def _set_mouse_plane(self):
+        shape = BulletPlaneShape((0, -1, 0), 1)
+        #self._mouse_plane_node = BulletRigidBodyNode('mouse plane')
+        self._mouse_plane_node = BulletGhostNode('mouse plane')
+        self._mouse_plane_node.addShape(shape)
+        #np = render.attachNewNode(self._mouse_plane_node)
+        #self._world.attachRigidBody(self._mouse_plane_node)
+        self._world.attachGhost(self._mouse_plane_node)
 
-    def on_click(self):
-        if not base.mouseWatcherNode.has_mouse(): return
+    def _get_hits(self):
+        if not base.mouseWatcherNode.has_mouse(): return []
         p_from = Point3()  # in camera coordinates
         p_to = Point3()    # in camera coordinates
         base.camLens.extrude(base.mouseWatcherNode.get_mouse(), p_from, p_to)
         p_from = render.get_relative_point(base.cam, p_from)  # global coords
         p_to = render.get_relative_point(base.cam, p_to)  # global coords
-        for hit in self._world.ray_test_all(p_from, p_to).get_hits():
+        return self._world.ray_test_all(p_from, p_to).get_hits()
+
+    def _on_click(self, method):
+        for hit in self._get_hits():
+            if hit.get_node() == self._mouse_plane_node:
+                pos = hit.get_hit_pos()
+        for hit in self._get_hits():
             for item in [i for i in self.items if hit.get_node() == i.node]:
-                item.on_click(hit)
+                getattr(item, method)(pos)
+                img = 'move' if method == 'on_click_l' else 'rotate'
+                self._cursor.set_image('assets/buttons/%s.png' % img)
+
+    def on_click_l(self):
+        self._on_click('on_click_l')
+
+    def on_click_r(self):
+        self._on_click('on_click_r')
+
+    def on_release(self):
+        [item.on_release() for item in self.items]
+        self._cursor.set_image('assets/buttons/arrowUpLeft.png')
+
+    def on_frame(self, task):
+        hits = self._get_hits()
+        pos = None
+        for hit in self._get_hits():
+            if hit.get_node() == self._mouse_plane_node:
+                pos = hit.get_hit_pos()
+        hit_nodes = [hit.get_node() for hit in hits]
+        items_hit = [itm for itm in self.items if itm.node in hit_nodes]
+        items_no_hit = [itm for itm in self.items if itm not in items_hit]
+        [itm.on_mouse_on() for itm in items_hit]
+        [itm.on_mouse_off() for itm in items_no_hit]
+        if pos:
+            [itm.on_mouse_move(pos) for itm in self.items]
+        return task.cont
+
+    def on_play(self):
+        [itm.play() for itm in self.items]
+
+    def on_next(self):
+        print('on_next')
+
+    def on_prev(self):
+        print('on_prev')
+
+    def on_rewind(self):
+        print('on_rewind')
+
+    def on_home(self):
+        print('on_home')
+
+    def on_information(self):
+        print('on_information')