diff --git a/paint/sources/functions.h b/paint/sources/functions.h index 9aabde8e..c3c1b13d 100644 --- a/paint/sources/functions.h +++ b/paint/sources/functions.h @@ -681,6 +681,11 @@ void rgb_node_init(); void rgb_to_bw_node_init(); void attribute_node_init(); void shader_node_init(); +void save_image_node_init(); +void save_image_node_run(ui_node_t *node, gpu_texture_t *result); +void repeat_node_init(); +void neural_node_load_result(ui_node_t *node); +void text_to_image_node_run(ui_node_t *node, void (*callback)(ui_node_t *)); void upscale_image_node_init(); void image_to_pbr_node_init(); void inpaint_image_node_init(); diff --git a/paint/sources/main.c b/paint/sources/main.c index bc102249..baeb04a7 100644 --- a/paint/sources/main.c +++ b/paint/sources/main.c @@ -86,6 +86,8 @@ #include "neural_nodes/neural_node.c" #include "neural_nodes/neural_node_models.c" #include "neural_nodes/outpaint_image_node.c" +#include "neural_nodes/repeat_node.c" +#include "neural_nodes/save_image_node.c" #include "neural_nodes/text_to_image_node.c" #include "neural_nodes/text_to_text_node.c" #include "neural_nodes/tile_image_node.c" diff --git a/paint/sources/neural_nodes/neural_node.c b/paint/sources/neural_nodes/neural_node.c index 7a1f740e..84d5a789 100644 --- a/paint/sources/neural_nodes/neural_node.c +++ b/paint/sources/neural_nodes/neural_node.c @@ -51,7 +51,7 @@ bool neural_node_button(ui_node_t *node, char *model) { if (node != neural_node_current) { ui->enabled = false; } - ui_button(tr("Processing..."), UI_ALIGN_CENTER, ""); + ui_button(tr("Running..."), UI_ALIGN_CENTER, ""); if (node != neural_node_current) { ui->enabled = true; } @@ -65,19 +65,34 @@ bool neural_node_button(ui_node_t *node, char *model) { return false; } +void neural_node_load_result(ui_node_t *node) { + char *file = string("%s%soutput.png", neural_node_dir(), PATH_SEP); + if (iron_file_exists(file)) { + gpu_texture_t *result = iron_load_texture(file); + any_imap_set(neural_node_results, node->id, result); + ui_nodes_hwnd->redraws = 2; + ui_view2d_hwnd->redraws = 2; + ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); + for (i32 i = 0; i < canvas->links->length; ++i) { + ui_node_link_t *l = canvas->links->buffer[i]; + if (l->from_id == node->id) { + ui_node_t *to_node = ui_get_node(canvas->nodes, l->to_id); + if (to_node != NULL && string_equals(to_node->type, "NEURAL_SAVE_IMAGE")) { + save_image_node_run(node, result); + break; + } + } + } + } +} + void neural_node_check_result(ui_node_t *node) { gc_unroot(neural_node_current); neural_node_current = node; gc_root(neural_node_current); iron_delay_idle_sleep(); if (iron_exec_async_done == 1) { - char *file = string("%s%soutput.png", neural_node_dir(), PATH_SEP); - if (iron_file_exists(file)) { - gpu_texture_t *result = iron_load_texture(file); - any_imap_set(neural_node_results, node->id, result); - ui_nodes_hwnd->redraws = 2; - ui_view2d_hwnd->redraws = 2; - } + neural_node_load_result(node); sys_remove_update(neural_node_check_result); } } diff --git a/paint/sources/neural_nodes/text_to_image_node.c b/paint/sources/neural_nodes/text_to_image_node.c index 8bd322e5..8df78b25 100644 --- a/paint/sources/neural_nodes/text_to_image_node.c +++ b/paint/sources/neural_nodes/text_to_image_node.c @@ -130,6 +130,35 @@ string_array_t *text_to_image_node_wan_args(char *dir, char *prompt) { return argv; } +void text_to_image_node_run(ui_node_t *node, void (*callback)(ui_node_t *)) { + char *node_name = parser_material_node_name(node, NULL); + ui_handle_t *h = ui_handle(node_name); + i32 model = ui_nest(h, 0)->i; + char *prompt = ui_nest(h, 1)->text; + char *dir = neural_node_dir(); + if (prompt == NULL || string_equals(prompt, "")) { + prompt = "."; + } + string_array_t *argv; + if (model == 0) { + argv = text_to_image_node_sd_args(dir, prompt); + } + else if (model == 1) { + argv = text_to_image_node_zimage_args(dir, prompt); + } + else if (model == 2) { + argv = text_to_image_node_qwen_args(dir, prompt); + } + else { + argv = text_to_image_node_wan_args(dir, prompt); + } + if (node->buttons->buffer[1]->default_value->buffer[0] > 0.0) { + array_insert(argv, argv->length - 1, "--circular"); + } + iron_exec_async(argv->buffer[0], argv->buffer); + sys_notify_on_update(callback, node); +} + void text_to_image_node_button(i32 node_id) { ui_node_t *node = ui_get_node(ui_nodes_get_canvas(true)->nodes, node_id); char *node_name = parser_material_node_name(node, NULL); @@ -147,45 +176,33 @@ void text_to_image_node_button(i32 node_id) { node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { - char *dir = neural_node_dir(); - - if (string_equals(prompt, "")) { - prompt = "."; - } - - string_array_t *argv; - if (model == 0) { - argv = text_to_image_node_sd_args(dir, prompt); - } - else if (model == 1) { - argv = text_to_image_node_zimage_args(dir, prompt); - } - else if (model == 2) { - argv = text_to_image_node_qwen_args(dir, prompt); - } - else { - argv = text_to_image_node_wan_args(dir, prompt); - } - - if (node->buttons->buffer[1]->default_value->buffer[0] > 0.0) { - array_insert(argv, argv->length - 1, "--circular"); - } - - iron_exec_async(argv->buffer[0], argv->buffer); - sys_notify_on_update(neural_node_check_result, node); + text_to_image_node_run(node, neural_node_check_result); } } void text_to_image_node_init() { ui_node_t *text_to_image_node_def = - GC_ALLOC_INIT(ui_node_t, {.id = 0, - .name = _tr("Text to Image"), - .type = "NEURAL_TEXT_TO_IMAGE", - .x = 0, - .y = 0, - .color = 0xff4982a0, - .inputs = any_array_create_from_raw((void *[]){}, 0), + GC_ALLOC_INIT(ui_node_t, {.id = 0, + .name = _tr("Text to Image"), + .type = "NEURAL_TEXT_TO_IMAGE", + .x = 0, + .y = 0, + .color = 0xff4982a0, + .inputs = any_array_create_from_raw( + (void *[]){ + GC_ALLOC_INIT(ui_node_socket_t, {.id = 0, + .node_id = 0, + .name = _tr("In"), + .type = "BOOL", + .color = 0xff6363c7, + .default_value = f32_array_create_xyz(0.0, 0.0, 0.0), + .min = 0.0, + .max = 1.0, + .precision = 100, + .display = 0}), + }, + 1), .outputs = any_array_create_from_raw( (void *[]){ GC_ALLOC_INIT(ui_node_socket_t, {.id = 0, diff --git a/paint/sources/nodes_material.c b/paint/sources/nodes_material.c index caefe479..114ff80c 100644 --- a/paint/sources/nodes_material.c +++ b/paint/sources/nodes_material.c @@ -93,6 +93,8 @@ void nodes_material_init() { image_to_pbr_node_init(); inpaint_image_node_init(); outpaint_image_node_init(); + repeat_node_init(); + save_image_node_init(); text_to_image_node_init(); tile_image_node_init(); upscale_image_node_init();