Browse Source

wallet: create a chatbox

rsx 2 years ago
parent
commit
7e9fba23fb
4 changed files with 144 additions and 26 deletions
  1. 106 10
      bin/darkwallet/gui/__init__.py
  2. 23 8
      bin/darkwallet/gui/api.py
  3. 12 6
      bin/darkwallet/gui/gfx.py
  4. 3 2
      bin/darkwallet/gui/print_tree.py

+ 106 - 10
bin/darkwallet/gui/__init__.py

@@ -1,7 +1,16 @@
+from pydrk import SceneNodeType, PropertyType, vertex, face
 from .print_tree import print_tree
 from .api import *
-from .gfx import Layer
+from .gfx import Layer, add_object
 from . import settings
+import time
+
+latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+numerals = "0123456789"
+punct = " .,<>/\\'[]{}:`~!@#$%^&*()_+?"
+keycmds = [
+    "Backspace"
+]
 
 class App(EventLoop):
 
@@ -15,10 +24,19 @@ class App(EventLoop):
         self.chatbox_layer.resize(w, h)
 
         self.chatbox_layer.add_obj("outline")
+        self.chatbox_layer.add_obj("user_input")
+
+        self.cursor_layer = Layer("cursor_layer")
+        self.cursor_layer.add_obj("cursor")
+
+        self.user_input = ""
+        self.last_keypress_time = 0
 
     def resize_event(self, w, h):
         self.chatbox_layer.resize(w, h)
+        self.cursor_layer.resize(w, h)
         resize_box()
+        draw_txt(self.user_input)
 
     def mouse_click(self, x, y):
         print(f"mouse click ({x}, {y})")
@@ -35,10 +53,85 @@ class App(EventLoop):
         elif keymods.ctrl and keycode == "-":
             settings.ui_scale *= 0.99
             print(settings.ui_scale)
+        elif keymods.ctrl and keycode == "H":
+            print("hello")
+        elif keymods.ctrl and keycode == "P":
+            print_tree()
+
+        elif keycode in latin:
+            key = keycode.upper() if keymods.shift else keycode.lower()
+            self.type_key(key, keymods, repeat)
+        elif keycode in numerals or keycode in punct or keycode in keycmds:
+            self.type_key(keycode, keymods, repeat)
+        #else:
+        #    print(keycode)
+
+    def type_key(self, key, _keymods, _repeat):
+        now = time.time()
+        if now - self.last_keypress_time < 0.2:
+            return
+        self.last_keypress_time = now
+        if key == "Backspace":
+            self.user_input = self.user_input[:-1]
+        else:
+            self.user_input += key
+        draw_txt(self.user_input)
+
+def draw_txt(user_input):
+    obj_id = add_object("/window/chatbox_layer", "user_input2")
+    # create a new one and link it
+    text_id = host.create_text("/font/inter-regular", "txt2", user_input, 30)
+    link_node(text_id, obj_id)
 
-def draw_box():
-    from pydrk import SceneNodeType, PropertyType
+    layer_w = get_property("/window/chatbox_layer", "rect_w")
+    layer_h = get_property("/window/chatbox_layer", "rect_h")
 
