Added graph edition methods and exposed to script API

master
Marc Gilleron 2020-02-24 23:03:41 +00:00
parent dbca01de59
commit 815954bc03
6 changed files with 304 additions and 77 deletions

View File

@ -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<ProgramGraph::Connection> &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);
}
}
}
}

View File

@ -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<uint32_t> &node_ids) const;
void copy_from(const ProgramGraph &other);
void get_connections(std::vector<ProgramGraph::Connection> &connections) const;
void debug_print_dot_file(String file_path) const;

View File

@ -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<ProgramGraph::Connection> &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<Resource> 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<PropertyInfo> *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<ProgramGraph::Connection> 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);
}

View File

@ -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<ProgramGraph::Connection> &connections) const;
PoolIntArray get_node_ids() const;
int get_used_channels_mask() const override;
@ -65,17 +68,24 @@ public:
Ref<Resource> 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<PropertyInfo> *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 {

View File

@ -21,67 +21,82 @@ void VoxelGraphNodeDB::destroy_singleton() {
}
VoxelGraphNodeDB::VoxelGraphNodeDB() {
FixedArray<NodeType, VoxelGeneratorGraph::NODE_TYPE_COUNT> &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;
}

View File

@ -4,8 +4,7 @@
#include "voxel_generator_graph.h"
#include <core/object.h>
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<Port> inputs;
std::vector<Port> outputs;
std::vector<Param> params;
@ -35,7 +43,12 @@ public:
static void create_singleton();
static void destroy_singleton();
FixedArray<NodeType, VoxelGeneratorGraph::NODE_TYPE_COUNT> 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<NodeType, VoxelGeneratorGraph::NODE_TYPE_COUNT> _types;
};
#endif // VOXEL_GRAPH_NODE_DB_H