ya2 · news · projects · code · about

renamed modules
[pmachines.git] / pmachines / gui / sidepanel.py
diff --git a/pmachines/gui/sidepanel.py b/pmachines/gui/sidepanel.py
new file mode 100644 (file)
index 0000000..39afaa4
--- /dev/null
@@ -0,0 +1,132 @@
+from textwrap import dedent
+from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, \
+    GeomVertexWriter, GeomTriangles, GeomNode, Shader, Point3, Plane, Vec3
+from ya2.p3d.gfx import P3dGfxMgr
+
+
+class SidePanel:
+
+    def __init__(self, world, plane_node, top_l, bottom_r, y, items):
+        self._world = world
+        self._plane_node = plane_node
+        self._set((-1, 1), y)
+        self.update(items)
+
+    def update(self, items):
+        p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
+        for hit in self._world.ray_test_all(p_from, p_to).get_hits():
+            if hit.get_node() == self._plane_node:
+                pos = hit.get_hit_pos()
+        y = 0
+        corner = -20, 20
+        for item in items:
+            if not item._instantiated:
+                bounds = item._np.get_tight_bounds()
+                if bounds[1][1] > y:
+                    y = bounds[1][1]
+                icorner = item.get_corner()
+                icorner = P3dGfxMgr.screen_coord(icorner)
+                if icorner[0] > corner[0]:
+                    corner = icorner[0], corner[1]
+                if icorner[1] < corner[1]:
+                    corner = corner[0], icorner[1]
+        self._set((pos[0], pos[2]), y)
+        bounds = self._np.get_tight_bounds()
+        corner3d = bounds[1][0], bounds[1][1], bounds[0][2]
+        corner2d = P3dGfxMgr.screen_coord(corner3d)
+        plane = Plane(Vec3(0, 1, 0), y)
+        pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
+        ar, margin = base.get_aspect_ratio(), .04
+        x = corner[0] / ar if ar >= 1 else corner[0]
+        z = corner[1] * ar if ar < 1 else corner[1]
+        x += margin / ar if ar >= 1 else margin
+        z -= margin * ar if ar < 1 else margin
+        base.camLens.extrude((x, z), near_pt, far_pt)
+        plane.intersects_line(
+            pos3d, render.get_relative_point(base.camera, near_pt),
+            render.get_relative_point(base.camera, far_pt))
+        corner_pos3d, near_pt, far_pt = Point3(), Point3(), Point3()
+        base.camLens.extrude((-1, 1), near_pt, far_pt)
+        plane.intersects_line(
+            corner_pos3d, render.get_relative_point(base.camera, near_pt),
+            render.get_relative_point(base.camera, far_pt))
+        self._np.set_pos((pos3d + corner_pos3d) / 2)
+        scale = Vec3(pos3d[0] - corner_pos3d[0], 1, corner_pos3d[2] - pos3d[2])
+        self._np.set_scale(scale)
+
+    def _set(self, pos, y):
+        if hasattr(self, '_np'):
+            self._np.remove_node()
+        vdata = GeomVertexData('quad', GeomVertexFormat.get_v3(), Geom.UHStatic)
+        vdata.setNumRows(2)
+        vertex = GeomVertexWriter(vdata, 'vertex')
+        vertex.add_data3(.5, 0, -.5)
+        vertex.add_data3(.5, 0, .5)
+        vertex.add_data3(-.5, 0, .5)
+        vertex.add_data3(-.5, 0, -.5)
+        prim = GeomTriangles(Geom.UHStatic)
+        prim.add_vertices(0, 1, 2)
+        prim.add_vertices(0, 2, 3)
+        prim.close_primitive()
+        geom = Geom(vdata)
+        geom.add_primitive(prim)
+        node = GeomNode('gnode')
+        node.add_geom(geom)
+        self._np = render.attach_new_node(node)
+        self._np.setTransparency(True)
+        self._np.set_pos(pos[0], y, pos[1])
+        vert = '''\
+            #version 130
+            uniform mat4 p3d_ModelViewProjectionMatrix;
+            in vec4 p3d_Vertex;
+            void main() {
+                gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; }'''
+        frag = '''\
+            #version 130
+            out vec4 p3d_FragColor;
+            void main() {
+                p3d_FragColor = vec4(.04, .04, .04, .08); }'''
+        self._np.set_shader(Shader.make(Shader.SL_GLSL, dedent(vert), dedent(frag)))
+        # mat = Material()
+        # mat.set_base_color((1, 1, 1, 1))
+        # mat.set_emission((1, 1, 1, 1))
+        # mat.set_metallic(.5)
+        # mat.set_roughness(.5)
+        # np.set_material(mat)
+        # texture_sz = 64
+        # base_color_pnm = PNMImage(texture_sz, texture_sz)
+        # base_color_pnm.fill(.1, .1, .1)
+        # base_color_pnm.add_alpha()
+        # base_color_pnm.alpha_fill(.04)
+        # base_color_tex = Texture('base color')
+        # base_color_tex.load(base_color_pnm)
+        # ts = TextureStage('base color')
+        # ts.set_mode(TextureStage.M_modulate)
+        # np.set_texture(ts, base_color_tex)
+        # emission_pnm = PNMImage(texture_sz, texture_sz)
+        # emission_pnm.fill(0, 0, 0)
+        # emission_tex = Texture('emission')
+        # emission_tex.load(emission_pnm)
+        # ts = TextureStage('emission')
+        # ts.set_mode(TextureStage.M_emission)
+        # np.set_texture(ts, emission_tex)
+        # metal_rough_pnm = PNMImage(texture_sz, texture_sz)
+        # ambient_occlusion = 1
+        # roughness = .5
+        # metallicity = .5
+        # metal_rough_pnm.fill(ambient_occlusion, roughness, metallicity)
+        # metal_rough_tex = Texture('ao metal roughness')
+        # metal_rough_tex.load(metal_rough_pnm)
+        # ts = TextureStage('ao metal roughness')
+        # ts.set_mode(TextureStage.M_selector)
+        # np.set_texture(ts, metal_rough_tex)
+        # normal_pnm = PNMImage(texture_sz, texture_sz)
+        # normal_pnm.fill(.5, .5, .1)
+        # normal_tex = Texture('normals')
+        # normal_tex.load(normal_pnm)
+        # ts = TextureStage('normals')
+        # ts.set_mode(TextureStage.M_normal)
+        # np.set_texture(ts, normal_tex)
+
+    def destroy(self):
+        self._np.remove_node()