240 lines
12 KiB
C
240 lines
12 KiB
C
|
|
#include "../global.h"
|
|
|
|
ui_nodes_t *_nodes_material_nodes;
|
|
ui_node_t *_nodes_material_node;
|
|
ui_node_socket_t_array_t *_nodes_material_sockets;
|
|
|
|
char *group_node_vector(ui_node_t *node, ui_node_socket_t *socket) {
|
|
return parser_material_parse_group(node, socket);
|
|
}
|
|
|
|
char *group_node_value(ui_node_t *node, ui_node_socket_t *socket) {
|
|
return parser_material_parse_group(node, socket);
|
|
}
|
|
|
|
void nodes_material_new_group_button(i32 node_id) {
|
|
ui_node_t *node = ui_get_node(ui_nodes_get_canvas(true)->nodes, node_id);
|
|
if (string_equals(node->name, "New Group")) {
|
|
for (i32 i = 1; i < 999; ++i) {
|
|
node->name = string("%s %s", tr("Group"), i32_to_string(i));
|
|
bool found = false;
|
|
for (i32 i = 0; i < project_material_groups->length; ++i) {
|
|
node_group_t *g = project_material_groups->buffer[i];
|
|
char *cname = g->canvas->name;
|
|
if (string_equals(cname, node->name)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
break;
|
|
}
|
|
}
|
|
ui_node_canvas_t *canvas = GC_ALLOC_INIT(
|
|
ui_node_canvas_t,
|
|
{.name = node->name,
|
|
.nodes = any_array_create_from_raw(
|
|
(void *[]){
|
|
GC_ALLOC_INIT(ui_node_t,
|
|
{.id = 0,
|
|
.name = _tr("Group Input"),
|
|
.type = "GROUP_INPUT",
|
|
.x = 50,
|
|
.y = 200,
|
|
.color = 0xff448c6d,
|
|
.inputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.outputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.buttons = any_array_create_from_raw(
|
|
(void *[]){
|
|
GC_ALLOC_INIT(ui_node_button_t, {.name = "nodes_material_group_input_button", .type = "CUSTOM", .height = 1, .output = -1, .default_value = f32_array_create_x(0.0) }),
|
|
},
|
|
1),
|
|
.width = 0,
|
|
.flags = 0}),
|
|
GC_ALLOC_INIT(ui_node_t,
|
|
{.id = 1,
|
|
.name = _tr("Group Output"),
|
|
.type = "GROUP_OUTPUT",
|
|
.x = 450,
|
|
.y = 200,
|
|
.color = 0xff448c6d,
|
|
.inputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.outputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.buttons = any_array_create_from_raw(
|
|
(void *[]){
|
|
GC_ALLOC_INIT(ui_node_button_t, {.name = "nodes_material_group_output_button", .type = "CUSTOM", .height = 1, .output = -1, .default_value = f32_array_create_x(0.0) }),
|
|
},
|
|
1),
|
|
.width = 0,
|
|
.flags = 0}),
|
|
},
|
|
2),
|
|
.links = any_array_create_from_raw((void *[]){}, 0)});
|
|
node_group_t *ng = GC_ALLOC_INIT(node_group_t, {.canvas = canvas, .nodes = ui_nodes_create()});
|
|
any_array_push(project_material_groups, ng);
|
|
}
|
|
node_group_t *group = NULL;
|
|
for (i32 i = 0; i < project_material_groups->length; ++i) {
|
|
node_group_t *g = project_material_groups->buffer[i];
|
|
char *cname = g->canvas->name;
|
|
if (string_equals(cname, node->name)) {
|
|
group = g;
|
|
break;
|
|
}
|
|
}
|
|
if (ui_button(tr("Nodes"), UI_ALIGN_CENTER, "")) {
|
|
any_array_push(ui_nodes_group_stack, group);
|
|
}
|
|
}
|
|
|
|
void nodes_material_add_socket_menu_draw() {
|
|
ui_nodes_t *nodes = _nodes_material_nodes;
|
|
ui_node_t *node = _nodes_material_node;
|
|
ui_node_socket_t_array_t *sockets = _nodes_material_sockets;
|
|
node_group_t_array_t *group_stack = ui_nodes_group_stack;
|
|
ui_node_canvas_t *c = group_stack->buffer[group_stack->length - 1]->canvas;
|
|
if (ui_menu_button(tr("RGBA"), "", ICON_NONE)) {
|
|
any_array_push(sockets, nodes_material_create_socket(nodes, node, NULL, "RGBA", c, 0.0, 1.0, NULL));
|
|
nodes_material_sync_sockets(node);
|
|
}
|
|
if (ui_menu_button(tr("Vector"), "", ICON_NONE)) {
|
|
any_array_push(sockets, nodes_material_create_socket(nodes, node, NULL, "VECTOR", c, 0.0, 1.0, NULL));
|
|
nodes_material_sync_sockets(node);
|
|
}
|
|
if (ui_menu_button(tr("Value"), "", ICON_NONE)) {
|
|
any_array_push(sockets, nodes_material_create_socket(nodes, node, NULL, "VALUE", c, 0.0, 1.0, NULL));
|
|
nodes_material_sync_sockets(node);
|
|
}
|
|
}
|
|
|
|
void nodes_material_add_socket_button(ui_nodes_t *nodes, ui_node_t *node, ui_node_socket_t_array_t *sockets) {
|
|
if (ui_button(tr("Add"), UI_ALIGN_CENTER, "")) {
|
|
gc_unroot(_nodes_material_nodes);
|
|
_nodes_material_nodes = nodes;
|
|
gc_root(_nodes_material_nodes);
|
|
gc_unroot(_nodes_material_node);
|
|
_nodes_material_node = node;
|
|
gc_root(_nodes_material_node);
|
|
gc_unroot(_nodes_material_sockets);
|
|
_nodes_material_sockets = sockets;
|
|
gc_root(_nodes_material_sockets);
|
|
ui_menu_draw(&nodes_material_add_socket_menu_draw, -1, -1);
|
|
}
|
|
}
|
|
|
|
void nodes_material_group_input_button(i32 node_id) {
|
|
ui_nodes_t *nodes = ui_nodes_get_nodes();
|
|
ui_node_t *node = ui_get_node(ui_nodes_get_canvas(true)->nodes, node_id);
|
|
nodes_material_add_socket_button(nodes, node, node->outputs);
|
|
}
|
|
|
|
void nodes_material_group_output_button(i32 node_id) {
|
|
ui_nodes_t *nodes = ui_nodes_get_nodes();
|
|
ui_node_t *node = ui_get_node(ui_nodes_get_canvas(true)->nodes, node_id);
|
|
nodes_material_add_socket_button(nodes, node, node->inputs);
|
|
}
|
|
|
|
void nodes_material_sync_group_sockets(ui_node_canvas_t *canvas, char *group_name, ui_node_t *node) {
|
|
for (i32 i = 0; i < canvas->nodes->length; ++i) {
|
|
ui_node_t *n = canvas->nodes->buffer[i];
|
|
if (string_equals(n->type, "GROUP") && string_equals(n->name, group_name)) {
|
|
bool is_inputs = string_equals(node->name, "Group Input");
|
|
ui_node_socket_t_array_t *old_sockets = is_inputs ? n->inputs : n->outputs;
|
|
ui_node_socket_t_array_t *sockets = util_clone_canvas_sockets(is_inputs ? node->outputs : node->inputs);
|
|
if (is_inputs) {
|
|
n->inputs = sockets;
|
|
}
|
|
else {
|
|
n->outputs = sockets;
|
|
}
|
|
for (i32 i = 0; i < sockets->length; ++i) {
|
|
ui_node_socket_t *s = sockets->buffer[i];
|
|
s->node_id = n->id;
|
|
}
|
|
i32 num_sockets = sockets->length < old_sockets->length ? sockets->length : old_sockets->length;
|
|
for (i32 i = 0; i < num_sockets; ++i) {
|
|
if (sockets->buffer[i]->type == old_sockets->buffer[i]->type) {
|
|
sockets->buffer[i]->default_value = old_sockets->buffer[i]->default_value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void nodes_material_sync_sockets(ui_node_t *node) {
|
|
node_group_t_array_t *group_stack = ui_nodes_group_stack;
|
|
ui_node_canvas_t *c = group_stack->buffer[group_stack->length - 1]->canvas;
|
|
for (i32 i = 0; i < project_materials->length; ++i) {
|
|
slot_material_t *m = project_materials->buffer[i];
|
|
nodes_material_sync_group_sockets(m->canvas, c->name, node);
|
|
}
|
|
for (i32 i = 0; i < project_material_groups->length; ++i) {
|
|
node_group_t *g = project_material_groups->buffer[i];
|
|
nodes_material_sync_group_sockets(g->canvas, c->name, node);
|
|
}
|
|
}
|
|
|
|
i32 nodes_material_get_socket_color(char *type) {
|
|
return string_equals(type, "RGBA") ? 0xffc7c729 : string_equals(type, "VECTOR") ? 0xff6363c7 : 0xffa1a1a1;
|
|
}
|
|
|
|
f32_array_t *nodes_material_get_socket_default_value(char *type) {
|
|
return string_equals(type, "RGBA") ? f32_array_create_xyzw(0.8, 0.8, 0.8, 1.0)
|
|
: string_equals(type, "VECTOR") ? f32_array_create_xyz(0.0, 0.0, 0.0)
|
|
: f32_array_create_x(0.0);
|
|
}
|
|
|
|
char *nodes_material_get_socket_name(char *type) {
|
|
return string_equals(type, "RGBA") ? _tr("Color") : string_equals(type, "VECTOR") ? _tr("Vector") : _tr("Value");
|
|
}
|
|
|
|
ui_node_socket_t *nodes_material_create_socket(ui_nodes_t *nodes, ui_node_t *node, char *name, char *type, ui_node_canvas_t *canvas, f32 min, f32 max,
|
|
void *default_value) {
|
|
ui_node_socket_t *soc =
|
|
GC_ALLOC_INIT(ui_node_socket_t, {.id = ui_get_socket_id(canvas->nodes),
|
|
.node_id = node->id,
|
|
.name = name == NULL ? nodes_material_get_socket_name(type) : name,
|
|
.type = type,
|
|
.color = nodes_material_get_socket_color(type),
|
|
.default_value = default_value == NULL ? nodes_material_get_socket_default_value(type) : default_value,
|
|
.min = min,
|
|
.max = max,
|
|
.precision = 100});
|
|
return soc;
|
|
}
|
|
|
|
void group_node_init() {
|
|
|
|
ui_node_t *group_node_def = GC_ALLOC_INIT(ui_node_t, {.id = 0,
|
|
.name = _tr("New Group"),
|
|
.type = "GROUP",
|
|
.x = 0,
|
|
.y = 0,
|
|
.color = 0xffb34f5a,
|
|
.inputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.outputs = any_array_create_from_raw((void *[]){}, 0),
|
|
.buttons = any_array_create_from_raw(
|
|
(void *[]){
|
|
GC_ALLOC_INIT(ui_node_button_t, {.name = "nodes_material_new_group_button",
|
|
.type = "CUSTOM",
|
|
.output = -1,
|
|
.default_value = f32_array_create_x(0),
|
|
.data = NULL,
|
|
.min = 0.0,
|
|
.max = 1.0,
|
|
.precision = 100,
|
|
.height = 1}),
|
|
},
|
|
1),
|
|
.width = 0,
|
|
.flags = 0});
|
|
|
|
any_array_push(nodes_material_group, group_node_def);
|
|
any_map_set(parser_material_node_vectors, "GROUP", group_node_vector);
|
|
any_map_set(parser_material_node_values, "GROUP", group_node_value);
|
|
any_map_set(ui_nodes_custom_buttons, "nodes_material_new_group_button", nodes_material_new_group_button);
|
|
any_map_set(ui_nodes_custom_buttons, "nodes_material_group_input_button", nodes_material_group_input_button);
|
|
any_map_set(ui_nodes_custom_buttons, "nodes_material_group_output_button", nodes_material_group_output_button);
|
|
}
|