mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
wallet: make a more powerful property system
This commit is contained in:
@@ -28,6 +28,11 @@ class App(EventLoop):
|
||||
|
||||
self.cursor_layer = Layer("cursor_layer")
|
||||
self.cursor_layer.add_obj("cursor")
|
||||
self.cursor_layer.resize(w, h)
|
||||
|
||||
self.rounded_box_layer = Layer("rounded_box_layer")
|
||||
self.rounded_box_layer.add_obj("box")
|
||||
self.rounded_box_layer.resize(w, h)
|
||||
|
||||
self.user_input = ""
|
||||
self.last_keypress_time = 0
|
||||
@@ -35,7 +40,9 @@ class App(EventLoop):
|
||||
def resize_event(self, w, h):
|
||||
self.chatbox_layer.resize(w, h)
|
||||
self.cursor_layer.resize(w, h)
|
||||
self.rounded_box_layer.resize(w, h)
|
||||
resize_box()
|
||||
resize_rounded_box()
|
||||
draw_txt(self.user_input)
|
||||
|
||||
def mouse_click(self, x, y):
|
||||
@@ -108,8 +115,19 @@ def draw_txt(user_input):
|
||||
rename_node("/window/chatbox_layer/user_input2/txt2", "txt")
|
||||
rename_node("/window/chatbox_layer/user_input2", "user_input")
|
||||
|
||||
reposition_cursor()
|
||||
|
||||
def reposition_cursor():
|
||||
layer_h = get_property("/window/chatbox_layer", "rect_h")
|
||||
y = layer_h - 20 - 30
|
||||
|
||||
# Move the cursor
|
||||
text_px_w = get_property("/window/chatbox_layer/user_input/txt", "width")
|
||||
text_id = api.lookup_node_id("/window/chatbox_layer/user_input/txt")
|
||||
text_px_w = 0
|
||||
user_input = ""
|
||||
if text_id is not None:
|
||||
text_px_w = get_property(text_id, "width")
|
||||
user_input = get_property(text_id, "text")
|
||||
x = text_px_w + 25
|
||||
if user_input and user_input[-1] == " ":
|
||||
x += 10
|
||||
@@ -152,7 +170,7 @@ def resize_box():
|
||||
|
||||
box_h = 60
|
||||
# Inner padding, so box inside will be (box_h - 2*padding) px high
|
||||
padding = 5
|
||||
padding = 10
|
||||
|
||||
# Lets add a poly - must be counterclockwise
|
||||
x, y = 0, layer_h - box_h
|
||||
@@ -177,12 +195,102 @@ def resize_box():
|
||||
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_rounded_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)
|
||||
link_node(mesh_id, "/window/rounded_box_layer/box")
|
||||
|
||||
mesh_id = api.add_node("inner_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/rounded_box_layer/box")
|
||||
|
||||
resize_rounded_box()
|
||||
|
||||
def resize_rounded_box():
|
||||
mesh_id = api.lookup_node_id("/window/rounded_box_layer/box/box")
|
||||
|
||||
layer_w = get_property("/window/rounded_box_layer", "rect_w")
|
||||
layer_h = get_property("/window/rounded_box_layer", "rect_h")
|
||||
|
||||
# Inner padding, so box inside will be (box_h - 2*padding) px high
|
||||
padding = 5
|
||||
|
||||
bevel = 20
|
||||
|
||||
# Lets add a poly - must be counterclockwise
|
||||
x, y = layer_w/4, layer_h/4
|
||||
w, h = layer_w/2, layer_h/2
|
||||
y0 = y + bevel
|
||||
h0 = h - 2*bevel
|
||||
verts = (
|
||||
vertex(x, y0, 1, 1, 1, 1, 0, 0) +
|
||||
vertex(x + w, y0, 1, 1, 1, 1, 1, 0) +
|
||||
vertex(x, y0 + h0, 1, 1, 1, 1, 0, 1) +
|
||||
vertex(x + w, y0 + h0, 1, 1, 1, 1, 1, 1)
|
||||
)
|
||||
faces = face(0, 2, 1) + face(1, 2, 3)
|
||||
x0 = x + bevel
|
||||
w0 = w - 2*bevel
|
||||
h0 = bevel
|
||||
verts += (
|
||||
vertex(x0, y, 1, 1, 1, 1, 0, 0) +
|
||||
vertex(x0 + w0, y, 1, 1, 1, 1, 1, 0) +
|
||||
vertex(x0, y + h0, 1, 1, 1, 1, 0, 1) +
|
||||
vertex(x0 + w0, y + h0, 1, 1, 1, 1, 1, 1)
|
||||
)
|
||||
o = 4
|
||||
faces += face(o + 0, o + 2, o + 1) + face(o + 1, o + 2, o + 3)
|
||||
y0 = y + h - bevel
|
||||
x0 = x + bevel
|
||||
w0 = w - 2*bevel
|
||||
h0 = bevel
|
||||
verts += (
|
||||
vertex(x0, y0, 1, 1, 1, 1, 0, 0) +
|
||||
vertex(x0 + w0, y0, 1, 1, 1, 1, 1, 0) +
|
||||
vertex(x0, y0 + h0, 1, 1, 1, 1, 0, 1) +
|
||||
vertex(x0 + w0, y0 + h0, 1, 1, 1, 1, 1, 1)
|
||||
)
|
||||
o = 8
|
||||
faces += face(o + 0, o + 2, o + 1) + face(o + 1, o + 2, o + 3)
|
||||
api.set_property_buffer(mesh_id, "verts", verts)
|
||||
api.set_property_buffer(mesh_id, "faces", faces)
|
||||
|
||||
# Second mesh
|
||||
mesh_id = api.lookup_node_id("/window/rounded_box_layer/box/inner_box")
|
||||
|
||||
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)
|
||||
vert4 = vertex(x + w, y + h, 0.3, 0.3, 0.3, 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 main():
|
||||
garbage_collect()
|
||||
|
||||
app = App()
|
||||
draw_box()
|
||||
draw_cursor()
|
||||
node_id = api.add_node("foo", SceneNodeType.WINDOW)
|
||||
prop = Property(
|
||||
"myprop", PropertyType.FLOAT32, PropertySubType.NULL,
|
||||
None,
|
||||
"myprop", "",
|
||||
False, 2, None, None, []
|
||||
)
|
||||
api.add_property(1, prop)
|
||||
api.link_node(node_id, 0)
|
||||
api.set_property_f32(1, "myprop", 0, 4.0)
|
||||
api.set_property_f32(1, "myprop", 1, 110.0)
|
||||
print(api.get_property_value(1, "myprop"))
|
||||
print_tree()
|
||||
app.run()
|
||||
#garbage_collect()
|
||||
|
||||
#app = App()
|
||||
#draw_box()
|
||||
#draw_rounded_box()
|
||||
#draw_cursor()
|
||||
#reposition_cursor()
|
||||
##print_tree()
|
||||
#app.run()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from collections import namedtuple
|
||||
from pydrk import Api, HostApi, PropertyType
|
||||
from pydrk import Api, HostApi, PropertyType, PropertySubType, Property
|
||||
import zmq
|
||||
|
||||
api = Api()
|
||||
@@ -28,8 +28,8 @@ def register_slot(node_path, sig, tag):
|
||||
node_id = api.lookup_node_id(node_path)
|
||||
api.register_slot(node_id, sig, "", tag)
|
||||
|
||||
def get_property(node_path, prop):
|
||||
node_id = api.lookup_node_id(node_path)
|
||||
def get_property(node_id, prop):
|
||||
node_id = lookup_node(node_id)
|
||||
return api.get_property(node_id, prop)
|
||||
|
||||
def set_property(node_id, prop, val):
|
||||
|
||||
@@ -49,19 +49,19 @@ def print_node_info(parent_id, indent):
|
||||
|
||||
print_node_info(child_id, indent+1)
|
||||
|
||||
for prop_name, prop_type in api.get_properties(parent_id):
|
||||
if prop_type == PropertyType.STR:
|
||||
prop_val = api.get_property(parent_id, prop_name)
|
||||
prop_val = f" = \"{prop_val}\""
|
||||
elif prop_type != PropertyType.BUFFER:
|
||||
prop_val = api.get_property(parent_id, prop_name)
|
||||
prop_val = f" = {prop_val}"
|
||||
else:
|
||||
prop_val = ""
|
||||
#for prop_name, prop_type in api.get_properties(parent_id):
|
||||
# if prop_type == PropertyType.STR:
|
||||
# prop_val = api.get_property(parent_id, prop_name)
|
||||
# prop_val = f" = \"{prop_val}\""
|
||||
# elif prop_type != PropertyType.BUFFER:
|
||||
# prop_val = api.get_property(parent_id, prop_name)
|
||||
# prop_val = f" = {prop_val}"
|
||||
# else:
|
||||
# prop_val = ""
|
||||
|
||||
prop_type = PropertyType.to_str(prop_type)
|
||||
# prop_type = PropertyType.to_str(prop_type)
|
||||
|
||||
print(f"{ws}{prop_name}: {prop_type}{prop_val}")
|
||||
# print(f"{ws}{prop_name}: {prop_type}{prop_val}")
|
||||
|
||||
for sig in api.get_signals(parent_id):
|
||||
print(f"{ws}~{sig}")
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from .api import Api, ErrorCode, SceneNodeType, PropertyType, vertex, face
|
||||
from .api import (Api, ErrorCode, SceneNodeType,
|
||||
PropertyType, PropertySubType, Property,
|
||||
vertex, face)
|
||||
from .host import HostApi
|
||||
from . import exc, serial
|
||||
|
||||
|
||||
@@ -1,7 +1,22 @@
|
||||
import zmq
|
||||
from collections import namedtuple
|
||||
from . import serial
|
||||
from . import exc
|
||||
|
||||
Property = namedtuple("Property", [
|
||||
"name",
|
||||
"type",
|
||||
"subtype",
|
||||
"defaults",
|
||||
"ui_name",
|
||||
"desc",
|
||||
"is_null_allowed",
|
||||
"array_len",
|
||||
"min_val",
|
||||
"max_val",
|
||||
"enum_items"
|
||||
])
|
||||
|
||||
class Command:
|
||||
HELLO = 0
|
||||
ADD_NODE = 1
|
||||
@@ -16,8 +31,8 @@ class Command:
|
||||
GET_CHILDREN = 4
|
||||
GET_PARENTS = 5
|
||||
GET_PROPERTIES = 3
|
||||
GET_PROPERTY = 6
|
||||
SET_PROPERTY = 7
|
||||
GET_PROPERTY_VALUE = 6
|
||||
SET_PROPERTY_VALUE = 7
|
||||
GET_SIGNALS = 14
|
||||
REGISTER_SLOT = 15
|
||||
UNREGISTER_SLOT = 16
|
||||
@@ -45,20 +60,19 @@ class SceneNodeType:
|
||||
|
||||
class PropertyType:
|
||||
NULL = 0
|
||||
BUFFER = 1
|
||||
BOOL = 2
|
||||
UINT32 = 3
|
||||
FLOAT32 = 4
|
||||
STR = 5
|
||||
SCENE_NODE_ID = 6
|
||||
BOOL = 1
|
||||
UINT32 = 2
|
||||
FLOAT32 = 3
|
||||
STR = 4
|
||||
ENUM = 5
|
||||
BUFFER = 6
|
||||
SCENE_NODE_ID = 7
|
||||
|
||||
@staticmethod
|
||||
def to_str(prop_type):
|
||||
match prop_type:
|
||||
case PropertyType.NULL:
|
||||
return "null"
|
||||
case PropertyType.BUFFER:
|
||||
return "buffer"
|
||||
case PropertyType.BOOL:
|
||||
return "bool"
|
||||
case PropertyType.UINT32:
|
||||
@@ -67,29 +81,55 @@ class PropertyType:
|
||||
return "float32"
|
||||
case PropertyType.STR:
|
||||
return "str"
|
||||
case PropertyType.ENUM:
|
||||
return "enum"
|
||||
case PropertyType.BUFFER:
|
||||
return "buffer"
|
||||
case PropertyType.SCENE_NODE_ID:
|
||||
return "scene_node_id"
|
||||
|
||||
class PropertySubType:
|
||||
NULL = 0
|
||||
COLOR = 1
|
||||
PIXEL = 2
|
||||
|
||||
@staticmethod
|
||||
def to_str(prop_type):
|
||||
match prop_type:
|
||||
case PropertySubType.NULL:
|
||||
return "null"
|
||||
case PropertySubType.Color:
|
||||
return "color"
|
||||
case PropertySubType.PIXEL:
|
||||
return "pixel"
|
||||
|
||||
class ErrorCode:
|
||||
INVALID_SCENE_PATH = 2
|
||||
NODE_NOT_FOUND = 3
|
||||
CHILD_NODE_NOT_FOUND = 4
|
||||
PARENT_NODE_NOT_FOUND = 5
|
||||
PROPERTY_ALREADY_EXISTS = 6
|
||||
PROPERTY_NOT_FOUND = 7
|
||||
PROPERTY_WRONG_TYPE = 8
|
||||
SIGNAL_ALREADY_EXISTS = 9
|
||||
SIGNAL_NOT_FOUND = 10
|
||||
SLOT_NOT_FOUND = 11
|
||||
METHOD_NOT_FOUND = 12
|
||||
NODES_ARE_LINKED = 13
|
||||
NODES_NOT_LINKED = 14
|
||||
NODE_HAS_PARENTS = 15
|
||||
NODE_HAS_CHILDREN = 16
|
||||
NODE_PARENT_NAME_CONFLICT = 17
|
||||
NODE_CHILD_NAME_CONFLICT = 18
|
||||
NODE_SIBLING_NAME_CONFLICT = 19
|
||||
FILE_NOT_FOUND = 20
|
||||
INVALID_SCENE_PATH = 1
|
||||
NODE_NOT_FOUND = 2
|
||||
CHILD_NODE_NOT_FOUND = 3
|
||||
PARENT_NODE_NOT_FOUND = 4
|
||||
PROPERTY_ALREADY_EXISTS = 5
|
||||
PROPERTY_NOT_FOUND = 6
|
||||
PROPERTY_WRONG_TYPE = 7
|
||||
PROPERTY_WRONG_LEN = 8
|
||||
PROPERTY_WRONG_INDEX = 9
|
||||
PROPERTY_OUT_OF_RANGE = 10
|
||||
PROPERTY_NULL_NOT_ALLOWED = 11
|
||||
PROPERTY_IS_BOUNDED = 12
|
||||
PROPERTY_WRONG_ENUM_ITEM = 13
|
||||
SIGNAL_ALREADY_EXISTS = 14
|
||||
SIGNAL_NOT_FOUND = 15
|
||||
SLOT_NOT_FOUND = 16
|
||||
METHOD_ALREADY_EXISTS = 17
|
||||
METHOD_NOT_FOUND = 18
|
||||
NODES_ARE_LINKED = 19
|
||||
NODES_NOT_LINKED = 20
|
||||
NODE_HAS_PARENTS = 21
|
||||
NODE_HAS_CHILDREN = 22
|
||||
NODE_PARENT_NAME_CONFLICT = 23
|
||||
NODE_CHILD_NAME_CONFLICT = 24
|
||||
NODE_SIBLING_NAME_CONFLICT = 25
|
||||
FILE_NOT_FOUND = 26
|
||||
|
||||
@staticmethod
|
||||
def to_str(errc):
|
||||
@@ -108,28 +148,42 @@ class ErrorCode:
|
||||
return "property_not_found"
|
||||
case ErrorCode.PROPERTY_WRONG_TYPE:
|
||||
return "property_wrong_type"
|
||||
case ErrorCode.PROPERTY_WRONG_LEN:
|
||||
return "property_wrong_len"
|
||||
case ErrorCode.PROPERTY_WRONG_INDEX:
|
||||
return "property_wrong_index"
|
||||
case ErrorCode.PROPERTY_OUT_OF_RANGE:
|
||||
return "property_out_of_range"
|
||||
case ErrorCode.PROPERTY_NULL_NOT_ALLOWED:
|
||||
return "property_null_not_allowed"
|
||||
case ErrorCode.PROPERTY_IS_BOUNDED:
|
||||
return "property_is_bounded"
|
||||
case ErrorCode.PROPERTY_WRONG_ENUM_ITEM:
|
||||
return "property_wrong_enum_item"
|
||||
case ErrorCode.SIGNAL_ALREADY_EXISTS:
|
||||
return "signal_already_exists"
|
||||
case ErrorCode.SIGNAL_NOT_FOUND:
|
||||
return "signal_not_found "
|
||||
return "signal_not_found"
|
||||
case ErrorCode.SLOT_NOT_FOUND:
|
||||
return "slot_not_found "
|
||||
return "slot_not_found"
|
||||
case ErrorCode.METHOD_ALREADY_EXISTS:
|
||||
return "method_already_exists"
|
||||
case ErrorCode.METHOD_NOT_FOUND:
|
||||
return "method_not_found "
|
||||
return "method_not_found"
|
||||
case ErrorCode.NODES_ARE_LINKED:
|
||||
return "nodes_are_linked "
|
||||
return "nodes_are_linked"
|
||||
case ErrorCode.NODES_NOT_LINKED:
|
||||
return "nodes_not_linked "
|
||||
return "nodes_not_linked"
|
||||
case ErrorCode.NODE_HAS_PARENTS:
|
||||
return "node_has_parents "
|
||||
return "node_has_parents"
|
||||
case ErrorCode.NODE_HAS_CHILDREN:
|
||||
return "node_has_children "
|
||||
return "node_has_children"
|
||||
case ErrorCode.NODE_PARENT_NAME_CONFLICT:
|
||||
return "node_parent_name_conflict "
|
||||
return "node_parent_name_conflict"
|
||||
case ErrorCode.NODE_CHILD_NAME_CONFLICT:
|
||||
return "node_child_name_conflict "
|
||||
return "node_child_name_conflict"
|
||||
case ErrorCode.NODE_SIBLING_NAME_CONFLICT:
|
||||
return "node_sibling_name_conflict "
|
||||
return "node_sibling_name_conflict"
|
||||
case ErrorCode.FILE_NOT_FOUND:
|
||||
return "file_not_found"
|
||||
|
||||
@@ -169,44 +223,58 @@ class Api:
|
||||
errc = int.from_bytes(errc, "little")
|
||||
cursor = serial.Cursor(reply)
|
||||
match errc:
|
||||
case 1:
|
||||
raise exc.InvalidScenePath
|
||||
case 2:
|
||||
raise exc.RequestInvalidScenePath
|
||||
raise exc.NodeNotFound
|
||||
case 3:
|
||||
raise exc.RequestNodeNotFound
|
||||
raise exc.ChildNodeNotFound
|
||||
case 4:
|
||||
raise exc.RequestChildNodeNotFound
|
||||
raise exc.ParentNodeNotFound
|
||||
case 5:
|
||||
raise exc.RequestParentNodeNotFound
|
||||
raise exc.PropertyAlreadyExists
|
||||
case 6:
|
||||
raise exc.RequestPropertyAlreadyExists
|
||||
raise exc.PropertyNotFound
|
||||
case 7:
|
||||
raise exc.RequestPropertyNotFound
|
||||
raise exc.PropertyWrongType
|
||||
case 8:
|
||||
raise exc.RequestPropertyWrongType
|
||||
raise exc.PropertyWrongLen
|
||||
case 9:
|
||||
raise exc.RequestSignalAlreadyExists
|
||||
raise exc.PropertyWrongIndex
|
||||
case 10:
|
||||
raise exc.RequestSignalNotFound
|
||||
raise exc.PropertyOutOfRange
|
||||
case 11:
|
||||
raise exc.RequestSlotNotFound
|
||||
raise exc.PropertyNullNotAllowed
|
||||
case 12:
|
||||
raise exc.RequestMethodNotFound
|
||||
raise exc.PropertyIsBounded
|
||||
case 13:
|
||||
raise exc.RequestNodesAreLinked
|
||||
raise exc.PropertyWrongEnumItem
|
||||
case 14:
|
||||
raise exc.RequestNodesNotLinked
|
||||
raise exc.SignalAlreadyExists
|
||||
case 15:
|
||||
raise exc.RequestNodeHasParents
|
||||
raise exc.SignalNotFound
|
||||
case 16:
|
||||
raise exc.RequestNodeHasChildren
|
||||
raise exc.SlotNotFound
|
||||
case 17:
|
||||
raise exc.RequestNodeParentNameConflict
|
||||
raise exc.MethodAlreadyExists
|
||||
case 18:
|
||||
raise exc.RequestNodeChildNameConflict
|
||||
raise exc.MethodNotFound
|
||||
case 19:
|
||||
raise exc.RequestNodeSiblingNameConflict
|
||||
raise exc.NodesAreLinked
|
||||
case 20:
|
||||
raise exc.RequestFileNotFound
|
||||
raise exc.NodesNotLinked
|
||||
case 21:
|
||||
raise exc.NodeHasParents
|
||||
case 22:
|
||||
raise exc.NodeHasChildren
|
||||
case 23:
|
||||
raise exc.NodeParentNameConflict
|
||||
case 24:
|
||||
raise exc.NodeChildNameConflict
|
||||
case 25:
|
||||
raise exc.NodeSiblingNameConflict
|
||||
case 26:
|
||||
raise exc.FileNotFound
|
||||
return cursor
|
||||
|
||||
def hello(self):
|
||||
@@ -259,27 +327,43 @@ class Api:
|
||||
props.append((prop_name, prop_type))
|
||||
return props
|
||||
|
||||
def get_property(self, node_id, prop_name):
|
||||
def get_property_value(self, node_id, prop_name):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
cur = self._make_request(Command.GET_PROPERTY, req)
|
||||
cur = self._make_request(Command.GET_PROPERTY_VALUE, req)
|
||||
prop_type = serial.read_u8(cur)
|
||||
prop_len = serial.decode_varint(cur)
|
||||
vals = []
|
||||
|
||||
def read_array(read_fn):
|
||||
for _ in range(prop_len):
|
||||
is_some = serial.read_u8(cur)
|
||||
if is_some:
|
||||
val = read_fn()
|
||||
vals.append(val)
|
||||
|
||||
match prop_type:
|
||||
case 0:
|
||||
case PropertyType.NULL:
|
||||
return None
|
||||
case 1:
|
||||
return []
|
||||
case 3:
|
||||
val = serial.read_u8(cur)
|
||||
return bool(val)
|
||||
case 2:
|
||||
return serial.read_u32(cur)
|
||||
case 4:
|
||||
return serial.read_f32(cur)
|
||||
case 5:
|
||||
return serial.decode_str(cur)
|
||||
raise Exception("unknown property type returned")
|
||||
case PropertyType.BOOL:
|
||||
read_array(lambda: bool(serial.read_u8(cur)))
|
||||
case PropertyType.UINT32:
|
||||
read_array(lambda: serial.read_u32(cur))
|
||||
case PropertyType.FLOAT32:
|
||||
read_array(lambda: serial.read_f32(cur))
|
||||
case PropertyType.STR:
|
||||
read_array(lambda: serial.decode_str(cur))
|
||||
case PropertyType.ENUM:
|
||||
read_array(lambda: serial.decode_str(cur))
|
||||
case PropertyType.BUFFER:
|
||||
pass
|
||||
case PropertyType.SCENE_NODE_ID:
|
||||
read_array(lambda: serial.read_u32(cur))
|
||||
case _:
|
||||
raise Exception("unknown property type returned")
|
||||
|
||||
return vals
|
||||
|
||||
def add_node(self, node_name, node_type):
|
||||
req = bytearray()
|
||||
@@ -318,11 +402,57 @@ class Api:
|
||||
return None
|
||||
return serial.read_u32(cur)
|
||||
|
||||
def add_property(self, node_id, prop_name, prop_type):
|
||||
def add_property(self, node_id, prop):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u8(req, int(prop_type))
|
||||
serial.encode_str(req, prop.name)
|
||||
serial.write_u8(req, int(prop.type))
|
||||
serial.write_u8(req, int(prop.subtype))
|
||||
serial.write_u32(req, int(prop.array_len))
|
||||
if prop.defaults is None:
|
||||
serial.write_u8(req, 0)
|
||||
else:
|
||||
serial.write_u8(req, 1)
|
||||
defaults_len = len(prop.defaults)
|
||||
serial.encode_varint(req, defaults_len)
|
||||
for default in prop.defaults:
|
||||
match prop.type:
|
||||
case PropertyType.UINT32:
|
||||
serial.write_u32(req, default)
|
||||
case PropertyType.FLOAT32:
|
||||
serial.write_f32(req, default)
|
||||
case _:
|
||||
raise exc.PropertyWrongType
|
||||
serial.encode_str(req, prop.ui_name)
|
||||
serial.encode_str(req, prop.desc)
|
||||
serial.write_u8(req, int(prop.is_null_allowed))
|
||||
if prop.min_val is None:
|
||||
serial.write_u8(req, 0)
|
||||
else:
|
||||
serial.write_u8(req, 1)
|
||||
match prop.type:
|
||||
case PropertyType.UINT32:
|
||||
serial.write_u32(req, prop.min_val)
|
||||
case PropertyType.FLOAT32:
|
||||
serial.write_f32(req, prop.min_val)
|
||||
case _:
|
||||
raise exc.PropertyWrongType
|
||||
if prop.max_val is None:
|
||||
serial.write_u8(req, 0)
|
||||
else:
|
||||
serial.write_u8(req, 1)
|
||||
match prop.type:
|
||||
case PropertyType.UINT32:
|
||||
serial.write_u32(req, prop.max_val)
|
||||
case PropertyType.FLOAT32:
|
||||
serial.write_f32(req, prop.max_val)
|
||||
case _:
|
||||
raise exc.PropertyWrongType
|
||||
serial.encode_varint(req, len(prop.enum_items))
|
||||
for enum_item in prop.enum_items:
|
||||
if prop.type != PropertyType.ENUM:
|
||||
raise exc.PropertyWrongType
|
||||
serial.encode_str(req, enum_item)
|
||||
self._make_request(Command.ADD_PROPERTY, req)
|
||||
|
||||
def link_node(self, child_id, parent_id):
|
||||
@@ -342,35 +472,39 @@ class Api:
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u8(req, int(val))
|
||||
self._make_request(Command.SET_PROPERTY, req)
|
||||
self._make_request(Command.SET_PROPERTY_VALUE, req)
|
||||
|
||||
def set_property_u32(self, node_id, prop_name, val):
|
||||
def set_property_u32(self, node_id, prop_name, i, val):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u32(req, i)
|
||||
serial.write_u32(req, val)
|
||||
self._make_request(Command.SET_PROPERTY, req)
|
||||
self._make_request(Command.SET_PROPERTY_VALUE, req)
|
||||
|
||||
def set_property_f32(self, node_id, prop_name, val):
|
||||
def set_property_f32(self, node_id, prop_name, i, val):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u32(req, i)
|
||||
serial.write_f32(req, val)
|
||||
self._make_request(Command.SET_PROPERTY, req)
|
||||
self._make_request(Command.SET_PROPERTY_VALUE, req)
|
||||
|
||||
def set_property_buffer(self, node_id, prop_name, buf):
|
||||
def set_property_buffer(self, node_id, prop_name, i, buf):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u32(req, i)
|
||||
serial.encode_buf(req, buf)
|
||||
self._make_request(Command.SET_PROPERTY, req)
|
||||
self._make_request(Command.SET_PROPERTY_VALUE, req)
|
||||
|
||||
def set_property_str(self, node_id, prop_name, val):
|
||||
def set_property_str(self, node_id, prop_name, i, val):
|
||||
req = bytearray()
|
||||
serial.write_u32(req, node_id)
|
||||
serial.encode_str(req, prop_name)
|
||||
serial.write_u32(req, i)
|
||||
serial.encode_str(req, val)
|
||||
self._make_request(Command.SET_PROPERTY, req)
|
||||
self._make_request(Command.SET_PROPERTY_VALUE, req)
|
||||
|
||||
def get_signals(self, node_id):
|
||||
req = bytearray()
|
||||
|
||||
@@ -1,38 +1,52 @@
|
||||
class RequestInvalidScenePath(Exception):
|
||||
class InvalidScenePath(Exception):
|
||||
pass
|
||||
class RequestNodeNotFound(Exception):
|
||||
class NodeNotFound(Exception):
|
||||
pass
|
||||
class RequestChildNodeNotFound(Exception):
|
||||
class ChildNodeNotFound(Exception):
|
||||
pass
|
||||
class RequestParentNodeNotFound(Exception):
|
||||
class ParentNodeNotFound(Exception):
|
||||
pass
|
||||
class RequestPropertyAlreadyExists(Exception):
|
||||
class PropertyAlreadyExists(Exception):
|
||||
pass
|
||||
class RequestPropertyNotFound(Exception):
|
||||
class PropertyNotFound(Exception):
|
||||
pass
|
||||
class RequestPropertyWrongType(Exception):
|
||||
class PropertyWrongType(Exception):
|
||||
pass
|
||||
class RequestSignalAlreadyExists(Exception):
|
||||
class PropertyWrongLen(Exception):
|
||||
pass
|
||||
class RequestSignalNotFound(Exception):
|
||||
class PropertyWrongIndex(Exception):
|
||||
pass
|
||||
class RequestSlotNotFound(Exception):
|
||||
class PropertyOutOfRange(Exception):
|
||||
pass
|
||||
class RequestMethodNotFound(Exception):
|
||||
class PropertyNullNotAllowed(Exception):
|
||||
pass
|
||||
class RequestNodesAreLinked(Exception):
|
||||
class PropertyIsBounded(Exception):
|
||||
pass
|
||||
class RequestNodesNotLinked(Exception):
|
||||
class PropertyWrongEnumItem(Exception):
|
||||
pass
|
||||
class RequestNodeHasParents(Exception):
|
||||
class SignalAlreadyExists(Exception):
|
||||
pass
|
||||
class RequestNodeHasChildren(Exception):
|
||||
class SignalNotFound(Exception):
|
||||
pass
|
||||
class RequestNodeParentNameConflict(Exception):
|
||||
class SlotNotFound(Exception):
|
||||
pass
|
||||
class RequestNodeChildNameConflict(Exception):
|
||||
class MethodAlreadyExists(Exception):
|
||||
pass
|
||||
class RequestNodeSiblingNameConflict(Exception):
|
||||
class MethodNotFound(Exception):
|
||||
pass
|
||||
class RequestFileNotFound(Exception):
|
||||
class NodesAreLinked(Exception):
|
||||
pass
|
||||
class NodesNotLinked(Exception):
|
||||
pass
|
||||
class NodeHasParents(Exception):
|
||||
pass
|
||||
class NodeHasChildren(Exception):
|
||||
pass
|
||||
class NodeParentNameConflict(Exception):
|
||||
pass
|
||||
class NodeChildNameConflict(Exception):
|
||||
pass
|
||||
class NodeSiblingNameConflict(Exception):
|
||||
pass
|
||||
class FileNotFound(Exception):
|
||||
pass
|
||||
|
||||
@@ -4,59 +4,80 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
#[derive(Debug, Copy, Clone, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Invalid scene path")]
|
||||
InvalidScenePath = 2,
|
||||
InvalidScenePath = 1,
|
||||
|
||||
#[error("Node not found")]
|
||||
NodeNotFound = 3,
|
||||
NodeNotFound = 2,
|
||||
|
||||
#[error("Child node not found")]
|
||||
ChildNodeNotFound = 4,
|
||||
ChildNodeNotFound = 3,
|
||||
|
||||
#[error("Parent node not found")]
|
||||
ParentNodeNotFound = 5,
|
||||
ParentNodeNotFound = 4,
|
||||
|
||||
#[error("Property already exists")]
|
||||
PropertyAlreadyExists = 6,
|
||||
PropertyAlreadyExists = 5,
|
||||
|
||||
#[error("Property not found")]
|
||||
PropertyNotFound = 7,
|
||||
PropertyNotFound = 6,
|
||||
|
||||
#[error("Property has wrong type")]
|
||||
PropertyWrongType = 8,
|
||||
PropertyWrongType = 7,
|
||||
|
||||
#[error("Property value has the wrong length")]
|
||||
PropertyWrongLen = 8,
|
||||
|
||||
#[error("Property index is wrong")]
|
||||
PropertyWrongIndex = 9,
|
||||
|
||||
#[error("Property out of range")]
|
||||
PropertyOutOfRange = 10,
|
||||
|
||||
#[error("Property null not allowed")]
|
||||
PropertyNullNotAllowed = 11,
|
||||
|
||||
#[error("Property array is bounded length")]
|
||||
PropertyIsBounded = 12,
|
||||
|
||||
#[error("Property enum item is invalid")]
|
||||
PropertyWrongEnumItem = 13,
|
||||
|
||||
#[error("Signal already exists")]
|
||||
SignalAlreadyExists = 9,
|
||||
SignalAlreadyExists = 14,
|
||||
|
||||
#[error("Signal not found")]
|
||||
SignalNotFound = 10,
|
||||
SignalNotFound = 15,
|
||||
|
||||
#[error("Slot not found")]
|
||||
SlotNotFound = 11,
|
||||
SlotNotFound = 16,
|
||||
|
||||
#[error("Signal already exists")]
|
||||
MethodAlreadyExists = 17,
|
||||
|
||||
#[error("Method not found")]
|
||||
MethodNotFound = 12,
|
||||
MethodNotFound = 18,
|
||||
|
||||
#[error("Nodes are not linked")]
|
||||
NodesAreLinked = 13,
|
||||
NodesAreLinked = 19,
|
||||
|
||||
#[error("Nodes are not linked")]
|
||||
NodesNotLinked = 14,
|
||||
NodesNotLinked = 20,
|
||||
|
||||
#[error("Node has parents")]
|
||||
NodeHasParents = 15,
|
||||
NodeHasParents = 21,
|
||||
|
||||
#[error("Node has children")]
|
||||
NodeHasChildren = 16,
|
||||
NodeHasChildren = 22,
|
||||
|
||||
#[error("Node has a parent with this name")]
|
||||
NodeParentNameConflict = 17,
|
||||
NodeParentNameConflict = 23,
|
||||
|
||||
#[error("Node has a child with this name")]
|
||||
NodeChildNameConflict = 18,
|
||||
NodeChildNameConflict = 24,
|
||||
|
||||
#[error("Node has a sibling with this name")]
|
||||
NodeSiblingNameConflict = 19,
|
||||
NodeSiblingNameConflict = 25,
|
||||
|
||||
#[error("File not found")]
|
||||
FileNotFound = 20,
|
||||
FileNotFound = 26,
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ use std::{fmt, io::Cursor};
|
||||
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
scene::{PropertyType, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeType},
|
||||
prop::{Property, PropertySubType, PropertyType},
|
||||
scene::{SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeType},
|
||||
shader,
|
||||
};
|
||||
|
||||
@@ -157,15 +158,15 @@ impl Stage {
|
||||
let font = include_bytes!("../Inter-Regular.ttf") as &[u8];
|
||||
let font = Font::from_bytes(font, FontSettings::default()).unwrap();
|
||||
let line_metrics = font.horizontal_line_metrics(1.).unwrap();
|
||||
inter_regular.add_property_f32("ascent", line_metrics.ascent).unwrap();
|
||||
inter_regular.add_property_f32("descent", line_metrics.descent).unwrap();
|
||||
inter_regular.add_property_f32("line_gap", line_metrics.line_gap).unwrap();
|
||||
inter_regular.add_property_f32("new_line_size", line_metrics.new_line_size).unwrap();
|
||||
//inter_regular.add_property_f32("ascent", line_metrics.ascent).unwrap();
|
||||
//inter_regular.add_property_f32("descent", line_metrics.descent).unwrap();
|
||||
//inter_regular.add_property_f32("line_gap", line_metrics.line_gap).unwrap();
|
||||
//inter_regular.add_property_f32("new_line_size", line_metrics.new_line_size).unwrap();
|
||||
|
||||
inter_regular.add_method(
|
||||
"create_text",
|
||||
vec![("text", PropertyType::Str), ("font_size", PropertyType::Float32)],
|
||||
vec![("node_id", PropertyType::SceneNodeId)],
|
||||
vec![("text", "", PropertyType::Str), ("font_size", "", PropertyType::Float32)],
|
||||
vec![("node_id", "", PropertyType::SceneNodeId)],
|
||||
);
|
||||
|
||||
let inter_regular_id = inter_regular.id;
|
||||
@@ -183,14 +184,29 @@ impl Stage {
|
||||
|
||||
let window = scene_graph.add_node("window", SceneNodeType::Window);
|
||||
let (screen_width, screen_height) = window::screen_size();
|
||||
window.add_property_f32("width", screen_width).unwrap();
|
||||
window.add_property_f32("height", screen_height).unwrap();
|
||||
window.add_signal("resize").unwrap();
|
||||
window.add_method(
|
||||
"load_texture",
|
||||
vec![("node_name", PropertyType::Str), ("path", PropertyType::Str)],
|
||||
vec![("node_id", PropertyType::SceneNodeId)],
|
||||
);
|
||||
|
||||
let mut prop = Property::new("screen_size", PropertyType::Float32, PropertySubType::Pixel);
|
||||
prop.set_array_len(2);
|
||||
prop.set_f32(0, screen_width);
|
||||
prop.set_f32(1, screen_height);
|
||||
window.add_property(prop).unwrap();
|
||||
|
||||
window
|
||||
.add_signal(
|
||||
"resize",
|
||||
vec![
|
||||
("screen_width", "", PropertyType::Float32),
|
||||
("screen_height", "", PropertyType::Float32),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
window
|
||||
.add_method(
|
||||
"load_texture",
|
||||
vec![("node_name", "", PropertyType::Str), ("path", "", PropertyType::Str)],
|
||||
vec![("node_id", "", PropertyType::SceneNodeId)],
|
||||
)
|
||||
.unwrap();
|
||||
let window_id = window.id;
|
||||
scene_graph.link(window_id, SceneGraph::ROOT_ID).unwrap();
|
||||
|
||||
@@ -199,27 +215,54 @@ impl Stage {
|
||||
scene_graph.link(input_id, window_id).unwrap();
|
||||
|
||||
let keyb = scene_graph.add_node("keyboard", SceneNodeType::Keyboard);
|
||||
keyb.add_property("shift", PropertyType::Bool).unwrap();
|
||||
keyb.add_property("ctrl", PropertyType::Bool).unwrap();
|
||||
keyb.add_property("alt", PropertyType::Bool).unwrap();
|
||||
keyb.add_property("logo", PropertyType::Bool).unwrap();
|
||||
keyb.add_property("repeat", PropertyType::Bool).unwrap();
|
||||
keyb.add_property("keycode", PropertyType::Str).unwrap();
|
||||
keyb.add_signal("key_down").unwrap();
|
||||
keyb.add_signal(
|
||||
"key_down",
|
||||
vec![
|
||||
("shift", "", PropertyType::Bool),
|
||||
("ctrl", "", PropertyType::Bool),
|
||||
("alt", "", PropertyType::Bool),
|
||||
("logo", "", PropertyType::Bool),
|
||||
("repeat", "", PropertyType::Bool),
|
||||
("keycode", "", PropertyType::Enum),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
let keyb_id = keyb.id;
|
||||
scene_graph.link(keyb_id, input_id).unwrap();
|
||||
|
||||
let mouse = scene_graph.add_node("mouse", SceneNodeType::Mouse);
|
||||
mouse.add_property("button", PropertyType::Uint32).unwrap();
|
||||
mouse.add_property("motion_x", PropertyType::Float32).unwrap();
|
||||
mouse.add_property("motion_y", PropertyType::Float32).unwrap();
|
||||
mouse.add_property("wheel_y", PropertyType::Float32).unwrap();
|
||||
mouse.add_property("click_x", PropertyType::Float32).unwrap();
|
||||
mouse.add_property("click_y", PropertyType::Float32).unwrap();
|
||||
mouse.add_signal("button_up").unwrap();
|
||||
mouse.add_signal("button_down").unwrap();
|
||||
mouse.add_signal("wheel").unwrap();
|
||||
mouse.add_signal("move").unwrap();
|
||||
mouse
|
||||
.add_signal(
|
||||
"button_up",
|
||||
vec![
|
||||
("button", "", PropertyType::Enum),
|
||||
("x", "", PropertyType::Float32),
|
||||
("y", "", PropertyType::Float32),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
mouse
|
||||
.add_signal(
|
||||
"button_down",
|
||||
vec![
|
||||
("button", "", PropertyType::Enum),
|
||||
("x", "", PropertyType::Float32),
|
||||
("y", "", PropertyType::Float32),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
mouse
|
||||
.add_signal(
|
||||
"wheel",
|
||||
vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
|
||||
)
|
||||
.unwrap();
|
||||
mouse
|
||||
.add_signal(
|
||||
"move",
|
||||
vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
|
||||
)
|
||||
.unwrap();
|
||||
let mouse_id = mouse.id;
|
||||
scene_graph.link(mouse_id, input_id).unwrap();
|
||||
}
|
||||
@@ -312,12 +355,16 @@ impl Stage {
|
||||
) -> Result<SceneNodeId> {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let text_node = scene_graph.add_node(node_name, SceneNodeType::RenderText);
|
||||
text_node.add_property_str("text", text.clone()).unwrap();
|
||||
text_node.add_property_f32("font_size", font_size).unwrap();
|
||||
text_node.add_property_f32("r", 0.).unwrap();
|
||||
text_node.add_property_f32("g", 0.).unwrap();
|
||||
text_node.add_property_f32("b", 0.).unwrap();
|
||||
text_node.add_property_f32("a", 0.).unwrap();
|
||||
|
||||
let mut prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
|
||||
text_node.add_property(prop)?;
|
||||
|
||||
let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
|
||||
text_node.add_property(prop)?;
|
||||
|
||||
let mut prop = Property::new("color", PropertyType::Float32, PropertySubType::Color);
|
||||
prop.set_array_len(4);
|
||||
text_node.add_property(prop)?;
|
||||
|
||||
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
|
||||
layout.reset(&LayoutSettings { ..LayoutSettings::default() });
|
||||
@@ -328,8 +375,6 @@ impl Stage {
|
||||
let fonts = [font];
|
||||
layout.append(&fonts, &TextStyle::new(&text, font_size, 0));
|
||||
|
||||
text_node.add_property_f32("height", layout.height()).unwrap();
|
||||
|
||||
// Calculate the text width
|
||||
// std::cmp::max() not impl for f32
|
||||
let max_f32 = |x: f32, y: f32| {
|
||||
@@ -347,28 +392,33 @@ impl Stage {
|
||||
total_width = max_f32(total_width, right);
|
||||
}
|
||||
|
||||
text_node.add_property_f32("width", total_width).unwrap();
|
||||
let mut prop = Property::new("size", PropertyType::Float32, PropertySubType::Pixel);
|
||||
prop.set_array_len(2);
|
||||
prop.set_f32(0, total_width).unwrap();
|
||||
prop.set_f32(1, layout.height()).unwrap();
|
||||
|
||||
let text_node_id = text_node.id;
|
||||
|
||||
/*
|
||||
let lines = layout.lines();
|
||||
if lines.is_some() {
|
||||
for (idx, line) in lines.unwrap().into_iter().enumerate() {
|
||||
let line_node_name = format!("line.{}", idx);
|
||||
let line_node = scene_graph.add_node(line_node_name, SceneNodeType::LinePosition);
|
||||
line_node.add_property_u32("idx", idx as u32).unwrap();
|
||||
line_node.add_property_f32("baseline_y", line.baseline_y).unwrap();
|
||||
line_node.add_property_f32("padding", line.padding).unwrap();
|
||||
line_node.add_property_f32("max_ascent", line.max_ascent).unwrap();
|
||||
line_node.add_property_f32("min_descent", line.min_descent).unwrap();
|
||||
line_node.add_property_f32("max_line_gap", line.max_line_gap).unwrap();
|
||||
line_node.add_property_u32("glyph_start", line.glyph_start as u32).unwrap();
|
||||
line_node.add_property_u32("glyph_end", line.glyph_end as u32).unwrap();
|
||||
//line_node.add_property_u32("idx", idx as u32).unwrap();
|
||||
//line_node.add_property_f32("baseline_y", line.baseline_y).unwrap();
|
||||
//line_node.add_property_f32("padding", line.padding).unwrap();
|
||||
//line_node.add_property_f32("max_ascent", line.max_ascent).unwrap();
|
||||
//line_node.add_property_f32("min_descent", line.min_descent).unwrap();
|
||||
//line_node.add_property_f32("max_line_gap", line.max_line_gap).unwrap();
|
||||
//line_node.add_property_u32("glyph_start", line.glyph_start as u32).unwrap();
|
||||
//line_node.add_property_u32("glyph_end", line.glyph_end as u32).unwrap();
|
||||
|
||||
let line_node_id = line_node.id;
|
||||
scene_graph.link(line_node_id, text_node_id)?;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
scene_graph.link(font_node_id, text_node_id)?;
|
||||
Ok(text_node_id)
|
||||
@@ -387,13 +437,25 @@ impl Stage {
|
||||
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let img_node = scene_graph.add_node(node_name, SceneNodeType::RenderTexture);
|
||||
img_node.add_property_u32("width", width).unwrap();
|
||||
img_node.add_property_u32("height", height).unwrap();
|
||||
img_node.add_property_u32("texture_id", id).unwrap();
|
||||
//img_node.add_property_u32("width", width).unwrap();
|
||||
//img_node.add_property_u32("height", height).unwrap();
|
||||
//img_node.add_property_u32("texture_id", id).unwrap();
|
||||
|
||||
let mut prop = Property::new("size", PropertyType::Uint32, PropertySubType::Pixel);
|
||||
prop.set_array_len(2);
|
||||
prop.set_u32(0, width).unwrap();
|
||||
prop.set_u32(1, height).unwrap();
|
||||
img_node.add_property(prop)?;
|
||||
|
||||
let mut prop = Property::new("texture_id", PropertyType::Uint32, PropertySubType::Null);
|
||||
prop.set_u32(0, id).unwrap();
|
||||
img_node.add_property(prop)?;
|
||||
|
||||
Ok(img_node.id)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn get_obj_props(obj: &SceneNode) -> Result<(f32, f32, f32, f32, bool)> {
|
||||
let x = obj.get_property_f32("x")?;
|
||||
let y = obj.get_property_f32("y")?;
|
||||
@@ -413,6 +475,7 @@ fn get_text_props(render_text: &SceneNode) -> Result<(String, f32, [f32; 4])> {
|
||||
let color = [r, g, b, a];
|
||||
Ok((text, font_size, color))
|
||||
}
|
||||
*/
|
||||
|
||||
impl EventHandler for Stage {
|
||||
fn update(&mut self) {
|
||||
@@ -501,10 +564,10 @@ impl EventHandler for Stage {
|
||||
// This will make the top left (0, 0) and the bottom right (1, 1)
|
||||
// Default is (-1, 1) -> (1, -1)
|
||||
let proj = glam::Mat4::from_translation(glam::Vec3::new(-1., 1., 0.)) *
|
||||
glam::Mat4::from_scale(glam::Vec3::new(2./screen_width, -2./screen_height, 1.));
|
||||
glam::Mat4::from_scale(glam::Vec3::new(2. / screen_width, -2. / screen_height, 1.));
|
||||
|
||||
// Reusable text layout
|
||||
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
|
||||
//let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
|
||||
|
||||
let scene_graph = self.scene_graph.lock().unwrap();
|
||||
|
||||
@@ -522,6 +585,7 @@ impl EventHandler for Stage {
|
||||
self.ctx.begin_default_pass(PassAction::Nothing);
|
||||
self.ctx.apply_pipeline(&self.pipeline);
|
||||
|
||||
/*
|
||||
let rect_x = layer.get_property_u32("rect_x").unwrap();
|
||||
let rect_y = layer.get_property_u32("rect_y").unwrap();
|
||||
let rect_w = layer.get_property_u32("rect_w").unwrap();
|
||||
@@ -666,6 +730,7 @@ impl EventHandler for Stage {
|
||||
}
|
||||
|
||||
self.ctx.end_render_pass();
|
||||
*/
|
||||
}
|
||||
self.ctx.commit_frame();
|
||||
}
|
||||
@@ -674,14 +739,14 @@ impl EventHandler for Stage {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap();
|
||||
|
||||
win.set_property_bool("shift", modifiers.shift).unwrap();
|
||||
win.set_property_bool("ctrl", modifiers.ctrl).unwrap();
|
||||
win.set_property_bool("alt", modifiers.alt).unwrap();
|
||||
win.set_property_bool("logo", modifiers.logo).unwrap();
|
||||
win.set_property_bool("repeat", repeat).unwrap();
|
||||
//win.set_property_bool("shift", modifiers.shift).unwrap();
|
||||
//win.set_property_bool("ctrl", modifiers.ctrl).unwrap();
|
||||
//win.set_property_bool("alt", modifiers.alt).unwrap();
|
||||
//win.set_property_bool("logo", modifiers.logo).unwrap();
|
||||
//win.set_property_bool("repeat", repeat).unwrap();
|
||||
|
||||
let send_key_down = |key: &str| {
|
||||
win.set_property_str("keycode", key).unwrap();
|
||||
//win.set_property_str("keycode", key).unwrap();
|
||||
win.trigger("key_down").unwrap();
|
||||
};
|
||||
|
||||
@@ -812,39 +877,39 @@ impl EventHandler for Stage {
|
||||
fn mouse_motion_event(&mut self, x: f32, y: f32) {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
|
||||
mouse.set_property_f32("motion_x", x).unwrap();
|
||||
mouse.set_property_f32("motion_y", y).unwrap();
|
||||
//mouse.set_property_f32("motion_x", x).unwrap();
|
||||
//mouse.set_property_f32("motion_y", y).unwrap();
|
||||
mouse.trigger("move").unwrap();
|
||||
}
|
||||
fn mouse_wheel_event(&mut self, x: f32, y: f32) {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
|
||||
//mouse.set_property_f32("x", x).unwrap();
|
||||
mouse.set_property_f32("wheel_y", y).unwrap();
|
||||
//mouse.set_property_f32("wheel_y", y).unwrap();
|
||||
mouse.trigger("wheel").unwrap();
|
||||
}
|
||||
fn mouse_button_down_event(&mut self, button: MouseButton, x: f32, y: f32) {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
|
||||
mouse.set_property_u32("button", button.to_u8() as u32).unwrap();
|
||||
mouse.set_property_f32("click_x", x).unwrap();
|
||||
mouse.set_property_f32("click_y", y).unwrap();
|
||||
//mouse.set_property_u32("button", button.to_u8() as u32).unwrap();
|
||||
//mouse.set_property_f32("click_x", x).unwrap();
|
||||
//mouse.set_property_f32("click_y", y).unwrap();
|
||||
mouse.trigger("button_down").unwrap();
|
||||
}
|
||||
fn mouse_button_up_event(&mut self, button: MouseButton, x: f32, y: f32) {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
|
||||
mouse.set_property_u32("button", button.to_u8() as u32).unwrap();
|
||||
mouse.set_property_f32("click_x", x).unwrap();
|
||||
mouse.set_property_f32("click_y", y).unwrap();
|
||||
//mouse.set_property_u32("button", button.to_u8() as u32).unwrap();
|
||||
//mouse.set_property_f32("click_x", x).unwrap();
|
||||
//mouse.set_property_f32("click_y", y).unwrap();
|
||||
mouse.trigger("button_up").unwrap();
|
||||
}
|
||||
|
||||
fn resize_event(&mut self, width: f32, height: f32) {
|
||||
let mut scene_graph = self.scene_graph.lock().unwrap();
|
||||
let win = scene_graph.lookup_node_mut("/window").unwrap();
|
||||
win.set_property_f32("width", width).unwrap();
|
||||
win.set_property_f32("height", height).unwrap();
|
||||
//win.set_property_f32("width", width).unwrap();
|
||||
//win.set_property_f32("height", height).unwrap();
|
||||
win.trigger("resize").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ use net::ZeroMQAdapter;
|
||||
mod scene;
|
||||
use scene::{SceneGraph, SceneGraphPtr};
|
||||
|
||||
mod prop;
|
||||
|
||||
mod shader;
|
||||
|
||||
#[macro_use]
|
||||
@@ -31,6 +33,8 @@ fn init_zmq(scene_graph: SceneGraphPtr) {
|
||||
|
||||
fn main() {
|
||||
let scene_graph = Arc::new(Mutex::new(SceneGraph::new()));
|
||||
init_zmq(scene_graph.clone());
|
||||
init_gui(scene_graph);
|
||||
//init_zmq(scene_graph.clone());
|
||||
//init_gui(scene_graph);
|
||||
let mut zmq_rpc = ZeroMQAdapter::new(scene_graph);
|
||||
zmq_rpc.poll();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use darkfi_serial::{deserialize, Decodable, Encodable, SerialDecodable};
|
||||
use darkfi_serial::{deserialize, Decodable, Encodable, SerialDecodable, VarInt};
|
||||
use std::{
|
||||
io::Cursor,
|
||||
sync::{atomic::Ordering, mpsc},
|
||||
@@ -7,7 +7,8 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
scene::{PropertyType, PropertyValue, SceneGraphPtr, SceneNodeId, SceneNodeType, Slot, SlotId},
|
||||
prop::{Property, PropertySubType, PropertyType, PropertyValue},
|
||||
scene::{SceneGraphPtr, SceneNodeId, SceneNodeType, Slot, SlotId},
|
||||
};
|
||||
|
||||
#[derive(Debug, SerialDecodable)]
|
||||
@@ -26,8 +27,8 @@ enum Command {
|
||||
GetChildren = 4,
|
||||
GetParents = 5,
|
||||
GetProperties = 3,
|
||||
GetProperty = 6,
|
||||
SetProperty = 7,
|
||||
GetPropertyValue = 6,
|
||||
SetPropertyValue = 7,
|
||||
GetSignals = 14,
|
||||
RegisterSlot = 15,
|
||||
UnregisterSlot = 16,
|
||||
@@ -38,6 +39,14 @@ enum Command {
|
||||
CallMethod = 22,
|
||||
}
|
||||
|
||||
// Missing calls todo:
|
||||
// GetPropLen
|
||||
// UnsetProperty
|
||||
// SetPropertyNull
|
||||
// PropertyPushNull
|
||||
// PropertyPush
|
||||
// PropertyIsUnset
|
||||
|
||||
pub struct ZeroMQAdapter {
|
||||
// req-reply commands
|
||||
req_socket: zmq::Socket,
|
||||
@@ -156,52 +165,103 @@ impl ZeroMQAdapter {
|
||||
debug!(target: "req", "{:?}({})", cmd, node_id);
|
||||
|
||||
let node = scene_graph.get_node(node_id).ok_or(Error::NodeNotFound)?;
|
||||
let mut props = vec![];
|
||||
//let mut props = vec![];
|
||||
for prop in &node.props {
|
||||
props.push((prop.name.clone(), prop.get_type() as u8));
|
||||
//props.push((prop.name.clone(), prop.get_type() as u8));
|
||||
}
|
||||
props.encode(&mut reply).unwrap();
|
||||
//props.encode(&mut reply).unwrap();
|
||||
}
|
||||
Command::GetProperty => {
|
||||
Command::GetPropertyValue => {
|
||||
let node_id = SceneNodeId::decode(&mut cur).unwrap();
|
||||
let prop_name = String::decode(&mut cur).unwrap();
|
||||
debug!(target: "req", "{:?}({}, {})", cmd, node_id, prop_name);
|
||||
|
||||
let node = scene_graph.get_node(node_id).ok_or(Error::NodeNotFound)?;
|
||||
let prop = node.get_property(&prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
match &prop.val {
|
||||
PropertyValue::Null => {
|
||||
0u8.encode(&mut reply).unwrap();
|
||||
prop.typ.encode(&mut reply).unwrap();
|
||||
VarInt(prop.get_len() as u64).encode(&mut reply).unwrap();
|
||||
match prop.typ {
|
||||
PropertyType::Null => {}
|
||||
PropertyType::Bool => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_bool_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::Buffer(_) => {
|
||||
1u8.encode(&mut reply).unwrap();
|
||||
PropertyType::Uint32 => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_u32_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::Bool(val) => {
|
||||
3u8.encode(&mut reply).unwrap();
|
||||
let val = val.load(Ordering::SeqCst);
|
||||
val.encode(&mut reply).unwrap();
|
||||
PropertyType::Float32 => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_f32_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::Uint32(val) => {
|
||||
2u8.encode(&mut reply).unwrap();
|
||||
let val = val.load(Ordering::SeqCst);
|
||||
val.encode(&mut reply).unwrap();
|
||||
PropertyType::Str => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_str_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::Float32(val) => {
|
||||
4u8.encode(&mut reply).unwrap();
|
||||
let val = val.load(Ordering::SeqCst);
|
||||
val.encode(&mut reply).unwrap();
|
||||
PropertyType::Enum => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_enum_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::Str(val) => {
|
||||
5u8.encode(&mut reply).unwrap();
|
||||
let val = val.lock().unwrap();
|
||||
val.encode(&mut reply).unwrap();
|
||||
PropertyType::Buffer => {}
|
||||
PropertyType::SceneNodeId => {
|
||||
for i in 0..prop.get_len() {
|
||||
match prop.get_node_id_opt(i).unwrap() {
|
||||
Some(v) => {
|
||||
true.encode(&mut reply).unwrap();
|
||||
v.encode(&mut reply).unwrap();
|
||||
}
|
||||
None => {
|
||||
false.encode(&mut reply).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyValue::SceneNodeId(val) => {
|
||||
6u8.encode(&mut reply).unwrap();
|
||||
let val = val.load(Ordering::SeqCst);
|
||||
val.encode(&mut reply).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Command::AddNode => {
|
||||
let node_name = String::decode(&mut cur).unwrap();
|
||||
@@ -236,10 +296,90 @@ impl ZeroMQAdapter {
|
||||
let node_id = SceneNodeId::decode(&mut cur).unwrap();
|
||||
let prop_name = String::decode(&mut cur).unwrap();
|
||||
let prop_type = PropertyType::decode(&mut cur).unwrap();
|
||||
debug!(target: "req", "{:?}({}, {}, {:?})", cmd, node_id, prop_name, prop_type);
|
||||
let prop_subtype = PropertySubType::decode(&mut cur).unwrap();
|
||||
|
||||
debug!(target: "req", "{:?}({}, {}, {:?}, {:?}, ...)", cmd, node_id, prop_name, prop_type, prop_subtype);
|
||||
let mut prop = Property::new(prop_name, prop_type, prop_subtype);
|
||||
|
||||
let prop_array_len = u32::decode(&mut cur).unwrap();
|
||||
prop.set_array_len(prop_array_len as usize);
|
||||
|
||||
let prop_defaults_is_some = bool::decode(&mut cur).unwrap();
|
||||
if prop_defaults_is_some {
|
||||
let prop_defaults_len = VarInt::decode(&mut cur).unwrap();
|
||||
match prop_type {
|
||||
PropertyType::Uint32 => {
|
||||
let mut prop_defaults = vec![];
|
||||
for _ in 0..prop_defaults_len.0 {
|
||||
prop_defaults.push(u32::decode(&mut cur).unwrap());
|
||||
}
|
||||
prop.set_defaults_u32(prop_defaults)?;
|
||||
}
|
||||
PropertyType::Float32 => {
|
||||
let mut prop_defaults = vec![];
|
||||
for _ in 0..prop_defaults_len.0 {
|
||||
prop_defaults.push(f32::decode(&mut cur).unwrap());
|
||||
}
|
||||
prop.set_defaults_f32(prop_defaults)?;
|
||||
}
|
||||
_ => return Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
let prop_ui_name = String::decode(&mut cur).unwrap();
|
||||
let prop_desc = String::decode(&mut cur).unwrap();
|
||||
let prop_is_null_allowed = bool::decode(&mut cur).unwrap();
|
||||
|
||||
match prop_type {
|
||||
PropertyType::Uint32 => {
|
||||
let min_is_some = bool::decode(&mut cur).unwrap();
|
||||
let min = if min_is_some {
|
||||
let min = u32::decode(&mut cur).unwrap();
|
||||
Some(PropertyValue::Uint32(min))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let max_is_some = bool::decode(&mut cur).unwrap();
|
||||
let max = if max_is_some {
|
||||
let max = u32::decode(&mut cur).unwrap();
|
||||
Some(PropertyValue::Uint32(max))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
prop.min_val = min;
|
||||
prop.max_val = max;
|
||||
}
|
||||
PropertyType::Float32 => {
|
||||
let min_is_some = bool::decode(&mut cur).unwrap();
|
||||
let min = if min_is_some {
|
||||
let min = f32::decode(&mut cur).unwrap();
|
||||
Some(PropertyValue::Float32(min))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let max_is_some = bool::decode(&mut cur).unwrap();
|
||||
let max = if max_is_some {
|
||||
let max = f32::decode(&mut cur).unwrap();
|
||||
Some(PropertyValue::Float32(max))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
prop.min_val = min;
|
||||
prop.max_val = max;
|
||||
}
|
||||
_ => return Err(Error::PropertyWrongType),
|
||||
}
|
||||
|
||||
let prop_enum_items = Vec::<String>::decode(&mut cur).unwrap();
|
||||
|
||||
let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
|
||||
node.add_property(prop_name, prop_type)?;
|
||||
|
||||
prop.set_ui_text(prop_ui_name, prop_desc);
|
||||
prop.is_null_allowed = prop_is_null_allowed;
|
||||
if !prop_enum_items.is_empty() {
|
||||
prop.set_enum_items(prop_enum_items)?;
|
||||
}
|
||||
node.add_property(prop)?;
|
||||
}
|
||||
Command::LinkNode => {
|
||||
let child_id = SceneNodeId::decode(&mut cur).unwrap();
|
||||
@@ -253,39 +393,40 @@ impl ZeroMQAdapter {
|
||||
debug!(target: "req", "{:?}({}, {})", cmd, child_id, parent_id);
|
||||
scene_graph.unlink(child_id, parent_id)?;
|
||||
}
|
||||
Command::SetProperty => {
|
||||
Command::SetPropertyValue => {
|
||||
let node_id = SceneNodeId::decode(&mut cur).unwrap();
|
||||
let prop_name = String::decode(&mut cur).unwrap();
|
||||
let prop_i = u32::decode(&mut cur).unwrap() as usize;
|
||||
debug!(target: "req", "{:?}({}, {})", cmd, node_id, prop_name);
|
||||
|
||||
let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
|
||||
let prop = node.get_property(&prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
match prop.get_type() {
|
||||
match prop.typ {
|
||||
PropertyType::Null => {}
|
||||
PropertyType::Buffer => {
|
||||
let val = Vec::<u8>::decode(&mut cur).unwrap();
|
||||
prop.set_buf(val)?;
|
||||
}
|
||||
PropertyType::Bool => {
|
||||
let val = bool::decode(&mut cur).unwrap();
|
||||
prop.set_bool(val)?;
|
||||
prop.set_bool(prop_i, val)?;
|
||||
}
|
||||
PropertyType::Uint32 => {
|
||||
let val = u32::decode(&mut cur).unwrap();
|
||||
prop.set_u32(val)?;
|
||||
prop.set_u32(prop_i, val)?;
|
||||
}
|
||||
PropertyType::Float32 => {
|
||||
let val = f32::decode(&mut cur).unwrap();
|
||||
prop.set_f32(val)?;
|
||||
prop.set_f32(prop_i, val)?;
|
||||
}
|
||||
PropertyType::Str => {
|
||||
PropertyType::Str | PropertyType::Enum => {
|
||||
let val = String::decode(&mut cur).unwrap();
|
||||
prop.set_str(val)?;
|
||||
prop.set_str(prop_i, val)?;
|
||||
}
|
||||
PropertyType::Buffer => {
|
||||
let val = Vec::<u8>::decode(&mut cur).unwrap();
|
||||
prop.set_buf(prop_i, val)?;
|
||||
}
|
||||
PropertyType::SceneNodeId => {
|
||||
let val = SceneNodeId::decode(&mut cur).unwrap();
|
||||
prop.set_node_id(val)?;
|
||||
prop.set_node_id(prop_i, val)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
574
bin/darkwallet/src/prop.rs
Normal file
574
bin/darkwallet/src/prop.rs
Normal file
@@ -0,0 +1,574 @@
|
||||
use crate::error::{Error, Result};
|
||||
use atomic_float::AtomicF32;
|
||||
use darkfi_serial::{SerialDecodable, SerialEncodable};
|
||||
use std::{
|
||||
fmt,
|
||||
str::FromStr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
Arc, Mutex, MutexGuard,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::scene::SceneNodeId;
|
||||
|
||||
type BufferGuard<'a> = MutexGuard<'a, Vec<u8>>;
|
||||
|
||||
type Buffer = Arc<Vec<u8>>;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
#[repr(u8)]
|
||||
pub enum PropertyType {
|
||||
Null = 0,
|
||||
Bool = 1,
|
||||
Uint32 = 2,
|
||||
Float32 = 3,
|
||||
Str = 4,
|
||||
Enum = 5,
|
||||
Buffer = 6,
|
||||
SceneNodeId = 7,
|
||||
}
|
||||
|
||||
impl PropertyType {
|
||||
fn default_value(&self) -> PropertyValue {
|
||||
match self {
|
||||
Self::Null => PropertyValue::Null,
|
||||
Self::Bool => PropertyValue::Bool(false),
|
||||
Self::Uint32 => PropertyValue::Uint32(0),
|
||||
Self::Float32 => PropertyValue::Float32(0.),
|
||||
Self::Str => PropertyValue::Str(String::new()),
|
||||
Self::Enum => PropertyValue::Enum(String::new()),
|
||||
Self::Buffer => PropertyValue::Buffer(Arc::new(vec![])),
|
||||
Self::SceneNodeId => PropertyValue::SceneNodeId(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
#[repr(u8)]
|
||||
pub enum PropertySubType {
|
||||
Null = 0,
|
||||
Color = 1,
|
||||
// Size of something in pixels
|
||||
Pixel = 2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PropertyValue {
|
||||
Unset,
|
||||
Null,
|
||||
Bool(bool),
|
||||
Uint32(u32),
|
||||
Float32(f32),
|
||||
Str(String),
|
||||
Enum(String),
|
||||
Buffer(Arc<Vec<u8>>),
|
||||
SceneNodeId(SceneNodeId),
|
||||
}
|
||||
|
||||
impl PropertyValue {
|
||||
fn as_type(&self) -> PropertyType {
|
||||
match self {
|
||||
Self::Unset => todo!("not sure"),
|
||||
Self::Null => PropertyType::Null,
|
||||
Self::Bool(_) => PropertyType::Bool,
|
||||
Self::Uint32(_) => PropertyType::Uint32,
|
||||
Self::Float32(_) => PropertyType::Float32,
|
||||
Self::Str(_) => PropertyType::Str,
|
||||
Self::Enum(_) => PropertyType::Enum,
|
||||
Self::Buffer(_) => PropertyType::Buffer,
|
||||
Self::SceneNodeId(_) => PropertyType::SceneNodeId,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_unset(&self) -> bool {
|
||||
match self {
|
||||
Self::Unset => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
match self {
|
||||
Self::Null => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_bool(&self) -> Result<bool> {
|
||||
match self {
|
||||
Self::Bool(v) => Ok(*v),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_u32(&self) -> Result<u32> {
|
||||
match self {
|
||||
Self::Uint32(v) => Ok(*v),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_f32(&self) -> Result<f32> {
|
||||
match self {
|
||||
Self::Float32(v) => Ok(*v),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_str(&self) -> Result<String> {
|
||||
match self {
|
||||
Self::Str(v) => Ok(v.clone()),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_enum(&self) -> Result<String> {
|
||||
match self {
|
||||
Self::Enum(v) => Ok(v.clone()),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_buf(&self) -> Result<Buffer> {
|
||||
match self {
|
||||
Self::Buffer(v) => Ok(v.clone()),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
fn as_node_id(&self) -> Result<SceneNodeId> {
|
||||
match self {
|
||||
Self::SceneNodeId(v) => Ok(*v),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Property {
|
||||
pub name: String,
|
||||
pub typ: PropertyType,
|
||||
pub subtype: PropertySubType,
|
||||
pub defaults: Vec<PropertyValue>,
|
||||
pub vals: Mutex<Vec<PropertyValue>>,
|
||||
|
||||
pub ui_name: String,
|
||||
pub desc: String,
|
||||
|
||||
pub is_null_allowed: bool,
|
||||
// Use 0 for unbounded length
|
||||
pub array_len: usize,
|
||||
pub min_val: Option<PropertyValue>,
|
||||
pub max_val: Option<PropertyValue>,
|
||||
|
||||
// PropertyType must be Enum
|
||||
pub enum_items: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Property {
|
||||
pub fn new<S: Into<String>>(name: S, typ: PropertyType, subtype: PropertySubType) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
typ,
|
||||
subtype,
|
||||
|
||||
defaults: vec![typ.default_value()],
|
||||
vals: Mutex::new(vec![PropertyValue::Unset]),
|
||||
|
||||
ui_name: String::new(),
|
||||
desc: String::new(),
|
||||
|
||||
is_null_allowed: false,
|
||||
array_len: 1,
|
||||
min_val: None,
|
||||
max_val: None,
|
||||
enum_items: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_ui_text<S: Into<String>>(&mut self, ui_name: S, desc: S) {
|
||||
self.ui_name = ui_name.into();
|
||||
self.desc = desc.into();
|
||||
}
|
||||
|
||||
pub fn set_array_len(&mut self, len: usize) {
|
||||
self.array_len = len;
|
||||
self.defaults.resize(len, self.typ.default_value());
|
||||
self.vals.lock().unwrap().resize(len, PropertyValue::Unset);
|
||||
}
|
||||
pub fn set_unbounded(&mut self) {
|
||||
self.set_array_len(0);
|
||||
}
|
||||
|
||||
pub fn set_range_u32(&mut self, min: u32, max: u32) {
|
||||
self.min_val = Some(PropertyValue::Uint32(min));
|
||||
self.max_val = Some(PropertyValue::Uint32(max));
|
||||
}
|
||||
pub fn set_range_f32(&mut self, min: f32, max: f32) {
|
||||
self.min_val = Some(PropertyValue::Float32(min));
|
||||
self.max_val = Some(PropertyValue::Float32(max));
|
||||
}
|
||||
|
||||
pub fn set_enum_items<S: Into<String>>(&mut self, enum_items: Vec<S>) -> Result<()> {
|
||||
if self.typ != PropertyType::Enum {
|
||||
return Err(Error::PropertyWrongType)
|
||||
}
|
||||
self.enum_items = Some(enum_items.into_iter().map(|item| item.into()).collect());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn allow_null_values(&mut self) {
|
||||
self.is_null_allowed = true;
|
||||
}
|
||||
|
||||
fn check_defaults_len(&self, defaults_len: usize) -> Result<()> {
|
||||
if !self.is_bounded() || defaults_len != self.array_len {
|
||||
return Err(Error::PropertyWrongLen)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_defaults_u32(&mut self, defaults: Vec<u32>) -> Result<()> {
|
||||
self.check_defaults_len(defaults.len())?;
|
||||
self.defaults = defaults.into_iter().map(|v| PropertyValue::Uint32(v)).collect();
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_defaults_f32(&mut self, defaults: Vec<f32>) -> Result<()> {
|
||||
self.check_defaults_len(defaults.len())?;
|
||||
self.defaults = defaults.into_iter().map(|v| PropertyValue::Float32(v)).collect();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_len(&self) -> usize {
|
||||
// Avoid locking unless we need to
|
||||
// If array len is nonzero, then vals len should be the same.
|
||||
if !self.is_bounded() {
|
||||
return self.vals.lock().unwrap().len()
|
||||
}
|
||||
self.array_len
|
||||
}
|
||||
|
||||
fn is_bounded(&self) -> bool {
|
||||
self.array_len != 0
|
||||
}
|
||||
|
||||
/// This will clear all values, resetting them to the default
|
||||
pub fn clear_values(&self) {
|
||||
let vals = &mut self.vals.lock().unwrap();
|
||||
vals.clear();
|
||||
vals.resize(self.array_len, PropertyValue::Unset);
|
||||
}
|
||||
|
||||
// Set
|
||||
|
||||
fn set_raw_value(&self, i: usize, val: PropertyValue) -> Result<()> {
|
||||
if self.typ != val.as_type() {
|
||||
return Err(Error::PropertyWrongType)
|
||||
}
|
||||
|
||||
let vals = &mut self.vals.lock().unwrap();
|
||||
if i >= vals.len() {
|
||||
return Err(Error::PropertyWrongIndex)
|
||||
}
|
||||
vals[i] = val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unset(&self, i: usize) -> Result<()> {
|
||||
let vals = &mut self.vals.lock().unwrap();
|
||||
if i >= vals.len() {
|
||||
return Err(Error::PropertyWrongIndex)
|
||||
}
|
||||
vals[i] = PropertyValue::Unset;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_null(&self, i: usize) -> Result<()> {
|
||||
if !self.is_null_allowed {
|
||||
return Err(Error::PropertyNullNotAllowed)
|
||||
}
|
||||
let vals = &mut self.vals.lock().unwrap();
|
||||
if i >= vals.len() {
|
||||
return Err(Error::PropertyWrongIndex)
|
||||
}
|
||||
vals[i] = PropertyValue::Null;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_bool(&self, i: usize, val: bool) -> Result<()> {
|
||||
self.set_raw_value(i, PropertyValue::Bool(val))
|
||||
}
|
||||
pub fn set_u32(&self, i: usize, val: u32) -> Result<()> {
|
||||
if self.min_val.is_some() {
|
||||
let min = self.min_val.as_ref().unwrap().as_u32()?;
|
||||
if val < min {
|
||||
return Err(Error::PropertyOutOfRange);
|
||||
}
|
||||
}
|
||||
if self.max_val.is_some() {
|
||||
let max = self.max_val.as_ref().unwrap().as_u32()?;
|
||||
if val > max {
|
||||
return Err(Error::PropertyOutOfRange);
|
||||
}
|
||||
}
|
||||
self.set_raw_value(i, PropertyValue::Uint32(val))
|
||||
}
|
||||
pub fn set_f32(&self, i: usize, val: f32) -> Result<()> {
|
||||
if self.min_val.is_some() {
|
||||
let min = self.min_val.as_ref().unwrap().as_f32()?;
|
||||
if val < min {
|
||||
return Err(Error::PropertyOutOfRange);
|
||||
}
|
||||
}
|
||||
if self.max_val.is_some() {
|
||||
let max = self.max_val.as_ref().unwrap().as_f32()?;
|
||||
if val > max {
|
||||
return Err(Error::PropertyOutOfRange);
|
||||
}
|
||||
}
|
||||
self.set_raw_value(i, PropertyValue::Float32(val))
|
||||
}
|
||||
pub fn set_str<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
|
||||
self.set_raw_value(i, PropertyValue::Str(val.into()))
|
||||
}
|
||||
pub fn set_enum<S: Into<String>>(&self, i: usize, val: S) -> Result<()> {
|
||||
if self.typ != PropertyType::Enum {
|
||||
return Err(Error::PropertyWrongType)
|
||||
}
|
||||
let val = val.into();
|
||||
if !self.enum_items.as_ref().unwrap().contains(&val) {
|
||||
return Err(Error::PropertyWrongEnumItem)
|
||||
}
|
||||
self.set_raw_value(i, PropertyValue::Enum(val.into()))
|
||||
}
|
||||
pub fn set_buf(&self, i: usize, val: Vec<u8>) -> Result<()> {
|
||||
self.set_raw_value(i, PropertyValue::Buffer(Arc::new(val)))
|
||||
}
|
||||
pub fn set_node_id(&self, i: usize, val: SceneNodeId) -> Result<()> {
|
||||
self.set_raw_value(i, PropertyValue::SceneNodeId(val))
|
||||
}
|
||||
|
||||
// Push
|
||||
|
||||
pub fn push_null(&self) -> Result<usize> {
|
||||
if self.is_bounded() {
|
||||
return Err(Error::PropertyIsBounded)
|
||||
}
|
||||
let vals = &mut self.vals.lock().unwrap();
|
||||
let i = vals.len();
|
||||
vals.push(PropertyValue::Null);
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
pub fn push_bool(&self, val: bool) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_bool(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_u32(&self, val: u32) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_u32(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_f32(&self, val: f32) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_f32(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_str<S: Into<String>>(&self, val: S) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_str(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_enum<S: Into<String>>(&self, val: S) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_enum(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_buf(&self, val: Vec<u8>) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_buf(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
pub fn push_node_id(&self, val: SceneNodeId) -> Result<usize> {
|
||||
let i = self.push_null()?;
|
||||
self.set_node_id(i, val)?;
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
// Get
|
||||
|
||||
pub fn is_unset(&self, i: usize) -> Result<bool> {
|
||||
let val = self.get_raw_value(i)?;
|
||||
Ok(val.is_unset())
|
||||
}
|
||||
|
||||
pub fn get_raw_value(&self, i: usize) -> Result<PropertyValue> {
|
||||
let vals = &self.vals.lock().unwrap();
|
||||
if self.is_bounded() {
|
||||
assert_eq!(vals.len(), self.array_len);
|
||||
}
|
||||
if i >= vals.len() {
|
||||
return Err(Error::PropertyWrongIndex)
|
||||
}
|
||||
Ok(vals[i].clone())
|
||||
}
|
||||
|
||||
pub fn get_value(&self, i: usize) -> Result<PropertyValue> {
|
||||
let val = self.get_raw_value(i)?;
|
||||
if val.is_unset() {
|
||||
return Ok(self.defaults[i].clone())
|
||||
}
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn get_bool(&self, i: usize) -> Result<bool> {
|
||||
self.get_value(i)?.as_bool()
|
||||
}
|
||||
pub fn get_bool_opt(&self, i: usize) -> Result<Option<bool>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_bool()?))
|
||||
}
|
||||
pub fn get_u32(&self, i: usize) -> Result<u32> {
|
||||
self.get_value(i)?.as_u32()
|
||||
}
|
||||
pub fn get_u32_opt(&self, i: usize) -> Result<Option<u32>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_u32()?))
|
||||
}
|
||||
pub fn get_f32(&self, i: usize) -> Result<f32> {
|
||||
self.get_value(i)?.as_f32()
|
||||
}
|
||||
pub fn get_f32_opt(&self, i: usize) -> Result<Option<f32>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_f32()?))
|
||||
}
|
||||
pub fn get_str(&self, i: usize) -> Result<String> {
|
||||
self.get_value(i)?.as_str()
|
||||
}
|
||||
pub fn get_str_opt(&self, i: usize) -> Result<Option<String>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_str()?))
|
||||
}
|
||||
pub fn get_enum(&self, i: usize) -> Result<String> {
|
||||
self.get_value(i)?.as_enum()
|
||||
}
|
||||
pub fn get_enum_opt(&self, i: usize) -> Result<Option<String>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_enum()?))
|
||||
}
|
||||
pub fn get_buf(&self, i: usize) -> Result<Buffer> {
|
||||
self.get_value(i)?.as_buf()
|
||||
}
|
||||
pub fn get_buf_opt(&self, i: usize) -> Result<Option<Buffer>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_buf()?))
|
||||
}
|
||||
pub fn get_node_id(&self, i: usize) -> Result<SceneNodeId> {
|
||||
self.get_value(i)?.as_node_id()
|
||||
}
|
||||
pub fn get_node_id_opt(&self, i: usize) -> Result<Option<SceneNodeId>> {
|
||||
let val = self.get_value(i)?;
|
||||
if val.is_null() {
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(Some(val.as_node_id()?))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_getset() {
|
||||
let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
assert!(prop.set_f32(1, 4.).is_err());
|
||||
assert!(prop.is_unset(0).unwrap());
|
||||
assert!(prop.set_f32(0, 4.).is_ok());
|
||||
assert_eq!(prop.get_f32(0).unwrap(), 4.);
|
||||
assert!(!prop.is_unset(0).unwrap());
|
||||
prop.unset(0).unwrap();
|
||||
assert!(prop.is_unset(0).unwrap());
|
||||
assert_eq!(prop.get_f32(0).unwrap(), 0.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nullable() {
|
||||
// default len is 1
|
||||
let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
assert!(prop.set_defaults_f32(vec![1.0, 0.0]).is_err());
|
||||
assert!(prop.set_defaults_f32(vec![2.0]).is_ok());
|
||||
prop.allow_null_values();
|
||||
prop.set_null(0).unwrap();
|
||||
|
||||
assert!(prop.get_f32_opt(1).is_err());
|
||||
assert!(prop.get_f32_opt(0).is_ok());
|
||||
assert!(prop.get_f32_opt(0).unwrap().is_none());
|
||||
|
||||
prop.clear_values();
|
||||
assert!(prop.get_f32(0).is_ok());
|
||||
assert!(prop.get_f32_opt(0).unwrap().is_some());
|
||||
assert_eq!(prop.get_f32(0).unwrap(), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonnullable() {
|
||||
let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
assert!(prop.set_null(0).is_err());
|
||||
assert!(prop.is_unset(0).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unbounded() {
|
||||
let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
prop.set_unbounded();
|
||||
assert_eq!(prop.get_len(), 0);
|
||||
prop.push_f32(2.0).unwrap();
|
||||
prop.push_f32(3.0).unwrap();
|
||||
assert_eq!(prop.get_len(), 2);
|
||||
|
||||
prop.clear_values();
|
||||
assert_eq!(prop.get_len(), 0);
|
||||
prop.allow_null_values();
|
||||
prop.push_null().unwrap();
|
||||
prop.push_f32(4.0).unwrap();
|
||||
prop.push_f32(5.0).unwrap();
|
||||
assert_eq!(prop.get_len(), 3);
|
||||
assert!(prop.get_f32_opt(0).unwrap().is_none());
|
||||
assert!(prop.get_f32_opt(1).unwrap().is_some());
|
||||
assert!(prop.get_f32_opt(2).unwrap().is_some());
|
||||
assert!(prop.get_f32_opt(3).is_err());
|
||||
|
||||
let mut prop2 = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
assert!(prop2.push_f32(4.0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range() {
|
||||
let mut prop = Property::new("foo", PropertyType::Float32, PropertySubType::Null);
|
||||
let half_pi = 3.1415926535 / 2.;
|
||||
prop.set_range_f32(-half_pi, half_pi);
|
||||
assert!(prop.set_f32(0, 6.).is_err());
|
||||
assert!(prop.set_f32(0, 1.).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enum() {
|
||||
let mut prop = Property::new("foo", PropertyType::Enum, PropertySubType::Null);
|
||||
prop.set_enum_items(vec!["ABC", "XYZ", "FOO"]).unwrap();
|
||||
assert!(prop.set_enum(0, "ABC").is_ok());
|
||||
assert!(prop.set_enum(0, "BAR").is_err());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::error::{Error, Result};
|
||||
use atomic_float::AtomicF32;
|
||||
use darkfi_serial::{SerialDecodable, SerialEncodable};
|
||||
use std::{
|
||||
@@ -10,6 +9,11 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
prop::{Property, PropertyType},
|
||||
};
|
||||
|
||||
pub struct ScenePath(Vec<String>);
|
||||
|
||||
impl<S: Into<String>> From<S> for ScenePath {
|
||||
@@ -397,43 +401,11 @@ impl SceneNode {
|
||||
.map(|child_inf| scene_graph.get_node(child_inf.id).unwrap())
|
||||
}
|
||||
|
||||
pub fn add_property<S: Into<String>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
typ: PropertyType,
|
||||
) -> Result<Arc<Property>> {
|
||||
let name = name.into();
|
||||
if self.has_property(&name) {
|
||||
pub fn add_property(&mut self, prop: Property) -> Result<()> {
|
||||
if self.has_property(&prop.name) {
|
||||
return Err(Error::PropertyAlreadyExists);
|
||||
}
|
||||
let prop = Property::new(name, typ);
|
||||
self.props.push(prop.clone());
|
||||
Ok(prop)
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
pub fn add_property_buf(&mut self, name: &str, val: Vec<u8>) -> Result<()> {
|
||||
self.add_property(name, PropertyType::Buffer)?.set_buf(val)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn add_property_bool(&mut self, name: &str, val: bool) -> Result<()> {
|
||||
self.add_property(name, PropertyType::Bool)?.set_bool(val)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn add_property_u32(&mut self, name: &str, val: u32) -> Result<()> {
|
||||
self.add_property(name, PropertyType::Uint32)?.set_u32(val)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn add_property_f32(&mut self, name: &str, val: f32) -> Result<()> {
|
||||
self.add_property(name, PropertyType::Float32)?.set_f32(val)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn add_property_str<S: Into<String>>(&mut self, name: &str, val: S) -> Result<()> {
|
||||
self.add_property(name, PropertyType::Str)?.set_str(val)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn add_property_node_id(&mut self, name: &str, val: SceneNodeId) -> Result<()> {
|
||||
self.add_property(name, PropertyType::SceneNodeId)?.set_node_id(val)?;
|
||||
self.props.push(Arc::new(prop));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -447,43 +419,51 @@ impl SceneNode {
|
||||
|
||||
// Convenience methods
|
||||
pub fn get_property_bool(&self, name: &str) -> Result<bool> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_bool()
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_bool(0)
|
||||
}
|
||||
pub fn get_property_u32(&self, name: &str) -> Result<u32> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_u32()
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_u32(0)
|
||||
}
|
||||
pub fn get_property_f32(&self, name: &str) -> Result<f32> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_f32()
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_f32(0)
|
||||
}
|
||||
pub fn get_property_str(&self, name: &str) -> Result<String> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_str()
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_str(0)
|
||||
}
|
||||
pub fn get_property_node_id(&self, name: &str) -> Result<SceneNodeId> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_node_id()
|
||||
}
|
||||
// Setters
|
||||
pub fn set_property_bool(&self, name: &str, val: bool) -> Result<()> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.set_bool(val)
|
||||
}
|
||||
pub fn set_property_u32(&self, name: &str, val: u32) -> Result<()> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.set_u32(val)
|
||||
}
|
||||
pub fn set_property_f32(&self, name: &str, val: f32) -> Result<()> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.set_f32(val)
|
||||
}
|
||||
pub fn set_property_str<S: Into<String>>(&self, name: &str, val: S) -> Result<()> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.set_str(val)
|
||||
}
|
||||
pub fn set_property_node_id(&self, name: &str, val: SceneNodeId) -> Result<()> {
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.set_node_id(val)
|
||||
self.get_property(name).ok_or(Error::PropertyNotFound)?.get_node_id(0)
|
||||
}
|
||||
//// Setters
|
||||
//pub fn set_property_bool(&self, name: &str, val: bool) -> Result<()> {
|
||||
// self.get_property(name).ok_or(Error::PropertyNotFound)?.set_bool(val)
|
||||
//}
|
||||
//pub fn set_property_u32(&self, name: &str, val: u32) -> Result<()> {
|
||||
// self.get_property(name).ok_or(Error::PropertyNotFound)?.set_u32(val)
|
||||
//}
|
||||
//pub fn set_property_f32(&self, name: &str, val: f32) -> Result<()> {
|
||||
// self.get_property(name).ok_or(Error::PropertyNotFound)?.set_f32(val)
|
||||
//}
|
||||
//pub fn set_property_str<S: Into<String>>(&self, name: &str, val: S) -> Result<()> {
|
||||
// self.get_property(name).ok_or(Error::PropertyNotFound)?.set_str(val)
|
||||
//}
|
||||
//pub fn set_property_node_id(&self, name: &str, val: SceneNodeId) -> Result<()> {
|
||||
// self.get_property(name).ok_or(Error::PropertyNotFound)?.set_node_id(val)
|
||||
//}
|
||||
|
||||
pub fn add_signal<S: Into<String>>(&mut self, name: S) -> Result<()> {
|
||||
pub fn add_signal<S: Into<String>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
fmt: Vec<(S, S, PropertyType)>,
|
||||
) -> Result<()> {
|
||||
let name = name.into();
|
||||
if self.has_signal(&name) {
|
||||
return Err(Error::SignalAlreadyExists);
|
||||
}
|
||||
self.sigs.push(Signal { name: name.into(), slots: vec![], freed: vec![] });
|
||||
let fmt = fmt
|
||||
.into_iter()
|
||||
.map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
|
||||
.collect();
|
||||
self.sigs.push(Signal { name: name.into(), fmt, slots: vec![], freed: vec![] });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -530,12 +510,23 @@ impl SceneNode {
|
||||
pub fn add_method<S: Into<String>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
args: Vec<(S, PropertyType)>,
|
||||
result: Vec<(S, PropertyType)>,
|
||||
) {
|
||||
let args = args.into_iter().map(|(s, p)| (s.into(), p)).collect();
|
||||
let result = result.into_iter().map(|(s, p)| (s.into(), p)).collect();
|
||||
self.methods.push(Method { name: name.into(), args, result, queue: vec![] })
|
||||
args: Vec<(S, S, PropertyType)>,
|
||||
result: Vec<(S, S, PropertyType)>,
|
||||
) -> Result<()> {
|
||||
let name = name.into();
|
||||
if self.has_signal(&name) {
|
||||
return Err(Error::MethodAlreadyExists);
|
||||
}
|
||||
let args = args
|
||||
.into_iter()
|
||||
.map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
|
||||
.collect();
|
||||
let result = result
|
||||
.into_iter()
|
||||
.map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
|
||||
.collect();
|
||||
self.methods.push(Method { name: name.into(), args, result, queue: vec![] });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_method(&self, name: &str) -> Option<&Method> {
|
||||
@@ -557,165 +548,11 @@ impl SceneNode {
|
||||
}
|
||||
}
|
||||
|
||||
type BufferGuard<'a> = MutexGuard<'a, Vec<u8>>;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
#[repr(u8)]
|
||||
pub enum PropertyType {
|
||||
Null = 0,
|
||||
Buffer = 1,
|
||||
Bool = 2,
|
||||
Uint32 = 3,
|
||||
Float32 = 4,
|
||||
Str = 5,
|
||||
SceneNodeId = 6,
|
||||
}
|
||||
|
||||
pub enum PropertyValue {
|
||||
Null,
|
||||
Buffer(Mutex<Vec<u8>>),
|
||||
Bool(AtomicBool),
|
||||
Uint32(AtomicU32),
|
||||
Float32(AtomicF32),
|
||||
Str(Mutex<String>),
|
||||
SceneNodeId(AtomicU32),
|
||||
}
|
||||
|
||||
pub struct Property {
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct CallArg {
|
||||
pub name: String,
|
||||
//typ: PropertyType,
|
||||
pub val: PropertyValue,
|
||||
}
|
||||
|
||||
impl Property {
|
||||
fn new(name: String, typ: PropertyType) -> Arc<Self> {
|
||||
let val = match typ {
|
||||
PropertyType::Null => PropertyValue::Null,
|
||||
PropertyType::Buffer => PropertyValue::Buffer(Mutex::new(Vec::new())),
|
||||
PropertyType::Bool => PropertyValue::Bool(AtomicBool::new(false)),
|
||||
PropertyType::Uint32 => PropertyValue::Uint32(AtomicU32::new(0)),
|
||||
PropertyType::Float32 => PropertyValue::Float32(AtomicF32::new(0.)),
|
||||
PropertyType::Str => PropertyValue::Str(Mutex::new(String::new())),
|
||||
PropertyType::SceneNodeId => PropertyValue::SceneNodeId(AtomicU32::new(0)),
|
||||
};
|
||||
Arc::new(Self { name, val })
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> PropertyType {
|
||||
match self.val {
|
||||
PropertyValue::Null => PropertyType::Null,
|
||||
PropertyValue::Buffer(_) => PropertyType::Buffer,
|
||||
PropertyValue::Bool(_) => PropertyType::Bool,
|
||||
PropertyValue::Uint32(_) => PropertyType::Uint32,
|
||||
PropertyValue::Float32(_) => PropertyType::Float32,
|
||||
PropertyValue::Str(_) => PropertyType::Str,
|
||||
PropertyValue::SceneNodeId(_) => PropertyType::SceneNodeId,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_buf<'a>(&'a self) -> Result<BufferGuard<'a>> {
|
||||
match &self.val {
|
||||
PropertyValue::Buffer(propval) => Ok(propval.lock().unwrap()),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bool(&self) -> Result<bool> {
|
||||
match &self.val {
|
||||
PropertyValue::Bool(propval) => Ok(propval.load(Ordering::SeqCst)),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_u32(&self) -> Result<u32> {
|
||||
match &self.val {
|
||||
PropertyValue::Uint32(propval) => Ok(propval.load(Ordering::SeqCst)),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_f32(&self) -> Result<f32> {
|
||||
match &self.val {
|
||||
PropertyValue::Float32(propval) => Ok(propval.load(Ordering::SeqCst)),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_str(&self) -> Result<String> {
|
||||
match &self.val {
|
||||
PropertyValue::Str(propval) => Ok(propval.lock().unwrap().clone()),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_node_id(&self) -> Result<SceneNodeId> {
|
||||
match &self.val {
|
||||
PropertyValue::SceneNodeId(propval) => Ok(propval.load(Ordering::SeqCst)),
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_buf(&self, val: Vec<u8>) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::Buffer(propval) => {
|
||||
let mut buf = propval.lock().unwrap();
|
||||
let _ = std::mem::replace(&mut *buf, val);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_bool(&self, val: bool) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::Bool(propval) => {
|
||||
propval.store(val, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_u32(&self, val: u32) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::Uint32(propval) => {
|
||||
propval.store(val, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_f32(&self, val: f32) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::Float32(propval) => {
|
||||
propval.store(val, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_str<S: Into<String>>(&self, val: S) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::Str(propval) => {
|
||||
let mut pv = propval.lock().unwrap();
|
||||
*pv = val.into();
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_node_id(&self, val: SceneNodeId) -> Result<()> {
|
||||
match &self.val {
|
||||
PropertyValue::SceneNodeId(propval) => {
|
||||
propval.store(val, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::PropertyWrongType),
|
||||
}
|
||||
}
|
||||
pub desc: String,
|
||||
pub typ: PropertyType,
|
||||
}
|
||||
|
||||
type SlotFn = Box<dyn Fn() + Send>;
|
||||
@@ -734,6 +571,7 @@ impl Slot {
|
||||
|
||||
pub struct Signal {
|
||||
pub name: String,
|
||||
pub fmt: Vec<CallArg>,
|
||||
slots: Vec<Slot>,
|
||||
freed: Vec<SlotId>,
|
||||
}
|
||||
@@ -768,7 +606,7 @@ type MethodResponseFn = Box<dyn Fn(Result<Vec<u8>>) + Send>;
|
||||
|
||||
pub struct Method {
|
||||
pub name: String,
|
||||
pub args: Vec<(String, PropertyType)>,
|
||||
pub result: Vec<(String, PropertyType)>,
|
||||
pub args: Vec<CallArg>,
|
||||
pub result: Vec<CallArg>,
|
||||
pub queue: Vec<(Vec<u8>, MethodResponseFn)>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user