+    x = 20
+    y = layer_h - 20 - 30
+
+    set_property_f32("/window/chatbox_layer/user_input2", "x", x)
+    set_property_f32("/window/chatbox_layer/user_input2", "y", y)
+    set_property_f32("/window/chatbox_layer/user_input2/txt2", "r", 1)
+    set_property_f32("/window/chatbox_layer/user_input2/txt2", "g", 1)
+    set_property_f32("/window/chatbox_layer/user_input2/txt2", "b", 1)
+    set_property_f32("/window/chatbox_layer/user_input2/txt2", "a", 1)
+
+    # Switch visibility
+    set_property_bool("/window/chatbox_layer/user_input",  "is_visible", False)
+    set_property_bool("/window/chatbox_layer/user_input2", "is_visible", True)
+
+    # Remove the old object
+    old_id = lookup_node("/window/chatbox_layer/user_input")
+    unlink_from_parents(old_id)
+    remove_node_recursive(old_id)
+
+    rename_node("/window/chatbox_layer/user_input2/txt2", "txt")
+    rename_node("/window/chatbox_layer/user_input2",      "user_input")
+
+    # Move the cursor
+    text_px_w = get_property("/window/chatbox_layer/user_input/txt", "width")
+    x = text_px_w + 25
+    if user_input and user_input[-1] == " ":
+        x += 10
+    set_property_f32("/window/cursor_layer/cursor", "x", x)
+    set_property_f32("/window/cursor_layer/cursor", "y", y)
+
+def draw_cursor():
+    mesh_id = api.add_node("cursor_box", SceneNodeType.RENDER_MESH)
+    api.add_property(mesh_id, "verts", PropertyType.BUFFER)
+    api.add_property(mesh_id, "faces", PropertyType.BUFFER)
+    link_node(mesh_id, "/window/cursor_layer/cursor")
+
+    x, y = 0, 0
+    w, h = 20, 40
+    vert1 = vertex(x,     y,     1, 1, 1, 1, 0, 0)
+    vert2 = vertex(x + w, y,     1, 1, 1, 1, 1, 0)
+    vert3 = vertex(x,     y + h, 1, 1, 1, 1, 0, 1)
+    vert4 = vertex(x + w, y + h, 1, 1, 1, 1, 1, 1)
+    api.set_property_buffer(mesh_id, "verts", vert1 + vert2 + vert3 + vert4)
+    api.set_property_buffer(mesh_id, "faces", face(0, 2, 1) + face(1, 2, 3))
+
+def draw_box():
     mesh_id = api.add_node("box", SceneNodeType.RENDER_MESH)
     api.add_property(mesh_id, "verts", PropertyType.BUFFER)
     api.add_property(mesh_id, "faces", PropertyType.BUFFER)
@@ -52,16 +145,18 @@ def draw_box():
     resize_box()
 
 def resize_box():
-    from pydrk import vertex, face
-
     mesh_id = api.lookup_node_id("/window/chatbox_layer/outline/box")
 
     layer_w = get_property("/window/chatbox_layer", "rect_w")
     layer_h = get_property("/window/chatbox_layer", "rect_h")
 
+    box_h = 60
+    # Inner padding, so box inside will be (box_h - 2*padding) px high
+    padding = 5
+
     # Lets add a poly - must be counterclockwise
-    x, y = layer_w * 0.25, layer_h * 0.25
-    w, h = layer_w * 0.50, layer_h * 0.50
+    x, y = 0, layer_h - box_h
+    w, h = layer_w, box_h
     vert1 = vertex(x,     y,     1, 1, 1, 1, 0, 0)
     vert2 = vertex(x + w, y,     1, 1, 1, 1, 1, 0)
     vert3 = vertex(x,     y + h, 1, 1, 1, 1, 0, 1)
@@ -72,9 +167,9 @@ def resize_box():
     # Second mesh
     mesh_id = api.lookup_node_id("/window/chatbox_layer/outline/inner_box")
 
-    x, y = x + 5, y + 5
-    w -= 10
-    h -= 10
+    x, y = x + padding, y + padding
+    w -= 2*padding
+    h -= 2*padding
     vert1 = vertex(x,     y,     0, 0, 0, 1, 0, 0)
     vert2 = vertex(x + w, y,     0, 0, 0, 1, 1, 0)
     vert3 = vertex(x,     y + h, 0, 0, 0, 1, 0, 1)
@@ -87,6 +182,7 @@ def main():
 
     app = App()
     draw_box()
+    draw_cursor()
     print_tree()
     app.run()
 

+ 23 - 8
bin/darkwallet/gui/api.py

@@ -13,6 +13,10 @@ def make_sub_socket():
     socket.connect("tcp://localhost:9485")
     return socket
 
+def rename_node(node, name):
+    node_id = lookup_node(node)
+    api.rename_node(node_id, name)
+
 def remove_all_slots(node_path, sig):
     node_id = api.lookup_node_id(node_path)
     for slot_id, slot in api.get_slots(node_id, sig):
@@ -29,17 +33,20 @@ def get_property(node_path, prop):
     return api.get_property(node_id, prop)
 
 def set_property(node_id, prop, val):
