2026-03-09 13:17:15 +01:00
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
|
|
2026-03-06 12:56:38 +01:00
|
|
|
f32_array_t *util_clone_f32_array(f32_array_t *f32a) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (f32a == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
return f32_array_create_from_array(f32a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32_array_t *util_clone_u32_array(u32_array_t *u32a) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (u32a == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
return u32_array_create_from_array(u32a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8_array_t *util_clone_u8_array(u8_array_t *u8a) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (u8a == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
return u8_array_create_from_array(u8a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string_t_array_t *util_clone_string_array(string_t_array_t *a) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (a == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
string_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < a->length; ++i) {
|
2026-03-07 21:12:59 +01:00
|
|
|
char *s = a->buffer[i];
|
2026-03-06 12:56:38 +01:00
|
|
|
any_array_push(r, s);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8_array_t *util_clone_bool_array(u8_array_t *a) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (a == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
u8_array_t *r = u8_array_create_from_raw((u8[]){}, 0);
|
|
|
|
|
for (i32 i = 0; i < a->length; ++i) {
|
|
|
|
|
bool s = a->buffer[i];
|
|
|
|
|
u8_array_push(r, s);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_socket_t_array_t *util_clone_canvas_sockets(ui_node_socket_t_array_t *sockets) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (sockets == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
ui_node_socket_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < sockets->length; ++i) {
|
|
|
|
|
ui_node_socket_t *s = GC_ALLOC_INIT(ui_node_socket_t, {0});
|
|
|
|
|
s->id = sockets->buffer[i]->id;
|
|
|
|
|
s->node_id = sockets->buffer[i]->node_id;
|
|
|
|
|
s->name = string_copy(sockets->buffer[i]->name);
|
|
|
|
|
s->type = string_copy(sockets->buffer[i]->type);
|
|
|
|
|
s->color = sockets->buffer[i]->color;
|
|
|
|
|
s->default_value = util_clone_f32_array(sockets->buffer[i]->default_value);
|
|
|
|
|
s->min = sockets->buffer[i]->min;
|
|
|
|
|
s->max = sockets->buffer[i]->max;
|
|
|
|
|
s->precision = sockets->buffer[i]->precision;
|
|
|
|
|
s->display = sockets->buffer[i]->display;
|
|
|
|
|
any_array_push(r, s);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_button_t_array_t *util_clone_canvas_buttons(ui_node_button_t_array_t *buttons) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (buttons == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
ui_node_button_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < buttons->length; ++i) {
|
|
|
|
|
ui_node_button_t *b = GC_ALLOC_INIT(ui_node_button_t, {0});
|
|
|
|
|
b->name = string_copy(buttons->buffer[i]->name);
|
|
|
|
|
b->type = string_copy(buttons->buffer[i]->type);
|
|
|
|
|
b->output = buttons->buffer[i]->output;
|
|
|
|
|
b->default_value = util_clone_f32_array(buttons->buffer[i]->default_value);
|
|
|
|
|
b->data = util_clone_u8_array(buttons->buffer[i]->data);
|
|
|
|
|
b->min = buttons->buffer[i]->min;
|
|
|
|
|
b->max = buttons->buffer[i]->max;
|
|
|
|
|
b->precision = buttons->buffer[i]->precision;
|
|
|
|
|
b->height = buttons->buffer[i]->height;
|
|
|
|
|
any_array_push(r, b);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_t *util_clone_canvas_node(ui_node_t *n) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (n == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
ui_node_t *r = GC_ALLOC_INIT(ui_node_t, {0});
|
|
|
|
|
r->id = n->id;
|
|
|
|
|
r->name = string_copy(n->name);
|
|
|
|
|
r->type = string_copy(n->type);
|
|
|
|
|
r->x = n->x;
|
|
|
|
|
r->y = n->y;
|
|
|
|
|
r->color = n->color;
|
|
|
|
|
r->inputs = util_clone_canvas_sockets(n->inputs);
|
|
|
|
|
r->outputs = util_clone_canvas_sockets(n->outputs);
|
|
|
|
|
r->buttons = util_clone_canvas_buttons(n->buttons);
|
|
|
|
|
r->width = n->width;
|
|
|
|
|
r->flags = n->flags;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_t_array_t *util_clone_canvas_nodes(ui_node_t_array_t *nodes) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (nodes == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
ui_node_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < nodes->length; ++i) {
|
|
|
|
|
ui_node_t *n = util_clone_canvas_node(nodes->buffer[i]);
|
|
|
|
|
any_array_push(r, n);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_link_t_array_t *util_clone_canvas_links(ui_node_link_t_array_t *links) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (links == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
ui_node_link_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < links->length; ++i) {
|
|
|
|
|
ui_node_link_t *l = GC_ALLOC_INIT(ui_node_link_t, {0});
|
|
|
|
|
l->id = links->buffer[i]->id;
|
|
|
|
|
l->from_id = links->buffer[i]->from_id;
|
|
|
|
|
l->from_socket = links->buffer[i]->from_socket;
|
|
|
|
|
l->to_id = links->buffer[i]->to_id;
|
|
|
|
|
l->to_socket = links->buffer[i]->to_socket;
|
|
|
|
|
any_array_push(r, l);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui_node_canvas_t *util_clone_canvas(ui_node_canvas_t *c) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (c == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
ui_node_canvas_t *r = GC_ALLOC_INIT(ui_node_canvas_t, {0});
|
|
|
|
|
r->name = string_copy(c->name);
|
|
|
|
|
r->nodes = util_clone_canvas_nodes(c->nodes);
|
|
|
|
|
r->links = util_clone_canvas_links(c->links);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vertex_element_t_array_t *util_clone_vertex_elements(vertex_element_t_array_t *elems) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (elems == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
vertex_element_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < elems->length; ++i) {
|
|
|
|
|
vertex_element_t *e = GC_ALLOC_INIT(vertex_element_t, {0});
|
|
|
|
|
e->name = string_copy(elems->buffer[i]->name);
|
|
|
|
|
e->data = string_copy(elems->buffer[i]->data);
|
|
|
|
|
any_array_push(r, e);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shader_const_t_array_t *util_clone_shader_consts(shader_const_t_array_t *consts) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (consts == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
shader_const_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < consts->length; ++i) {
|
|
|
|
|
shader_const_t *s = GC_ALLOC_INIT(shader_const_t, {0});
|
|
|
|
|
s->name = string_copy(consts->buffer[i]->name);
|
|
|
|
|
s->type = string_copy(consts->buffer[i]->type);
|
|
|
|
|
s->link = string_copy(consts->buffer[i]->link);
|
|
|
|
|
any_array_push(r, s);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tex_unit_t_array_t *util_clone_tex_units(tex_unit_t_array_t *units) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (units == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
tex_unit_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < units->length; ++i) {
|
|
|
|
|
tex_unit_t *u = GC_ALLOC_INIT(tex_unit_t, {0});
|
|
|
|
|
u->name = string_copy(units->buffer[i]->name);
|
|
|
|
|
u->link = string_copy(units->buffer[i]->link);
|
|
|
|
|
any_array_push(r, u);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shader_context_t_array_t *util_clone_shader_contexts(shader_context_t_array_t *contexts) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (contexts == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
shader_context_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < contexts->length; ++i) {
|
|
|
|
|
shader_context_t *c = GC_ALLOC_INIT(shader_context_t, {0});
|
|
|
|
|
c->name = string_copy(contexts->buffer[i]->name);
|
|
|
|
|
c->depth_write = contexts->buffer[i]->depth_write;
|
|
|
|
|
c->compare_mode = string_copy(contexts->buffer[i]->compare_mode);
|
|
|
|
|
c->cull_mode = string_copy(contexts->buffer[i]->cull_mode);
|
|
|
|
|
c->vertex_shader = string_copy(contexts->buffer[i]->vertex_shader);
|
|
|
|
|
c->fragment_shader = string_copy(contexts->buffer[i]->fragment_shader);
|
|
|
|
|
c->shader_from_source = contexts->buffer[i]->shader_from_source;
|
|
|
|
|
c->blend_source = string_copy(contexts->buffer[i]->blend_source);
|
|
|
|
|
c->blend_destination = string_copy(contexts->buffer[i]->blend_destination);
|
|
|
|
|
c->alpha_blend_source = string_copy(contexts->buffer[i]->alpha_blend_source);
|
|
|
|
|
c->alpha_blend_destination = string_copy(contexts->buffer[i]->alpha_blend_destination);
|
|
|
|
|
c->color_writes_red = util_clone_bool_array(contexts->buffer[i]->color_writes_red);
|
|
|
|
|
c->color_writes_green = util_clone_bool_array(contexts->buffer[i]->color_writes_green);
|
|
|
|
|
c->color_writes_blue = util_clone_bool_array(contexts->buffer[i]->color_writes_blue);
|
|
|
|
|
c->color_writes_alpha = util_clone_bool_array(contexts->buffer[i]->color_writes_alpha);
|
|
|
|
|
c->color_attachments = util_clone_string_array(contexts->buffer[i]->color_attachments);
|
|
|
|
|
c->depth_attachment = string_copy(contexts->buffer[i]->depth_attachment);
|
|
|
|
|
c->vertex_elements = util_clone_vertex_elements(contexts->buffer[i]->vertex_elements);
|
|
|
|
|
c->constants = util_clone_shader_consts(contexts->buffer[i]->constants);
|
|
|
|
|
c->texture_units = util_clone_tex_units(contexts->buffer[i]->texture_units);
|
|
|
|
|
any_array_push(r, c);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shader_data_t *util_clone_shader_data(shader_data_t *s) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (s == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
shader_data_t *r = GC_ALLOC_INIT(shader_data_t, {0});
|
|
|
|
|
r->name = string_copy(s->name);
|
|
|
|
|
r->contexts = util_clone_shader_contexts(s->contexts);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bind_const_t_array_t *util_clone_bind_constants(bind_const_t_array_t *consts) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (consts == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
bind_const_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < consts->length; ++i) {
|
|
|
|
|
bind_const_t *c = GC_ALLOC_INIT(bind_const_t, {0});
|
|
|
|
|
c->name = string_copy(consts->buffer[i]->name);
|
|
|
|
|
c->vec = util_clone_f32_array(consts->buffer[i]->vec);
|
|
|
|
|
any_array_push(r, c);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bind_tex_t_array_t *util_clone_bind_textures(bind_tex_t_array_t *texs) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (texs == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
bind_tex_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < texs->length; ++i) {
|
|
|
|
|
bind_tex_t *t = GC_ALLOC_INIT(bind_tex_t, {0});
|
|
|
|
|
t->name = string_copy(texs->buffer[i]->name);
|
|
|
|
|
t->file = string_copy(texs->buffer[i]->file);
|
|
|
|
|
any_array_push(r, t);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
material_context_t_array_t *util_clone_material_contexts(material_context_t_array_t *contexts) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (contexts == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-03-08 08:39:29 +01:00
|
|
|
material_context_t_array_t *r = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < contexts->length; ++i) {
|
|
|
|
|
material_context_t *c = GC_ALLOC_INIT(material_context_t, {0});
|
|
|
|
|
c->name = string_copy(contexts->buffer[i]->name);
|
|
|
|
|
c->bind_constants = util_clone_bind_constants(contexts->buffer[i]->bind_constants);
|
|
|
|
|
c->bind_textures = util_clone_bind_textures(contexts->buffer[i]->bind_textures);
|
|
|
|
|
any_array_push(r, c);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
material_data_t *util_clone_material_data(material_data_t *m) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (m == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
material_data_t *r = GC_ALLOC_INIT(material_data_t, {0});
|
|
|
|
|
r->name = string_copy(m->name);
|
|
|
|
|
r->shader = string_copy(m->shader);
|
|
|
|
|
r->contexts = util_clone_material_contexts(m->contexts);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj_t *util_clone_obj(obj_t *o) {
|
2026-03-07 21:12:59 +01:00
|
|
|
if (o == NULL) {
|
|
|
|
|
return NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
obj_t *r = GC_ALLOC_INIT(obj_t, {0});
|
|
|
|
|
r->name = string_copy(o->name);
|
|
|
|
|
r->type = string_copy(o->type);
|
|
|
|
|
r->data_ref = string_copy(o->data_ref);
|
|
|
|
|
r->transform = util_clone_f32_array(o->transform);
|
|
|
|
|
r->dimensions = util_clone_f32_array(o->dimensions);
|
|
|
|
|
r->visible = o->visible;
|
|
|
|
|
r->spawn = o->spawn;
|
|
|
|
|
r->material_ref = string_copy(o->material_ref);
|
2026-03-07 21:12:59 +01:00
|
|
|
if (o->children != NULL) {
|
2026-03-08 08:39:29 +01:00
|
|
|
r->children = any_array_create_from_raw((void *[]){}, 0);
|
2026-03-06 12:56:38 +01:00
|
|
|
for (i32 i = 0; i < o->children->length; ++i) {
|
|
|
|
|
obj_t *c = util_clone_obj(o->children->buffer[i]);
|
|
|
|
|
any_array_push(r->children, c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
swatch_color_t *util_clone_swatch_color(swatch_color_t *s) {
|
|
|
|
|
swatch_color_t *r = GC_ALLOC_INIT(swatch_color_t, {0});
|
|
|
|
|
r->base = s->base;
|
|
|
|
|
r->opacity = s->opacity;
|
|
|
|
|
r->occlusion = s->occlusion;
|
|
|
|
|
r->roughness = s->roughness;
|
|
|
|
|
r->metallic = s->metallic;
|
|
|
|
|
r->normal = s->normal;
|
|
|
|
|
r->emission = s->emission;
|
|
|
|
|
r->height = s->height;
|
|
|
|
|
r->subsurface = s->subsurface;
|
|
|
|
|
return r;
|
|
|
|
|
}
|