From 815954bc03a7d5da08c3f29b8e642e36db1c110e Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Mon, 24 Feb 2020 23:03:41 +0000 Subject: [PATCH] Added graph edition methods and exposed to script API --- generators/graph/program_graph.cpp | 23 ++- generators/graph/program_graph.h | 6 + generators/graph/voxel_generator_graph.cpp | 222 ++++++++++++++++----- generators/graph/voxel_generator_graph.h | 22 +- generators/graph/voxel_graph_node_db.cpp | 87 +++++++- generators/graph/voxel_graph_node_db.h | 21 +- 6 files changed, 304 insertions(+), 77 deletions(-) diff --git a/generators/graph/program_graph.cpp b/generators/graph/program_graph.cpp index e738b702..9adfc37a 100644 --- a/generators/graph/program_graph.cpp +++ b/generators/graph/program_graph.cpp @@ -98,11 +98,11 @@ bool ProgramGraph::is_connected(PortLocation src, PortLocation dst) const { } void ProgramGraph::connect(PortLocation src, PortLocation dst) { - CRASH_COND(is_connected(src, dst)); - CRASH_COND(has_path(dst.node_id, src.node_id)); + ERR_FAIL_COND(is_connected(src, dst)); + ERR_FAIL_COND(has_path(dst.node_id, src.node_id)); Node *src_node = get_node(src.node_id); Node *dst_node = get_node(dst.node_id); - CRASH_COND(dst_node->inputs[dst.port_index].connections.size() != 0); + ERR_FAIL_COND(dst_node->inputs[dst.port_index].connections.size() != 0); src_node->outputs[src.port_index].connections.push_back(dst); dst_node->inputs[dst.port_index].connections.push_back(src); } @@ -289,3 +289,20 @@ void ProgramGraph::copy_from(const ProgramGraph &other) { _nodes.insert(std::make_pair(node->id, node)); } } + +void ProgramGraph::get_connections(std::vector &connections) const { + for (auto it = _nodes.begin(); it != _nodes.end(); ++it) { + const Node *node = it->second; + + for (size_t i = 0; i < node->outputs.size(); ++i) { + const Port &port = node->outputs[i]; + + for (size_t j = 0; j < port.connections.size(); ++j) { + Connection con; + con.src = PortLocation{ node->id, uint32_t(i) }; + con.dst = port.connections[j]; + connections.push_back(con); + } + } + } +} diff --git a/generators/graph/program_graph.h b/generators/graph/program_graph.h index ef20b1be..9d0d92f4 100644 --- a/generators/graph/program_graph.h +++ b/generators/graph/program_graph.h @@ -15,6 +15,11 @@ public: uint32_t port_index; }; + struct Connection { + PortLocation src; + PortLocation dst; + }; + struct PortLocationHasher { static inline uint32_t hash(const PortLocation &v) { uint32_t hash = hash_djb2_one_32(v.node_id); @@ -50,6 +55,7 @@ public: void find_terminal_nodes(std::vector &node_ids) const; void copy_from(const ProgramGraph &other); + void get_connections(std::vector &connections) const; void debug_print_dot_file(String file_path) const; diff --git a/generators/graph/voxel_generator_graph.cpp b/generators/graph/voxel_generator_graph.cpp index 356e296b..9fc84f00 100644 --- a/generators/graph/voxel_generator_graph.cpp +++ b/generators/graph/voxel_generator_graph.cpp @@ -15,7 +15,7 @@ VoxelGeneratorGraph::VoxelGeneratorGraph() { _bounds.max = Vector3i(128); // TODO Remove this, it's for testing - load_waves_preset(); + debug_load_waves_preset(); compile(); } @@ -38,7 +38,7 @@ void VoxelGeneratorGraph::clear() { } uint32_t VoxelGeneratorGraph::create_node(NodeTypeID type_id) { - const VoxelGraphNodeDB::NodeType &type = VoxelGraphNodeDB::get_singleton()->types[type_id]; + const VoxelGraphNodeDB::NodeType &type = VoxelGraphNodeDB::get_singleton()->get_type(type_id); ProgramGraph::Node *pg_node = _graph.create_node(); pg_node->inputs.resize(type.inputs.size()); @@ -66,67 +66,70 @@ void VoxelGeneratorGraph::remove_node(uint32_t node_id) { } } -void VoxelGeneratorGraph::node_connect(ProgramGraph::PortLocation src, ProgramGraph::PortLocation dst) { - _graph.connect(src, dst); +void VoxelGeneratorGraph::add_connection(uint32_t src_node_id, uint32_t src_port_index, uint32_t dst_node_id, uint32_t dst_port_index) { + _graph.connect( + ProgramGraph::PortLocation{ src_node_id, src_port_index }, + ProgramGraph::PortLocation{ dst_node_id, dst_port_index }); } -void VoxelGeneratorGraph::node_set_param(uint32_t node_id, uint32_t param_index, Variant value) { +void VoxelGeneratorGraph::remove_connection(uint32_t src_node_id, uint32_t src_port_index, uint32_t dst_node_id, uint32_t dst_port_index) { + _graph.disconnect( + ProgramGraph::PortLocation{ src_node_id, src_port_index }, + ProgramGraph::PortLocation{ dst_node_id, dst_port_index }); +} + +void VoxelGeneratorGraph::set_node_param(uint32_t node_id, uint32_t param_index, Variant value) { Node **pptr = _nodes.getptr(node_id); ERR_FAIL_COND(pptr == nullptr); Node *node = *pptr; + ERR_FAIL_INDEX(param_index, node->params.size()); node->params[param_index] = value; } +Variant VoxelGeneratorGraph::get_node_param(uint32_t node_id, uint32_t param_index) const { + const Node *const *pptr = _nodes.getptr(node_id); + ERR_FAIL_COND_V(pptr == nullptr, Variant()); + const Node *node = *pptr; + ERR_FAIL_INDEX_V(param_index, node->params.size(), Variant()); + return node->params[param_index]; +} + +Vector2 VoxelGeneratorGraph::get_node_gui_position(uint32_t node_id) const { + const Node *const *pptr = _nodes.getptr(node_id); + ERR_FAIL_COND_V(pptr == nullptr, Vector2()); + const Node *node = *pptr; + return node->gui_position; +} + +void VoxelGeneratorGraph::set_node_gui_position(uint32_t node_id, Vector2 pos) { + Node **node_pptr = _nodes.getptr(node_id); + ERR_FAIL_COND(node_pptr == nullptr); + Node *node = *node_pptr; + node->gui_position = pos; +} + +void VoxelGeneratorGraph::get_connections(std::vector &connections) const { + _graph.get_connections(connections); +} + +PoolIntArray VoxelGeneratorGraph::get_node_ids() const { + PoolIntArray ids; + ids.resize(_nodes.size()); + { + PoolIntArray::Write w = ids.write(); + int i = 0; + const uint32_t *key = nullptr; + while (key = _nodes.next(key)) { + w[i++] = *key; + } + } + return ids; +} + int VoxelGeneratorGraph::get_used_channels_mask() const { return 1 << _channel; } -void VoxelGeneratorGraph::load_waves_preset() { - clear(); - // This is mostly for testing - - uint32_t n_x = create_node(NODE_INPUT_X); - uint32_t n_y = create_node(NODE_INPUT_Y); - uint32_t n_z = create_node(NODE_INPUT_Z); - uint32_t n_o = create_node(NODE_OUTPUT_SDF); - uint32_t n_sin0 = create_node(NODE_SINE); - uint32_t n_sin1 = create_node(NODE_SINE); - uint32_t n_add = create_node(NODE_ADD); - uint32_t n_mul0 = create_node(NODE_MULTIPLY); - uint32_t n_mul1 = create_node(NODE_MULTIPLY); - uint32_t n_mul2 = create_node(NODE_MULTIPLY); - uint32_t n_c0 = create_node(NODE_CONSTANT); - uint32_t n_c1 = create_node(NODE_CONSTANT); - uint32_t n_sub = create_node(NODE_SUBTRACT); - - node_set_param(n_c0, 0, 1.f / 20.f); - node_set_param(n_c1, 0, 10.f); - - /* - * X --- * --- sin Y - * / \ \ - * 1/20 + --- * --- - --- O - * \ / / - * Z --- * --- sin 10.0 - */ - - typedef ProgramGraph::PortLocation PL; - - node_connect(PL{ n_x, 0 }, PL{ n_mul0, 0 }); - node_connect(PL{ n_z, 0 }, PL{ n_mul1, 0 }); - node_connect(PL{ n_c0, 0 }, PL{ n_mul0, 1 }); - node_connect(PL{ n_c0, 0 }, PL{ n_mul1, 1 }); - node_connect(PL{ n_mul0, 0 }, PL{ n_sin0, 0 }); - node_connect(PL{ n_mul1, 0 }, PL{ n_sin1, 0 }); - node_connect(PL{ n_sin0, 0 }, PL{ n_add, 0 }); - node_connect(PL{ n_sin1, 0 }, PL{ n_add, 1 }); - node_connect(PL{ n_add, 0 }, PL{ n_mul2, 0 }); - node_connect(PL{ n_c1, 0 }, PL{ n_mul2, 1 }); - node_connect(PL{ n_y, 0 }, PL{ n_sub, 0 }); - node_connect(PL{ n_mul2, 0 }, PL{ n_sub, 1 }); - node_connect(PL{ n_sub, 0 }, PL{ n_o, 0 }); -} - void VoxelGeneratorGraph::generate_block(VoxelBlockRequest &input) { VoxelBuffer &out_buffer = **input.voxel_buffer; @@ -270,7 +273,7 @@ void VoxelGeneratorGraph::compile() { const uint32_t node_id = order[i]; const ProgramGraph::Node *pg_node = _graph.get_node(node_id); const Node *node = _nodes[node_id]; - const VoxelGraphNodeDB::NodeType &type = type_db.types[node->type]; + const VoxelGraphNodeDB::NodeType &type = type_db.get_type(node->type); CRASH_COND(node == nullptr); CRASH_COND(pg_node->inputs.size() != type.inputs.size()); @@ -924,6 +927,8 @@ Ref VoxelGeneratorGraph::duplicate(bool p_subresources) const { return d; } +// Debug land + float VoxelGeneratorGraph::debug_measure_microseconds_per_voxel() { Vector3i pos(1, 1, 1); float v; @@ -940,6 +945,52 @@ float VoxelGeneratorGraph::debug_measure_microseconds_per_voxel() { return us; } +void VoxelGeneratorGraph::debug_load_waves_preset() { + clear(); + // This is mostly for testing + + uint32_t n_x = create_node(NODE_INPUT_X); + uint32_t n_y = create_node(NODE_INPUT_Y); + uint32_t n_z = create_node(NODE_INPUT_Z); + uint32_t n_o = create_node(NODE_OUTPUT_SDF); + uint32_t n_sin0 = create_node(NODE_SINE); + uint32_t n_sin1 = create_node(NODE_SINE); + uint32_t n_add = create_node(NODE_ADD); + uint32_t n_mul0 = create_node(NODE_MULTIPLY); + uint32_t n_mul1 = create_node(NODE_MULTIPLY); + uint32_t n_mul2 = create_node(NODE_MULTIPLY); + uint32_t n_c0 = create_node(NODE_CONSTANT); + uint32_t n_c1 = create_node(NODE_CONSTANT); + uint32_t n_sub = create_node(NODE_SUBTRACT); + + set_node_param(n_c0, 0, 1.f / 20.f); + set_node_param(n_c1, 0, 10.f); + + /* + * X --- * --- sin Y + * / \ \ + * 1/20 + --- * --- - --- O + * \ / / + * Z --- * --- sin 10.0 + */ + + add_connection(n_x, 0, n_mul0, 0); + add_connection(n_z, 0, n_mul1, 0); + add_connection(n_c0, 0, n_mul0, 1); + add_connection(n_c0, 0, n_mul1, 1); + add_connection(n_mul0, 0, n_sin0, 0); + add_connection(n_mul1, 0, n_sin1, 0); + add_connection(n_sin0, 0, n_add, 0); + add_connection(n_sin1, 0, n_add, 1); + add_connection(n_add, 0, n_mul2, 0); + add_connection(n_c1, 0, n_mul2, 1); + add_connection(n_y, 0, n_sub, 0); + add_connection(n_mul2, 0, n_sub, 1); + add_connection(n_sub, 0, n_o, 0); +} + +// Binding land + bool VoxelGeneratorGraph::_set(const StringName &p_name, const Variant &p_value) { const String name = p_name; @@ -1075,10 +1126,75 @@ void VoxelGeneratorGraph::_get_property_list(List *p_list) const { } } +int VoxelGeneratorGraph::_b_get_node_type_count() const { + return VoxelGraphNodeDB::get_singleton()->get_type_count(); +} + +Dictionary VoxelGeneratorGraph::_b_get_node_type_info(int type_id) const { + return VoxelGraphNodeDB::get_singleton()->get_type_info_dict(type_id); +} + +Array VoxelGeneratorGraph::_b_get_connections() const { + Array con_array; + std::vector cons; + _graph.get_connections(cons); + con_array.resize(cons.size()); + + for (size_t i = 0; i < cons.size(); ++i) { + const ProgramGraph::Connection &con = cons[i]; + Dictionary d; + d["src_node_id"] = con.src.node_id; + d["src_port_index"] = con.src.port_index; + d["dst_node_id"] = con.dst.node_id; + d["dst_port_index"] = con.dst.port_index; + con_array[i] = d; + } + + return con_array; +} + void VoxelGeneratorGraph::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &VoxelGeneratorGraph::clear); + ClassDB::bind_method(D_METHOD("create_node", "type_id"), &VoxelGeneratorGraph::create_node); + ClassDB::bind_method(D_METHOD("remove_node", "node_id"), &VoxelGeneratorGraph::remove_node); + ClassDB::bind_method(D_METHOD("add_connection", "src_node_id", "src_port_index", "dst_node_id", "dst_port_index"), &VoxelGeneratorGraph::add_connection); + ClassDB::bind_method(D_METHOD("remove_connection", "src_node_id", "src_port_index", "dst_node_id", "dst_port_index"), &VoxelGeneratorGraph::remove_connection); + ClassDB::bind_method(D_METHOD("get_node_param", "node_id", "param_index"), &VoxelGeneratorGraph::get_node_param); + ClassDB::bind_method(D_METHOD("set_node_param", "node_id", "param_index", "value"), &VoxelGeneratorGraph::set_node_param); + ClassDB::bind_method(D_METHOD("get_node_gui_position", "node_id"), &VoxelGeneratorGraph::get_node_gui_position); + ClassDB::bind_method(D_METHOD("set_node_gui_position", "node_id", "position"), &VoxelGeneratorGraph::set_node_gui_position); + ClassDB::bind_method(D_METHOD("get_connections"), &VoxelGeneratorGraph::_b_get_connections); + ClassDB::bind_method(D_METHOD("get_node_ids"), &VoxelGeneratorGraph::get_node_ids); + ClassDB::bind_method(D_METHOD("compile"), &VoxelGeneratorGraph::compile); - ClassDB::bind_method(D_METHOD("load_waves_preset"), &VoxelGeneratorGraph::load_waves_preset); + + ClassDB::bind_method(D_METHOD("get_node_type_count"), &VoxelGeneratorGraph::_b_get_node_type_count); + ClassDB::bind_method(D_METHOD("get_node_type_info", "type_id"), &VoxelGeneratorGraph::_b_get_node_type_info); + + ClassDB::bind_method(D_METHOD("debug_load_waves_preset"), &VoxelGeneratorGraph::debug_load_waves_preset); ClassDB::bind_method(D_METHOD("debug_measure_microseconds_per_voxel"), &VoxelGeneratorGraph::debug_measure_microseconds_per_voxel); + + BIND_ENUM_CONSTANT(NODE_CONSTANT); + BIND_ENUM_CONSTANT(NODE_INPUT_X); + BIND_ENUM_CONSTANT(NODE_INPUT_Y); + BIND_ENUM_CONSTANT(NODE_INPUT_Z); + BIND_ENUM_CONSTANT(NODE_OUTPUT_SDF); + BIND_ENUM_CONSTANT(NODE_ADD); + BIND_ENUM_CONSTANT(NODE_SUBTRACT); + BIND_ENUM_CONSTANT(NODE_MULTIPLY); + BIND_ENUM_CONSTANT(NODE_SINE); + BIND_ENUM_CONSTANT(NODE_FLOOR); + BIND_ENUM_CONSTANT(NODE_ABS); + BIND_ENUM_CONSTANT(NODE_SQRT); + BIND_ENUM_CONSTANT(NODE_DISTANCE_2D); + BIND_ENUM_CONSTANT(NODE_DISTANCE_3D); + BIND_ENUM_CONSTANT(NODE_CLAMP); + BIND_ENUM_CONSTANT(NODE_MIX); + BIND_ENUM_CONSTANT(NODE_REMAP); + BIND_ENUM_CONSTANT(NODE_CURVE); + BIND_ENUM_CONSTANT(NODE_NOISE_2D); + BIND_ENUM_CONSTANT(NODE_NOISE_3D); + BIND_ENUM_CONSTANT(NODE_IMAGE_2D); + BIND_ENUM_CONSTANT(NODE_TYPE_COUNT); } diff --git a/generators/graph/voxel_generator_graph.h b/generators/graph/voxel_generator_graph.h index 0182de4b..051b7940 100644 --- a/generators/graph/voxel_generator_graph.h +++ b/generators/graph/voxel_generator_graph.h @@ -41,11 +41,14 @@ public: uint32_t create_node(NodeTypeID type_id); void remove_node(uint32_t node_id); - void node_connect(ProgramGraph::PortLocation src, ProgramGraph::PortLocation dst); - void node_set_param(uint32_t node_id, uint32_t param_index, Variant value); - - // TODO Empty preset - void load_waves_preset(); + void add_connection(uint32_t src_node_id, uint32_t src_port_index, uint32_t dst_node_id, uint32_t dst_port_index); + void remove_connection(uint32_t src_node_id, uint32_t src_port_index, uint32_t dst_node_id, uint32_t dst_port_index); + Variant get_node_param(uint32_t node_id, uint32_t param_index) const; + void set_node_param(uint32_t node_id, uint32_t param_index, Variant value); + Vector2 get_node_gui_position(uint32_t node_id) const; + void set_node_gui_position(uint32_t node_id, Vector2 pos); + void get_connections(std::vector &connections) const; + PoolIntArray get_node_ids() const; int get_used_channels_mask() const override; @@ -65,17 +68,24 @@ public: Ref duplicate(bool p_subresources) const override; + // Debug + float debug_measure_microseconds_per_voxel(); + void debug_load_waves_preset(); private: void compile(); Interval analyze_range(Vector3i min_pos, Vector3i max_pos); - void make_modified(); bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List *p_list) const; + int _b_get_node_type_count() const; + Dictionary _b_get_node_type_info(int type_id) const; + PoolIntArray _b_get_node_ids() const; + Array _b_get_connections() const; + static void _bind_methods(); struct Node { diff --git a/generators/graph/voxel_graph_node_db.cpp b/generators/graph/voxel_graph_node_db.cpp index 5d05033f..ef93d8c8 100644 --- a/generators/graph/voxel_graph_node_db.cpp +++ b/generators/graph/voxel_graph_node_db.cpp @@ -21,67 +21,82 @@ void VoxelGraphNodeDB::destroy_singleton() { } VoxelGraphNodeDB::VoxelGraphNodeDB() { + FixedArray &types = _types; + { NodeType &t = types[VoxelGeneratorGraph::NODE_CONSTANT]; + t.name = "Constant"; t.outputs.push_back(Port("Value")); - t.params.push_back(Param("Value")); + t.params.push_back(Param("Value", Variant::REAL)); } { NodeType &t = types[VoxelGeneratorGraph::NODE_INPUT_X]; + t.name = "Input X"; t.outputs.push_back(Port("Value")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_INPUT_Y]; + t.name = "Input Y"; t.outputs.push_back(Port("Value")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_INPUT_Z]; + t.name = "Input Z"; t.outputs.push_back(Port("Value")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_OUTPUT_SDF]; + t.name = "Output SDF"; t.inputs.push_back(Port("Value")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_ADD]; + t.name = "Add"; t.inputs.push_back(Port("A")); t.inputs.push_back(Port("B")); t.outputs.push_back(Port("Sum")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_SUBTRACT]; + t.name = "Subtract"; t.inputs.push_back(Port("A")); t.inputs.push_back(Port("B")); t.outputs.push_back(Port("Sum")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_MULTIPLY]; + t.name = "Multiply"; t.inputs.push_back(Port("A")); t.inputs.push_back(Port("B")); t.outputs.push_back(Port("Product")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_SINE]; + t.name = "Sine"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_FLOOR]; + t.name = "Floor"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_ABS]; + t.name = "Abs"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_SQRT]; + t.name = "Sqrt"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_DISTANCE_2D]; + t.name = "Distance 2D"; t.inputs.push_back(Port("X0")); t.inputs.push_back(Port("Y0")); t.inputs.push_back(Port("X1")); @@ -90,6 +105,7 @@ VoxelGraphNodeDB::VoxelGraphNodeDB() { } { NodeType &t = types[VoxelGeneratorGraph::NODE_DISTANCE_3D]; + t.name = "Distance 3D"; t.inputs.push_back(Port("X0")); t.inputs.push_back(Port("Y0")); t.inputs.push_back(Port("Y0")); @@ -100,13 +116,15 @@ VoxelGraphNodeDB::VoxelGraphNodeDB() { } { NodeType &t = types[VoxelGeneratorGraph::NODE_CLAMP]; + t.name = "Clamp"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Min", -1.f)); - t.params.push_back(Param("Max", 1.f)); + t.params.push_back(Param("Min", Variant::REAL, -1.f)); + t.params.push_back(Param("Max", Variant::REAL, 1.f)); } { NodeType &t = types[VoxelGeneratorGraph::NODE_MIX]; + t.name = "Mix"; t.inputs.push_back(Port("A")); t.inputs.push_back(Port("B")); t.inputs.push_back(Port("Ratio")); @@ -114,39 +132,86 @@ VoxelGraphNodeDB::VoxelGraphNodeDB() { } { NodeType &t = types[VoxelGeneratorGraph::NODE_REMAP]; + t.name = "Remap"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Min0", -1.f)); - t.params.push_back(Param("Max0", 1.f)); - t.params.push_back(Param("Min1", -1.f)); - t.params.push_back(Param("Max1", 1.f)); + t.params.push_back(Param("Min0", Variant::REAL, -1.f)); + t.params.push_back(Param("Max0", Variant::REAL, 1.f)); + t.params.push_back(Param("Min1", Variant::REAL, -1.f)); + t.params.push_back(Param("Max1", Variant::REAL, 1.f)); } { NodeType &t = types[VoxelGeneratorGraph::NODE_CURVE]; + t.name = "Curve"; t.inputs.push_back(Port("X")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Curve")); + t.params.push_back(Param("Curve", "Curve")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_NOISE_2D]; + t.name = "Noise 2D"; t.inputs.push_back(Port("X")); t.inputs.push_back(Port("Y")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Noise")); + t.params.push_back(Param("Noise", "OpenSimplexNoise")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_NOISE_3D]; + t.name = "Noise 3D"; t.inputs.push_back(Port("X")); t.inputs.push_back(Port("Y")); t.inputs.push_back(Port("Z")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Noise")); + t.params.push_back(Param("Noise", "OpenSimplexNoise")); } { NodeType &t = types[VoxelGeneratorGraph::NODE_IMAGE_2D]; + t.name = "Image"; t.inputs.push_back(Port("X")); t.inputs.push_back(Port("Y")); t.outputs.push_back(Port("Result")); - t.params.push_back(Param("Image")); + t.params.push_back(Param("Image", "Image")); } } + +Dictionary VoxelGraphNodeDB::get_type_info_dict(int id) const { + const NodeType &type = _types[id]; + + Dictionary type_dict; + type_dict["name"] = type.name; + + Array inputs; + inputs.resize(type.inputs.size()); + for (size_t i = 0; i < type.inputs.size(); ++i) { + const Port &input = type.inputs[i]; + Dictionary d; + d["name"] = input.name; + inputs[i] = d; + } + + Array outputs; + outputs.resize(type.outputs.size()); + for (size_t i = 0; i < type.outputs.size(); ++i) { + const Port &output = type.outputs[i]; + Dictionary d; + d["name"] = output.name; + outputs[i] = d; + } + + Array params; + params.resize(type.params.size()); + for (size_t i = 0; i < type.params.size(); ++i) { + const Param &p = type.params[i]; + Dictionary d; + d["name"] = p.name; + d["type"] = p.type; + d["class_name"] = p.class_name; + d["default_value"] = p.default_value; + } + + type_dict["inputs"] = inputs; + type_dict["outputs"] = outputs; + type_dict["params"] = params; + + return type_dict; +} diff --git a/generators/graph/voxel_graph_node_db.h b/generators/graph/voxel_graph_node_db.h index f248fe86..128c6aac 100644 --- a/generators/graph/voxel_graph_node_db.h +++ b/generators/graph/voxel_graph_node_db.h @@ -4,8 +4,7 @@ #include "voxel_generator_graph.h" #include -class VoxelGraphNodeDB : public Object { - GDCLASS(VoxelGraphNodeDB, Object) +class VoxelGraphNodeDB { public: struct Port { String name; @@ -17,13 +16,22 @@ public: struct Param { String name; Variant default_value; + Variant::Type type; + String class_name; - Param(String p_name, Variant p_default_value = Variant()) : + Param(String p_name, Variant::Type p_type, Variant p_default_value = Variant()) : name(p_name), + type(p_type), default_value(p_default_value) {} + + Param(String p_name, String p_class_name) : + name(p_name), + type(Variant::OBJECT), + class_name(p_class_name) {} }; struct NodeType { + String name; std::vector inputs; std::vector outputs; std::vector params; @@ -35,7 +43,12 @@ public: static void create_singleton(); static void destroy_singleton(); - FixedArray types; + int get_type_count() const { return _types.size(); } + const NodeType &get_type(int id) const { return _types[id]; } + Dictionary get_type_info_dict(int id) const; + +private: + FixedArray _types; }; #endif // VOXEL_GRAPH_NODE_DB_H