-    node_id = _lookup_node(node_id)
+    node_id = lookup_node(node_id)
     match val:
         case float():
             api.set_property_f32(node_id, prop, val)
         case int():
             api.set_property_u32(node_id, prop, val)
+def set_property_bool(node_id, prop, val):
+    node_id = lookup_node(node_id)
+    api.set_property_bool(node_id, prop, val)
 def set_property_f32(node_id, prop, val):
-    node_id = _lookup_node(node_id)
+    node_id = lookup_node(node_id)
     api.set_property_f32(node_id, prop, float(val))
 def set_property_u32(node_id, prop, val):
-    node_id = _lookup_node(node_id)
+    node_id = lookup_node(node_id)
     api.set_property_u32(node_id, prop, int(val))
 
 def add_property_bool(node_id, prop, val=None):
@@ -55,26 +62,34 @@ def add_property_u32(node_id, prop, val=None):
     if val is not None:
         api.set_property_u32(node_id, prop, val)
 
-def _lookup_node(node_id):
+def lookup_node(node_id):
     if isinstance(node_id, str):
         node_id = api.lookup_node_id(node_id)
     return node_id
 
 def link_node(child_id, parent_id):
-    child_id = _lookup_node(child_id)
-    parent_id = _lookup_node(parent_id)
+    child_id = lookup_node(child_id)
+    parent_id = lookup_node(parent_id)
     api.link_node(child_id, parent_id)
 def unlink_node(child_id, parent_id):
-    child_id = _lookup_node(child_id)
-    parent_id = _lookup_node(parent_id)
+    child_id = lookup_node(child_id)
+    parent_id = lookup_node(parent_id)
     api.unlink_node(child_id, parent_id)
 
+def unlink_from_parents(node_id):
+    node_id = lookup_node(node_id)
+    for (_, parent_id, _) in api.get_parents(node_id):
+        api.unlink_node(node_id, parent_id)
+
 def remove_node_recursive(node_id):
+    node_id = lookup_node(node_id)
+
     for (_, child_id, _) in api.get_children(node_id):
         # Unlink the child
         api.unlink_node(child_id, node_id)
         # Remove the node
         remove_node_recursive(child_id)
+
     # Garbage collection
     if not api.get_parents(node_id):
         api.remove_node(node_id)

+ 12 - 6
bin/darkwallet/gui/gfx.py

@@ -25,6 +25,17 @@ def add_layer(layer_name):
     link_node(layer_id, "/window")
     return layer_id
 
+def add_object(layer_id, obj_name):
+    layer_id = lookup_node(layer_id)
+    obj_id = api.add_node(obj_name, SceneNodeType.RENDER_OBJECT)
+    add_property_f32(obj_id, "x")
+    add_property_f32(obj_id, "y")
+    add_property_f32(obj_id, "scale_x", 1.0)
+    add_property_f32(obj_id, "scale_y", 1.0)
+    add_property_bool(obj_id, "is_visible", True)
+    link_node(obj_id, layer_id)
+    return obj_id
+
 class Layer:
 
     def __init__(self, name):
@@ -37,10 +48,5 @@ class Layer:
         set_property_u32(self.id, "rect_h", h)
 
     def add_obj(self, name):
-        obj_id = api.add_node(name, SceneNodeType.RENDER_OBJECT)
-        add_property_f32(obj_id, "x")
-        add_property_f32(obj_id, "y")
-        add_property_f32(obj_id, "scale_x", 1.0)
-        add_property_f32(obj_id, "scale_y", 1.0)
-        link_node(obj_id, self.id)
+        return add_object(self.id, name)
 

+ 3 - 2
bin/darkwallet/gui/print_tree.py

@@ -8,9 +8,10 @@ def join(parent_path, child_name):
 
 def print_tree():
     root_id = api.lookup_node_id("/")
-    print_node_info(root_id)
+    print("/")
+    print_node_info(root_id, indent=1)
 
-def print_node_info(parent_id, indent=0):
+def print_node_info(parent_id, indent):
     ws = " "*4*indent
     for (child_name, child_id, child_type) in api.get_children(parent_id):
         match child_type: