diff --git a/base/project.js b/base/project.js index 7fcd8e6e..59ae7a21 100644 --- a/base/project.js +++ b/base/project.js @@ -1,24 +1,4 @@ -function add_gpu_backend(name) { - project.add_cfiles("sources/backends/" + name + "_gpu.*"); - project.add_define("BACKEND_GPU_H=\"backends/" + name + "_gpu.h\""); -} - -function add_sys_backend(name) { - project.add_cfiles("sources/backends/" + name + "_system.*"); - project.add_define("BACKEND_SYS_H=\"backends/" + name + "_system.h\""); -} - -function add_net_backend(name) { - project.add_cfiles("sources/backends/" + name + "_net.*"); - project.add_define("BACKEND_NET_H=\"backends/" + name + "_net.h\""); -} - -function add_thread_backend(name) { - project.add_cfiles("sources/backends/" + name + "_thread.*"); - project.add_define("BACKEND_THREAD_H=\"backends/" + name + "_thread.h\""); -} - function get_version_code() { const now = new Date(); const year = now.getFullYear().toString().slice(-2); @@ -38,7 +18,6 @@ project.add_assets("assets/*", {destination : "data/{name}"}); project.add_assets("assets/licenses/**", {destination : "data/licenses/{name}"}); project.add_assets("assets/themes/*.json", {destination : "data/themes/{name}"}); project.add_cfiles("sources/*.c"); -// project.add_cfiles("sources/iron.c"); if (platform != "wasm") { project.add_cfiles("sources/libs/gc.c"); } @@ -48,10 +27,10 @@ project.add_define("EMBED_H_PATH=\"" + os_cwd() + "/build/embed.h" + "\""); if (platform == "windows") { - add_sys_backend("windows"); - add_net_backend("windows"); - add_thread_backend("windows"); - add_gpu_backend("direct3d12"); + project.add_cfiles("sources/backends/windows_system.*"); + project.add_cfiles("sources/backends/windows_net.*"); + project.add_cfiles("sources/backends/windows_thread.*"); + project.add_cfiles("sources/backends/direct3d12_gpu.*"); project.add_define("_CRT_SECURE_NO_WARNINGS"); project.add_define("_WINSOCK_DEPRECATED_NO_WARNINGS"); project.add_define("IRON_DIRECT3D12"); @@ -73,10 +52,10 @@ if (platform == "windows") { } } else if (platform == "linux") { - add_sys_backend("linux"); - add_net_backend("posix"); - add_thread_backend("posix"); - add_gpu_backend("vulkan"); + project.add_cfiles("sources/backends/linux_system.*"); + project.add_cfiles("sources/backends/posix_net.*"); + project.add_cfiles("sources/backends/posix_thread.*"); + project.add_cfiles("sources/backends/vulkan_gpu.*"); project.add_define("IRON_VULKAN"); project.add_define("_POSIX_C_SOURCE=200809L"); project.add_lib("X11"); @@ -94,18 +73,18 @@ else if (platform == "linux") { } } else if (platform == "macos") { - add_sys_backend("macos"); - add_net_backend("apple"); - add_thread_backend("apple"); - add_gpu_backend("metal"); + project.add_cfiles("sources/backends/macos_system.*"); + project.add_cfiles("sources/backends/apple_net.*"); + project.add_cfiles("sources/backends/apple_thread.*"); + project.add_cfiles("sources/backends/metal_gpu.*"); project.add_cfiles("sources/backends/data/mac.plist"); project.add_define("IRON_METAL"); } else if (platform == "ios") { - add_sys_backend("ios"); - add_net_backend("apple"); - add_thread_backend("apple"); - add_gpu_backend("metal"); + project.add_cfiles("sources/backends/ios_system.*"); + project.add_cfiles("sources/backends/apple_net.*"); + project.add_cfiles("sources/backends/apple_thread.*"); + project.add_cfiles("sources/backends/metal_gpu.*"); project.add_cfiles("sources/backends/data/ios.plist"); project.add_cfiles("sources/backends/ios_file_dialog.m"); project.add_define("IRON_METAL"); @@ -113,9 +92,9 @@ else if (platform == "ios") { project.target_options.ios.version = get_version_code() + ""; } else if (platform == "android") { - add_sys_backend("android"); - add_thread_backend("posix"); - add_gpu_backend("vulkan"); + project.add_cfiles("sources/backends/android_system.*"); + project.add_cfiles("sources/backends/posix_thread.*"); + project.add_cfiles("sources/backends/vulkan_gpu.*"); project.add_cfiles("sources/backends/android_file_dialog.c"); project.add_cfiles("sources/backends/android_net.c"); project.add_cfiles("sources/backends/android_native_app_glue.c"); @@ -137,9 +116,9 @@ else if (platform == "android") { project.target_options.android.versionName = "1.0 alpha"; } else if (platform == "wasm") { - add_sys_backend("wasm"); - add_thread_backend("wasm"); - add_gpu_backend("webgpu"); + project.add_cfiles("sources/backends/wasm_system.*"); + project.add_cfiles("sources/backends/wasm_thread.*"); + project.add_cfiles("sources/backends/webgpu_gpu.*"); project.add_define("IRON_WASM"); project.add_define("IRON_WEBGPU"); project.add_define("NO_GC"); diff --git a/base/sources/iron_gpu.h b/base/sources/iron_gpu.h index b5d5030f..a25672e8 100644 --- a/base/sources/iron_gpu.h +++ b/base/sources/iron_gpu.h @@ -7,7 +7,15 @@ #include #include #include -#include BACKEND_GPU_H +#if defined(IRON_WINDOWS) +#include "backends/direct3d12_gpu.h" +#elif defined(IRON_MACOS) || defined(IRON_IOS) +#include "backends/metal_gpu.h" +#elif defined(IRON_WASM) +#include "backends/webgpu_gpu.h" +#else +#include "backends/vulkan_gpu.h" +#endif #define GPU_MAX_VERTEX_ELEMENTS 16 #define GPU_MAX_TEXTURES 16 diff --git a/base/sources/iron_string.c b/base/sources/iron_string.c index 2d2962ea..84490e04 100644 --- a/base/sources/iron_string.c +++ b/base/sources/iron_string.c @@ -4,6 +4,7 @@ #include #include #include +#include void *gc_alloc(size_t size); void gc_leaf(void *ptr); @@ -14,6 +15,21 @@ char *string_alloc(int size) { return r; } +char *string(char *fmt, ...) { + va_list args; + va_start(args, fmt); + + va_list args_copy; + va_copy(args_copy, args); + int len = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char *str = string_alloc(len + 1); + vsnprintf(str, len + 1, fmt, args); + va_end(args); + return str; +} + char *string_join(char *a, char *b) { char *r = string_alloc(strlen(a) + strlen(b) + 1); strcpy(r, a); diff --git a/base/sources/iron_string.h b/base/sources/iron_string.h index 2a1adaf2..bc42df4a 100644 --- a/base/sources/iron_string.h +++ b/base/sources/iron_string.h @@ -3,8 +3,10 @@ #include "iron_array.h" #include #include +#include char *string_alloc(int size); +char *string(char *fmt, ...); char *string_join(char *a, char *b); char *string_copy(char *a); int string_length(char *str); diff --git a/base/sources/iron_thread.h b/base/sources/iron_thread.h index 77cfc0e3..1ce25cc9 100644 --- a/base/sources/iron_thread.h +++ b/base/sources/iron_thread.h @@ -2,7 +2,16 @@ #include "iron_global.h" #include -#include BACKEND_THREAD_H +#if defined(IRON_WINDOWS) +#include "backends/windows_thread.h" +#elif defined(IRON_MACOS) || defined(IRON_IOS) +#include "backends/apple_thread.h" +#elif defined(IRON_WASM) +#include "backends/wasm_thread.h" +#else +#include "backends/posix_thread.h" +#endif + typedef struct iron_thread { iron_thread_impl_t impl; diff --git a/paint/sources/args.c b/paint/sources/args.c index eedb0680..a6d59651 100644 --- a/paint/sources/args.c +++ b/paint/sources/args.c @@ -5,7 +5,7 @@ void args_parse() { if (iron_get_arg_count() > 1) { args_use = true; - i32 i = 0; + i32 i = 0; while (i < iron_get_arg_count()) { // Process each arg char *current_arg = iron_get_arg(i); @@ -110,18 +110,18 @@ void args_run_on_next_frame(void *_) { // Get export preset and apply the correct one from args gc_unroot(box_export_files); - box_export_files = file_read_directory(string_join(string_join(path_data(), PATH_SEP), "export_presets")); + box_export_files = file_read_directory(string("%s%sexport_presets", path_data(), PATH_SEP)); gc_root(box_export_files); for (i32 i = 0; i < box_export_files->length; ++i) { - char *s = box_export_files->buffer[i]; + char *s = box_export_files->buffer[i]; box_export_files->buffer[i] = substring(s, 0, string_length(s) - 5); // Strip .json } - char *file = string_join(string_join("export_presets/", box_export_files->buffer[0]), ".json"); + char *file = string("export_presets/%s.json", box_export_files->buffer[0]); for (i32 i = 0; i < box_export_files->length; ++i) { char *f = box_export_files->buffer[i]; if (string_equals(f, args_export_textures_preset)) { - file = string_join(string_join("export_presets/", box_export_files->buffer[array_index_of(box_export_files, f)]), ".json"); + file = string("export_presets/%s.json", box_export_files->buffer[array_index_of(box_export_files, f)]); } } @@ -129,7 +129,7 @@ void args_run_on_next_frame(void *_) { gc_unroot(box_export_preset); box_export_preset = json_parse(sys_buffer_to_string(blob)); gc_root(box_export_preset); - data_delete_blob(string_join("export_presets/", file)); + data_delete_blob(string("export_presets/%s", file)); // Export queue sys_notify_on_next_frame(&args_run_export_queue, NULL); @@ -143,7 +143,7 @@ void args_run_on_next_frame(void *_) { if (string_equals(f, "")) { f = string_copy(tr("untitled", NULL)); } - export_mesh_run(string_join(string_join(args_export_mesh_path, PATH_SEP), f), NULL, false, true); + export_mesh_run(string("%s%s%s", args_export_mesh_path, PATH_SEP, f), NULL, false, true); } else if (args_export_material) { context_raw->write_icon_on_export = true; diff --git a/paint/sources/base.c b/paint/sources/base.c index a1178024..20b4a768 100644 --- a/paint/sources/base.c +++ b/paint/sources/base.c @@ -2,9 +2,9 @@ #include "global.h" void base_on_shutdown() { - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) project_save(false); - #endif +#endif config_save(); } @@ -54,9 +54,9 @@ void base_init() { gc_unroot(ui_files_filename); ui_files_filename = string_copy(tr("untitled", NULL)); gc_root(ui_files_filename); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) sys_title_set(tr("untitled", NULL)); - #endif +#endif // Baked font for fast startup if (string_equals(config_raw->locale, "en")) { @@ -182,9 +182,9 @@ i32 base_h() { i32 res = iron_window_height(); if (config_raw->layout == NULL) { res -= ui_header_default_h * 2 + ui_statusbar_default_h; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) res += ui_header_h; - #endif +#endif } else if (ui_base_show && res > 0) { i32 statush = config_raw->layout->buffer[LAYOUT_SIZE_STATUS_H]; @@ -445,12 +445,12 @@ void base_material_dropped() { void base_handle_drop_paths() { if (base_drop_paths->length > 0) { bool wait = false; - #if defined(IRON_LINUX) || defined(IRON_MACOS) +#if defined(IRON_LINUX) || defined(IRON_MACOS) wait = !mouse_moved; // Mouse coords not updated during drag - #endif +#endif if (!wait) { - base_drop_x = mouse_x; - base_drop_y = mouse_y; + base_drop_x = mouse_x; + base_drop_y = mouse_y; char *drop_path = array_shift(base_drop_paths); import_asset_run(drop_path, base_drop_x, base_drop_y, true, true, NULL); } @@ -578,13 +578,13 @@ void base_render(void *_) { context_raw->last_paint_vec_x = context_raw->paint_vec.x; context_raw->last_paint_vec_y = context_raw->paint_vec.y; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) // No mouse move events for touch, re-init last paint position on touch start if (!mouse_down("left")) { context_raw->last_paint_x = -1; context_raw->last_paint_y = -1; } - #endif +#endif } string_t_array_t *base_enum_texts(char *node_type) { @@ -677,7 +677,7 @@ void base_init_undo_layers() { gc_root(history_undo_layers); for (i32 i = 0; i < config_raw->undo_steps; ++i) { i32 len = history_undo_layers->length; - char *ext = string_join("_undo", i32_to_string(len)); + char *ext = string("_undo%s", i32_to_string(len)); slot_layer_t *l = slot_layer_create(ext, LAYER_SLOT_TYPE_LAYER, NULL); any_array_push(history_undo_layers, l); } @@ -738,11 +738,11 @@ tab_draw_array_t_array_t *ui_base_init_hwnd_tabs() { }, 7); - #ifdef IRON_IOS +#ifdef IRON_IOS if (config_is_iphone()) { array_splice(a2, 4, 1); // Swatches } - #endif +#endif tab_draw_array_t_array_t *r = any_array_create_from_raw((void *[]){}, 0); any_array_push(r, a0); @@ -751,7 +751,7 @@ tab_draw_array_t_array_t *ui_base_init_hwnd_tabs() { return r; } -void ui_base_init_on_next_frame(void * _) { +void ui_base_init_on_next_frame(void *_) { layers_init(); } @@ -901,11 +901,11 @@ void ui_base_menu_draw_viewport_mode() { } } -void ui_base_update_51603(void * _) { +void ui_base_update_51603(void *_) { export_texture_run(context_raw->texture_export_path, false); } -void ui_base_update(void * _) { +void ui_base_update(void *_) { ui_base_update_ui(); operator_update(); @@ -977,11 +977,11 @@ void ui_base_update(void * _) { ui_base_toggle_distract_free(); } - #ifdef IRON_LINUX +#ifdef IRON_LINUX if (operator_shortcut("alt+enter", SHORTCUT_TYPE_STARTED)) { base_toggle_fullscreen(); } - #endif +#endif bool decal_mask = context_is_decal_mask(); @@ -990,8 +990,7 @@ void ui_base_update(void * _) { operator_shortcut(any_map_get(config_keymap, "brush_opacity"), SHORTCUT_TYPE_DOWN) || operator_shortcut(any_map_get(config_keymap, "brush_angle"), SHORTCUT_TYPE_DOWN) || (decal_mask && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), any_map_get(config_keymap, "brush_radius")), - SHORTCUT_TYPE_DOWN))) { + operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius")), SHORTCUT_TYPE_DOWN))) { if (context_raw->brush_locked) { if (operator_shortcut(any_map_get(config_keymap, "brush_opacity"), SHORTCUT_TYPE_DOWN)) { context_raw->brush_opacity += mouse_movement_x / (float)500; @@ -1008,9 +1007,8 @@ void ui_base_update(void * _) { context_raw->brush_angle_handle->f = context_raw->brush_angle; make_material_parse_paint_material(true); } - else if (decal_mask && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), any_map_get(config_keymap, "brush_radius")), - SHORTCUT_TYPE_DOWN)) { + else if (decal_mask && operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius")), + SHORTCUT_TYPE_DOWN)) { context_raw->brush_decal_mask_radius += mouse_movement_x / (float)150; context_raw->brush_decal_mask_radius = math_max(0.01, math_min(4.0, context_raw->brush_decal_mask_radius)); context_raw->brush_decal_mask_radius = math_round(context_raw->brush_decal_mask_radius * 100) / (float)100; @@ -1032,7 +1030,7 @@ void ui_base_update(void * _) { if (operator_shortcut(any_map_get(config_keymap, "select_material"), SHORTCUT_TYPE_DOWN)) { ui_base_hwnds->buffer[TAB_AREA_SIDEBAR1]->redraws = 2; for (i32 i = 1; i < 10; ++i) { - if (keyboard_started(string_join(i32_to_string(i), ""))) { + if (keyboard_started(i32_to_string(i))) { context_select_material(i - 1); } } @@ -1040,7 +1038,7 @@ void ui_base_update(void * _) { else if (operator_shortcut(any_map_get(config_keymap, "select_layer"), SHORTCUT_TYPE_DOWN)) { ui_base_hwnds->buffer[TAB_AREA_SIDEBAR0]->redraws = 2; for (i32 i = 1; i < 10; ++i) { - if (keyboard_started(string_join(i32_to_string(i), ""))) { + if (keyboard_started(i32_to_string(i))) { context_select_layer(i - 1); } } @@ -1105,9 +1103,8 @@ void ui_base_update(void * _) { if (operator_shortcut(any_map_get(config_keymap, "brush_radius"), SHORTCUT_TYPE_STARTED) || operator_shortcut(any_map_get(config_keymap, "brush_opacity"), SHORTCUT_TYPE_STARTED) || operator_shortcut(any_map_get(config_keymap, "brush_angle"), SHORTCUT_TYPE_STARTED) || - (decal_mask && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), any_map_get(config_keymap, "brush_radius")), - SHORTCUT_TYPE_STARTED))) { + (decal_mask && operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius")), + SHORTCUT_TYPE_STARTED))) { context_raw->brush_locked = true; if (!pen_connected) { iron_mouse_lock(); @@ -1126,16 +1123,14 @@ void ui_base_update(void * _) { ui_header_handle->redraws = 2; } else if (decal_mask) { - if (operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), - any_map_get(config_keymap, "brush_radius_decrease")), + if (operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius_decrease")), SHORTCUT_TYPE_REPEAT)) { context_raw->brush_decal_mask_radius -= ui_base_get_radius_increment(); context_raw->brush_decal_mask_radius = math_max(math_round(context_raw->brush_decal_mask_radius * 100) / (float)100, 0.01); context_raw->brush_decal_mask_radius_handle->f = context_raw->brush_decal_mask_radius; ui_header_handle->redraws = 2; } - else if (operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), - any_map_get(config_keymap, "brush_radius_increase")), + else if (operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius_increase")), SHORTCUT_TYPE_REPEAT)) { context_raw->brush_decal_mask_radius += ui_base_get_radius_increment(); context_raw->brush_decal_mask_radius = math_round(context_raw->brush_decal_mask_radius * 100) / (float)100; @@ -1210,9 +1205,8 @@ void ui_base_update(void * _) { bool b = context_raw->brush_locked && !operator_shortcut(any_map_get(config_keymap, "brush_radius"), SHORTCUT_TYPE_DOWN) && !operator_shortcut(any_map_get(config_keymap, "brush_opacity"), SHORTCUT_TYPE_DOWN) && !operator_shortcut(any_map_get(config_keymap, "brush_angle"), SHORTCUT_TYPE_DOWN) && - !(decal_mask && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), any_map_get(config_keymap, "brush_radius")), - SHORTCUT_TYPE_DOWN)); + !(decal_mask && operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "brush_radius")), + SHORTCUT_TYPE_DOWN)); if (b) { iron_mouse_unlock(); context_raw->last_paint_x = -1; @@ -1325,7 +1319,7 @@ void ui_base_update(void * _) { context_raw->particle_timer = tween_timer(5, &mesh_object_remove, mo); } - #ifdef arm_physics +#ifdef arm_physics physics_pair_t_array_t *pairs = physics_world_get_contact_pairs(world, context_raw->paint_body); if (pairs != NULL) { @@ -1342,7 +1336,7 @@ void ui_base_update(void * _) { } } - #endif +#endif } } @@ -1359,7 +1353,7 @@ void ui_base_view_top() { void ui_base_operator_search_menu_draw() { ui_menu_h = UI_ELEMENT_H() * 8; ui_handle_t *search_handle = ui_handle(__ID__); - char *search = ui_text_input(search_handle, "", UI_ALIGN_LEFT, true, true); + char *search = ui_text_input(search_handle, "", UI_ALIGN_LEFT, true, true); ui->changed = false; if (_ui_base_operator_search_first) { _ui_base_operator_search_first = false; @@ -1379,11 +1373,11 @@ void ui_base_operator_search_menu_draw() { ui_base_operator_search_offset--; } } - bool enter = keyboard_down("enter"); - i32 count = 0; - i32 BUTTON_COL = ui->ops->theme->BUTTON_COL; + bool enter = keyboard_down("enter"); + i32 count = 0; + i32 BUTTON_COL = ui->ops->theme->BUTTON_COL; - string_t_array_t *keys = map_keys(config_keymap); + string_t_array_t *keys = map_keys(config_keymap); for (i32 i = 0; i < keys->length; ++i) { char *n = keys->buffer[i]; if (string_index_of(n, search) >= 0) { @@ -1436,7 +1430,7 @@ rect_t *ui_base_get_brush_stencil_rect() { return r; } -void ui_base_update_ui_on_next_frame(void * _) { +void ui_base_update_ui_on_next_frame(void *_) { layers_update_fill_layer(true); make_material_parse_paint_material(false); } @@ -1464,14 +1458,14 @@ void ui_base_update_ui() { ui_base_action_paint_remap = string_copy(paint_key); gc_root(ui_base_action_paint_remap); util_render_pick_pos_nor_tex(); - bool is_mesh = math_abs(context_raw->posx_picked) < 50 && math_abs(context_raw->posy_picked) < 50 && math_abs(context_raw->posz_picked) < 50; - #ifdef IRON_ANDROID + bool is_mesh = math_abs(context_raw->posx_picked) < 50 && math_abs(context_raw->posy_picked) < 50 && math_abs(context_raw->posz_picked) < 50; +#ifdef IRON_ANDROID // Allow rotating with both pen and touch, because hovering a pen prevents touch input on android bool pen_only = false; - #else +#else bool pen_only = context_raw->pen_painting_only; - #endif - bool is_pen = pen_only && pen_down("tip"); +#endif + bool is_pen = pen_only && pen_down("tip"); // Mesh picked - disable rotate // Pen painting only - rotate with touch, paint with pen if ((is_mesh && !pen_only) || is_pen) { @@ -1543,14 +1537,12 @@ void ui_base_update_ui() { } bool set_clone_source = context_raw->tool == TOOL_TYPE_CLONE && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "set_clone_source"), "+"), any_map_get(config_keymap, "action_paint")), - SHORTCUT_TYPE_DOWN); + operator_shortcut(string("%s+%s", any_map_get(config_keymap, "set_clone_source"), any_map_get(config_keymap, "action_paint")), SHORTCUT_TYPE_DOWN); bool decal_mask = context_is_decal_mask_paint(); - bool down = operator_shortcut(any_map_get(config_keymap, "action_paint"), SHORTCUT_TYPE_DOWN) || decal_mask || set_clone_source || - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "brush_ruler"), "+"), any_map_get(config_keymap, "action_paint")), - SHORTCUT_TYPE_DOWN) || + bool down = operator_shortcut(any_map_get(config_keymap, "action_paint"), SHORTCUT_TYPE_DOWN) || decal_mask || set_clone_source || + operator_shortcut(string("%s+%s", any_map_get(config_keymap, "brush_ruler"), any_map_get(config_keymap, "action_paint")), SHORTCUT_TYPE_DOWN) || (pen_down("tip") && !keyboard_down("alt")); if (config_raw->touch_ui) { @@ -1586,7 +1578,7 @@ void ui_base_update_ui() { if (context_raw->brush_time == 0 && !base_is_dragging && !base_is_resizing && ui->combo_selected_handle == NULL) { // Paint started // Draw line - if (operator_shortcut(string_join(string_join(any_map_get(config_keymap, "brush_ruler"), "+"), any_map_get(config_keymap, "action_paint")), + if (operator_shortcut(string("%s+%s", any_map_get(config_keymap, "brush_ruler"), any_map_get(config_keymap, "action_paint")), SHORTCUT_TYPE_DOWN)) { context_raw->last_paint_vec_x = context_raw->last_paint_x; context_raw->last_paint_vec_y = context_raw->last_paint_y; @@ -1613,11 +1605,11 @@ void ui_base_update_ui() { } } else if (context_raw->brush_time > 0) { // Brush released - context_raw->brush_time = 0; - context_raw->prev_paint_vec_x = -1; - context_raw->prev_paint_vec_y = -1; + context_raw->brush_time = 0; + context_raw->prev_paint_vec_x = -1; + context_raw->prev_paint_vec_y = -1; // context_raw->ddirty = 3; // Keep accumulated samples for D3D12 - context_raw->brush_blend_dirty = true; // Update brush mask + context_raw->brush_blend_dirty = true; // Update brush mask context_raw->layer_preview_dirty = true; // Update layer preview @@ -1657,9 +1649,9 @@ void ui_base_update_ui() { context_raw->layer_preview_dirty = false; context_raw->mask_preview_last = NULL; // Update layer preview - slot_layer_t *l = context_raw->layer; + slot_layer_t *l = context_raw->layer; - gpu_texture_t *target = l->texpaint_preview; + gpu_texture_t *target = l->texpaint_preview; if (target != NULL) { gpu_texture_t *source = l->texpaint; @@ -1704,7 +1696,7 @@ void ui_base_update_ui() { gizmo_update(); } -void ui_base_render(void * _) { +void ui_base_render(void *_) { if (!ui_base_show && config_raw->touch_ui) { ui->input_enabled = true; ui_begin(ui); @@ -1753,7 +1745,7 @@ void ui_base_render(void * _) { ui->input_enabled = true; } -void ui_base_render_cursor(void * _) { +void ui_base_render_cursor(void *_) { if (!base_ui_enabled) { return; } diff --git a/paint/sources/box_export.c b/paint/sources/box_export.c index adeb59f2..9045fa05 100644 --- a/paint/sources/box_export.c +++ b/paint/sources/box_export.c @@ -15,9 +15,9 @@ void box_export_show_textures_box() { box_export_tab_presets(); box_export_tab_atlases(); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) box_export_tab_export_mesh(box_export_htab); - #endif +#endif } void box_export_show_textures() { @@ -42,19 +42,19 @@ void box_export_show_bake_material() { ui_box_show_custom(&box_export_show_bake_material_box, 600, 400, NULL, true, tr("Export", NULL)); } -void box_export_tab_export_textures_run(void * _) { +void box_export_tab_export_textures_run(void *_) { export_texture_run(context_raw->texture_export_path, _box_export_bake_material); } void box_export_tab_export_textures_path_picked(char *path) { context_raw->texture_export_path = string_copy(path); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) console_toast(tr("Exporting textures", NULL)); - #endif +#endif sys_notify_on_next_frame(&box_export_tab_export_textures_run, NULL); } -void box_export_tab_export_textures_on_next_frame(void * _) { +void box_export_tab_export_textures_on_next_frame(void *_) { layers_set_bits(); } @@ -64,7 +64,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { ui_row2(); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) string_t_array_t *base_res_combo = any_array_create_from_raw( (void *[]){ "128", @@ -75,7 +75,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { "4096", }, 6); - #else +#else string_t_array_t *base_res_combo = any_array_create_from_raw( (void *[]){ "128", @@ -88,20 +88,20 @@ void box_export_tab_export_textures(char *title, bool bake_material) { "16384", }, 8); - #endif +#endif ui_combo(base_res_handle, base_res_combo, tr("Resolution", NULL), true, UI_ALIGN_LEFT, true); if (base_res_handle->changed) { layers_on_resized(); } - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) string_t_array_t *base_bits_combo = any_array_create_from_raw( (void *[]){ "8bit", }, 1); - #else +#else string_t_array_t *base_bits_combo = any_array_create_from_raw( (void *[]){ "8bit", @@ -109,7 +109,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { "32bit", }, 3); - #endif +#endif ui_combo(base_bits_handle, base_bits_combo, tr("Color", NULL), true, UI_ALIGN_LEFT, true); if (base_bits_handle->changed) { @@ -143,7 +143,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { context_raw->format_type = ui_combo(h, format_combo, tr("Format", NULL), true, UI_ALIGN_LEFT, true); } - ui->enabled = context_raw->format_type == TEXTURE_LDR_FORMAT_JPG && base_bits_handle->i == TEXTURE_BITS_BITS8; + ui->enabled = context_raw->format_type == TEXTURE_LDR_FORMAT_JPG && base_bits_handle->i == TEXTURE_BITS_BITS8; ui_handle_t *h_quality = ui_handle(__ID__); if (h_quality->init) { @@ -151,7 +151,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { } context_raw->format_quality = ui_slider(h_quality, tr("Quality", NULL), 0.0, 100.0, true, 1, true, UI_ALIGN_RIGHT, true); - ui->enabled = true; + ui->enabled = true; ui_row2(); ui->enabled = !bake_material; @@ -174,8 +174,8 @@ void box_export_tab_export_textures(char *title, bool bake_material) { box_export_preset = NULL; } - ui_handle_t *layers_destination_handle = ui_handle(__ID__); - layers_destination_handle->i = context_raw->layers_destination; + ui_handle_t *layers_destination_handle = ui_handle(__ID__); + layers_destination_handle->i = context_raw->layers_destination; string_t_array_t *layers_destination_combo = any_array_create_from_raw( (void *[]){ @@ -206,7 +206,7 @@ void box_export_tab_export_textures(char *title, bool bake_material) { } if (ui->is_hovered) { char *key = any_map_get(config_keymap, "file_export_textures"); - char *tip = string_join(string_join(string_join(tr("Export texture files", NULL), " ("), key), ")"); + char *tip = string("%s (%s)", tr("Export texture files", NULL), key); ui_tooltip(tip); } } @@ -223,13 +223,13 @@ void box_export_tab_presets_import(char *path) { path = string_copy(to_lower_case(path)); if (ends_with(path, ".json")) { char *filename = substring(path, string_last_index_of(path, PATH_SEP) + 1, string_length(path)); - char *dst_path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "export_presets"), PATH_SEP), filename); + char *dst_path = string("%s%sexport_presets%s%s", path_data(), PATH_SEP, PATH_SEP, filename); file_copy(path, dst_path); // Copy to presets folder box_export_fetch_presets(); gc_unroot(box_export_preset); box_export_preset = NULL; box_export_hpreset->i = char_ptr_array_index_of(box_export_files, substring(filename, 0, string_length(filename) - 5)); // Strip .json - console_info(string_join(string_join(tr("Preset imported:", NULL), " "), filename)); + console_info(string("%s %s", tr("Preset imported:", NULL), filename)); } else { console_error(strings_unknown_asset_format()); @@ -389,7 +389,7 @@ void box_export_tab_atlases() { for (i32 i = 0; i < project_paint_objects->length; ++i) { i32_array_push(project_atlas_objects, 0); i32 i1 = i + 1; - any_array_push(project_atlas_names, string_join(string_join(tr("Atlas", NULL), " "), i32_to_string(i1))); + any_array_push(project_atlas_names, string("%s %s", tr("Atlas", NULL), i32_to_string(i1))); } } for (i32 i = 0; i < project_paint_objects->length; ++i) { @@ -413,17 +413,17 @@ void box_export_show_mesh() { } void box_export_tab_export_mesh_path_picked(char *path) { - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) char *f = sys_title(); - #else +#else char *f = ui_files_filename; - #endif +#endif if (string_equals(f, "")) { f = string_copy(tr("untitled", NULL)); } - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) console_toast(tr("Exporting mesh", NULL)); - #endif +#endif mesh_object_t_array_t *paint_objects; if (box_export_mesh_handle->i == 0) { @@ -437,7 +437,7 @@ void box_export_tab_export_mesh_path_picked(char *path) { }, 1); } - export_mesh_run(string_join(string_join(path, PATH_SEP), f), paint_objects, _box_export_apply_displacement, _box_export_merge_vertices); + export_mesh_run(string("%s%s%s", path, PATH_SEP, f), paint_objects, _box_export_apply_displacement, _box_export_merge_vertices); } void box_export_tab_export_mesh(ui_handle_t *htab) { @@ -458,27 +458,27 @@ void box_export_tab_export_mesh(ui_handle_t *htab) { 2); context_raw->export_mesh_format = ui_combo(h_export_mesh_format, export_mesh_format_combo, tr("Format", NULL), true, UI_ALIGN_LEFT, true); - string_t_array_t *ar = any_array_create_from_raw( - (void *[]){ - tr("All", NULL), - }, - 1); + string_t_array_t *ar = any_array_create_from_raw( + (void *[]){ + tr("All", NULL), + }, + 1); for (i32 i = 0; i < project_paint_objects->length; ++i) { mesh_object_t *p = project_paint_objects->buffer[i]; any_array_push(ar, p->base->name); } ui_combo(box_export_mesh_handle, ar, tr("Meshes", NULL), true, UI_ALIGN_LEFT, true); - bool apply_displacement = ui_check(ui_handle(__ID__), tr("Apply Displacement", NULL), ""); + bool apply_displacement = ui_check(ui_handle(__ID__), tr("Apply Displacement", NULL), ""); - ui_handle_t *hmerge = ui_handle(__ID__); + ui_handle_t *hmerge = ui_handle(__ID__); if (hmerge->init) { hmerge->b = true; } - bool merge_vertices = ui_check(hmerge, tr("Merge Shared Vertices", NULL), ""); + bool merge_vertices = ui_check(hmerge, tr("Merge Shared Vertices", NULL), ""); - i32 tris = 0; - i32 pos = box_export_mesh_handle->i; + i32 tris = 0; + i32 pos = box_export_mesh_handle->i; mesh_object_t_array_t *paint_objects; if (pos == 0) { paint_objects = project_paint_objects; @@ -495,7 +495,7 @@ void box_export_tab_export_mesh(ui_handle_t *htab) { mesh_object_t *po = paint_objects->buffer[i]; tris += math_floor(po->data->index_array->length / (float)3); } - ui_text(string_join(string_join(i32_to_string(tris), " "), tr("triangles", NULL)), UI_ALIGN_LEFT, 0x00000000); + ui_text(string("%s %s", i32_to_string(tris), tr("triangles", NULL)), UI_ALIGN_LEFT, 0x00000000); ui_row2(); if (ui_icon_button(tr("Cancel", NULL), ICON_CLOSE, UI_ALIGN_CENTER)) { @@ -519,7 +519,7 @@ void box_export_show_material_export(char *path) { if (string_equals(f, "")) { f = string_copy(tr("untitled", NULL)); } - sys_notify_on_next_frame(&box_export_show_material_export_on_next_frame, string_join(string_join(path, PATH_SEP), f)); + sys_notify_on_next_frame(&box_export_show_material_export_on_next_frame, string("%s%s%s", path, PATH_SEP, f)); } void box_export_show_material_box() { @@ -555,7 +555,7 @@ void box_export_show_brush_export(char *path) { char *f = ui_files_filename; if (string_equals(f, "")) f = string_copy(tr("untitled", NULL)); - sys_notify_on_next_frame(&box_export_show_brush_export_on_next_frame, string_join(string_join(path, PATH_SEP), f)); + sys_notify_on_next_frame(&box_export_show_brush_export_on_next_frame, string("%s%s%s", path, PATH_SEP, f)); } void box_export_show_brush_box() { @@ -585,16 +585,16 @@ void box_export_show_brush() { void box_export_fetch_presets() { gc_unroot(box_export_files); - box_export_files = file_read_directory(string_join(string_join(path_data(), PATH_SEP), "export_presets")); + box_export_files = file_read_directory(string("%s%sexport_presets", path_data(), PATH_SEP)); gc_root(box_export_files); for (i32 i = 0; i < box_export_files->length; ++i) { - char *s = box_export_files->buffer[i]; + char *s = box_export_files->buffer[i]; box_export_files->buffer[i] = substring(s, 0, string_length(s) - 5); // Strip .json } } void box_export_parse_preset() { - char *file = string_join(string_join("export_presets/", box_export_files->buffer[box_export_hpreset->i]), ".json"); + char *file = string("export_presets/%s.json", box_export_files->buffer[box_export_hpreset->i]); buffer_t *blob = data_get_blob(file); gc_unroot(box_export_preset); box_export_preset = json_parse(sys_buffer_to_string(blob)); @@ -610,9 +610,9 @@ void box_export_new_preset(char *name) { }\ "; if (!ends_with(name, ".json")) { - name = string_join(name, ".json"); + name = string("%s.json", name); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "export_presets"), PATH_SEP), name); + char *path = string("%s%sexport_presets%s%s", path_data(), PATH_SEP, PATH_SEP, name); iron_file_save_bytes(path, sys_string_to_buffer(template), 0); } @@ -621,7 +621,7 @@ void box_export_save_preset() { if (string_equals(name, "generic")) { return; // generic is const } - char *path = string_join(string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "export_presets"), PATH_SEP), name), ".json"); + char *path = string("%s%sexport_presets%s%s.json", path_data(), PATH_SEP, PATH_SEP, name); iron_file_save_bytes(path, sys_string_to_buffer(box_export_preset_to_json(box_export_preset)), 0); } diff --git a/paint/sources/box_preferences.c b/paint/sources/box_preferences.c index 1efb4e56..812f3da2 100644 --- a/paint/sources/box_preferences.c +++ b/paint/sources/box_preferences.c @@ -168,10 +168,9 @@ void box_preferences_theme_tab_theme_field_menu() { } void box_preferences_theme_tab_export(char *path) { - path = string_join(path, PATH_SEP); - path = string_join(path, ui_files_filename); + path = string("%s%s%s", path, PATH_SEP, ui_files_filename); if (!ends_with(path, ".json")) { - path = string_join(path, ".json"); + path = string("%s.json", path); } iron_file_save_bytes(path, sys_string_to_buffer(box_preferences_theme_to_json(base_theme)), 0); } @@ -190,9 +189,9 @@ void box_preferences_theme_tab_new_box() { if (ui_icon_button(tr("OK", NULL), ICON_CHECK, UI_ALIGN_CENTER) || ui->is_return_down) { char *template = box_preferences_theme_to_json(base_theme); if (!ends_with(theme_name, ".json")) { - theme_name = string_join(theme_name, ".json"); + theme_name = string("%s.json", theme_name); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "themes"), PATH_SEP), theme_name); + char *path = string("%s%sthemes%s%s", path_data(), PATH_SEP, PATH_SEP, theme_name); iron_file_save_bytes(path, sys_string_to_buffer(template), 0); box_preferences_fetch_themes(); // Refresh file list config_raw->theme = string_copy(theme_name); @@ -217,7 +216,7 @@ void box_preferences_theme_tab() { box_preferences_h_theme->i = box_preferences_get_theme_index(); ui_combo(box_preferences_h_theme, box_preferences_themes, tr("Theme", NULL), false, UI_ALIGN_LEFT, true); if (box_preferences_h_theme->changed) { - config_raw->theme = string_join(box_preferences_themes->buffer[box_preferences_h_theme->i], ".json"); + config_raw->theme = string("%s.json", box_preferences_themes->buffer[box_preferences_h_theme->i]); config_load_theme(config_raw->theme, true); } @@ -318,7 +317,7 @@ void box_preferences_usage_tab() { if (history_undo_layers != NULL) { while (history_undo_layers->length < config_raw->undo_steps) { i32 len = history_undo_layers->length; - slot_layer_t *l = slot_layer_create(string_join("_undo", i32_to_string(len)), LAYER_SLOT_TYPE_LAYER, NULL); + slot_layer_t *l = slot_layer_create(string("_undo%s", i32_to_string(len)), LAYER_SLOT_TYPE_LAYER, NULL); any_array_push(history_undo_layers, l); } while (history_undo_layers->length > config_raw->undo_steps) { @@ -506,8 +505,7 @@ void box_preferences_pen_tab() { if (ui_icon_button(tr("Help", NULL), ICON_LINK, UI_ALIGN_CENTER)) { char *url = "https://github.com/armory3d/"; char *name = to_lower_case(manifest_title); - url = string_join(url, name); - url = string_join(url, "_docs#pen"); + url = string("%s%s_docs#pen", url, name); iron_load_url(url); } } @@ -626,11 +624,11 @@ void box_preferences_viewport_tab() { void box_preferences_keymap_tab_export(char *dest) { if (!ends_with(ui_files_filename, ".json")) { gc_unroot(ui_files_filename); - ui_files_filename = string_join(ui_files_filename, ".json"); + ui_files_filename = string("%s.json", ui_files_filename); gc_root(ui_files_filename); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "keymap_presets"), PATH_SEP), config_raw->keymap); - file_copy(path, string_join(string_join(dest, PATH_SEP), ui_files_filename)); + char *path = string("%s%skeymap_presets%s%s", path_data(), PATH_SEP, PATH_SEP, config_raw->keymap); + file_copy(path, string("%s%s%s", dest, PATH_SEP, ui_files_filename)); } void box_preferences_keymap_tab_import(char *path) { @@ -647,9 +645,9 @@ void box_preferences_keymap_tab_new_box() { if (ui_icon_button(tr("OK", NULL), ICON_CHECK, UI_ALIGN_CENTER) || ui->is_return_down) { char *template = keymap_to_json(keymap_get_default()); if (!ends_with(keymap_name, ".json")) { - keymap_name = string_join(keymap_name, ".json"); + keymap_name = string("%s.json", keymap_name); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "keymap_presets"), PATH_SEP), keymap_name); + char *path = string("%s%skeymap_presets%s%s", path_data(), PATH_SEP, PATH_SEP, keymap_name); iron_file_save_bytes(path, sys_string_to_buffer(template), 0); box_preferences_fetch_keymaps(); // Refresh file list config_raw->keymap = string_copy(keymap_name); @@ -674,7 +672,7 @@ void box_preferences_keymap_tab() { box_preferences_h_preset->i = box_preferences_get_preset_index(); ui_combo(box_preferences_h_preset, box_preferences_files_keymap, tr("Preset", NULL), false, UI_ALIGN_LEFT, true); if (box_preferences_h_preset->changed) { - config_raw->keymap = string_join(box_preferences_files_keymap->buffer[box_preferences_h_preset->i], ".json"); + config_raw->keymap = string("%s.json", box_preferences_files_keymap->buffer[box_preferences_h_preset->i]); config_apply(); keymap_load(); } @@ -762,7 +760,7 @@ void box_preferences_neural_tab() { } bool box_preferences_model_exists(char *file_name) { - return iron_file_exists(string_join(string_join(neural_node_dir(), PATH_SEP), file_name)); + return iron_file_exists(string("%s%s%s", neural_node_dir(), PATH_SEP, file_name)); } char *box_preferences_file_name_from_url(char *url) { @@ -784,12 +782,11 @@ char *box_preferneces_model_url_from_name(char *name) { void box_preferences_model_panel(neural_node_model_t *m) { if (ui_panel(ui_handle(m->name), m->name, false, true, false)) { - if (ui_text(string_join(string_join(string_join(string_join(string_join(tr("source", NULL), ": "), m->web), " ("), m->license), ")"), UI_ALIGN_LEFT, - 0x00000000) == UI_STATE_RELEASED) { + if (ui_text(string("%s: %s (%s)", tr("source", NULL), m->web, m->license), UI_ALIGN_LEFT, 0x00000000) == UI_STATE_RELEASED) { iron_load_url(m->web); } - ui_text(string_join(string_join(tr("gpu memory", NULL), ": "), m->memory), UI_ALIGN_LEFT, 0x00000000); - ui_text(string_join(string_join(tr("nodes", NULL), ": "), m->nodes), UI_ALIGN_LEFT, 0x00000000); + ui_text(string("%s: %s", tr("gpu memory", NULL), m->memory), UI_ALIGN_LEFT, 0x00000000); + ui_text(string("%s: %s", tr("nodes", NULL), m->nodes), UI_ALIGN_LEFT, 0x00000000); char *url = m->urls->buffer[0]; char *file_name = box_preferences_file_name_from_url(url); @@ -801,7 +798,7 @@ void box_preferences_model_panel(neural_node_model_t *m) { u64 u = iron_net_bytes_downloaded; i32 i = (u / (float)1000000000) * 100; f32 f = i / (float)100; - char *downloaded = string_join(f32_to_string(f), "GB"); + char *downloaded = string("%sGB", f32_to_string(f)); ui_box_hwnd->redraws = 2; box_preferences_htab->redraws = 2; iron_delay_idle_sleep(); @@ -811,21 +808,21 @@ void box_preferences_model_panel(neural_node_model_t *m) { ui_handle_t *h = ui_handle(__ID__); h->f = f / (float)parse_float(m->size); - ui_slider(h, string_join(string_join(downloaded, " / "), m->size), 0.0, 1.0, true, 100, false, UI_ALIGN_CENTER, true); + ui_slider(h, string("%s / %s", downloaded, m->size), 0.0, 1.0, true, 100, false, UI_ALIGN_CENTER, true); ui->ops->theme->BUTTON_COL = _BUTTON_COL; ui->enabled = true; } - else if (!found && ui_icon_button(string_join(string_join(string_join(tr("Download", NULL), " ("), m->size), ")"), ICON_ARROW_DOWN, UI_ALIGN_CENTER)) { + else if (!found && ui_icon_button(string("%s (%s)", tr("Download", NULL), m->size), ICON_ARROW_DOWN, UI_ALIGN_CENTER)) { neural_node_download_models(m->urls); console_info(tr("Downloading", NULL)); } - else if (found && ui_icon_button(string_join(string_join(string_join(tr("Remove", NULL), " ("), m->size), ")"), ICON_DELETE, UI_ALIGN_CENTER)) { + else if (found && ui_icon_button(string("%s (%s)", tr("Remove", NULL), m->size), ICON_DELETE, UI_ALIGN_CENTER)) { for (i32 i = 0; i < m->urls->length; ++i) { char *url = m->urls->buffer[i]; char *file_name = box_preferences_file_name_from_url(url); - iron_delete_file(string_join(string_join(neural_node_dir(), PATH_SEP), file_name)); + iron_delete_file(string("%s%s%s", neural_node_dir(), PATH_SEP, file_name)); } } } @@ -834,22 +831,22 @@ void box_preferences_model_panel(neural_node_model_t *m) { void box_preferences_plugins_tab_plugin_menu_export(char *dest) { if (!ends_with(ui_files_filename, ".js")) { gc_unroot(ui_files_filename); - ui_files_filename = string_join(ui_files_filename, ".js"); + ui_files_filename = string("%s.js", ui_files_filename); gc_root(ui_files_filename); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "plugins"), PATH_SEP), _box_preferences_f); - file_copy(path, string_join(string_join(dest, PATH_SEP), ui_files_filename)); + char *path = string("%s%splugins%s%s", path_data(), PATH_SEP, PATH_SEP, _box_preferences_f); + file_copy(path, string("%s%s%s", dest, PATH_SEP, ui_files_filename)); } void box_preferences_plugins_tab_plugin_menu() { - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "plugins"), PATH_SEP), _box_preferences_f); + char *path = string("%s%splugins%s%s", path_data(), PATH_SEP, PATH_SEP, _box_preferences_f); if (ui_menu_button(tr("Edit in Text Editor", NULL), "", ICON_NONE)) { file_start(path); } if (ui_menu_button(tr("Edit in Script Tab", NULL), "", ICON_NONE)) { - buffer_t *blob = data_get_blob(string_join("plugins/", _box_preferences_f)); + buffer_t *blob = data_get_blob(string("plugins/%s", _box_preferences_f)); tab_scripts_hscript->text = string_copy(sys_buffer_to_string(blob)); - data_delete_blob(string_join("plugins/", _box_preferences_f)); + data_delete_blob(string("plugins/%s", _box_preferences_f)); console_info(tr("Script opened", NULL)); } if (ui_menu_button(tr("Export", NULL), "", ICON_EXPORT)) { @@ -888,9 +885,9 @@ plugin_notify_on_ui(plugin, function() {\ });\ "; if (!ends_with(plugin_name, ".js")) { - plugin_name = string_join(plugin_name, ".js"); + plugin_name = string("%s.js", plugin_name); } - char *path = string_join(string_join(string_join(string_join(path_data(), PATH_SEP), "plugins"), PATH_SEP), plugin_name); + char *path = string("%s%splugins%s%s", path_data(), PATH_SEP, PATH_SEP, plugin_name); iron_file_save_bytes(path, sys_string_to_buffer(template), 0); gc_unroot(box_preferences_files_plugin); box_preferences_files_plugin = NULL; // Refresh file list @@ -997,7 +994,7 @@ void box_preferences_show() { void box_preferences_fetch_themes() { gc_unroot(box_preferences_themes); - box_preferences_themes = file_read_directory(string_join(string_join(path_data(), PATH_SEP), "themes")); + box_preferences_themes = file_read_directory(string("%s%sthemes", path_data(), PATH_SEP)); gc_root(box_preferences_themes); for (i32 i = 0; i < box_preferences_themes->length; ++i) { char *s = box_preferences_themes->buffer[i]; @@ -1008,7 +1005,7 @@ void box_preferences_fetch_themes() { void box_preferences_fetch_keymaps() { gc_unroot(box_preferences_files_keymap); - box_preferences_files_keymap = file_read_directory(string_join(string_join(path_data(), PATH_SEP), "keymap_presets")); + box_preferences_files_keymap = file_read_directory(string("%s%skeymap_presets", path_data(), PATH_SEP)); gc_root(box_preferences_files_keymap); for (i32 i = 0; i < box_preferences_files_keymap->length; ++i) { char *s = box_preferences_files_keymap->buffer[i]; @@ -1019,7 +1016,7 @@ void box_preferences_fetch_keymaps() { void box_preferences_fetch_plugins() { gc_unroot(box_preferences_files_plugin); - box_preferences_files_plugin = file_read_directory(string_join(string_join(path_data(), PATH_SEP), "plugins")); + box_preferences_files_plugin = file_read_directory(string("%s%splugins", path_data(), PATH_SEP)); gc_root(box_preferences_files_plugin); } diff --git a/paint/sources/box_projects.c b/paint/sources/box_projects.c index 4f29c713..b858ca97 100644 --- a/paint/sources/box_projects.c +++ b/paint/sources/box_projects.c @@ -2,16 +2,16 @@ #include "global.h" void box_projects_show_box() { - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) box_projects_align_to_fullscreen(); - #endif +#endif - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) box_projects_tab(); box_projects_get_started_tab(); - #else +#else box_projects_recent_tab(); - #endif +#endif } void box_projects_show() { @@ -26,16 +26,16 @@ void box_projects_show() { } bool draggable; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) draggable = false; - #else +#else draggable = true; - #endif +#endif ui_box_show_custom(&box_projects_show_box, 600, 400, NULL, draggable, ""); } -void box_projects_tab_menu_on_next_frame(void * _) { +void box_projects_tab_menu_on_next_frame(void *_) { iron_delete_file(_box_projects_path); iron_delete_file(_box_projects_icon_path); char *data_path = substring(_box_projects_path, 0, string_length(_box_projects_path) - 4); @@ -68,16 +68,16 @@ void box_projects_tab() { project_new(true); ui_box_hide(); // Pick unique name - i32 i = 0; - i32 j = 0; - char *title = string_join(string_join("", tr("untitled", NULL)), i32_to_string(i)); + i32 i = 0; + i32 j = 0; + char *title = string("%s%s", tr("untitled", NULL), i32_to_string(i)); while (j < config_raw->recent_projects->length) { char *base = config_raw->recent_projects->buffer[j]; - base = string_copy(substring(base, string_last_index_of(base, PATH_SEP) + 1, string_last_index_of(base, "."))); + base = string_copy(substring(base, string_last_index_of(base, PATH_SEP) + 1, string_last_index_of(base, "."))); j++; if (string_equals(title, base)) { i++; - title = string_join(string_join("", tr("untitled", NULL)), i32_to_string(i)); + title = string("%s%s", tr("untitled", NULL), i32_to_string(i)); j = 0; } } @@ -119,15 +119,15 @@ void box_projects_tab() { continue; } - char *path = recent_projects->buffer[i]; + char *path = recent_projects->buffer[i]; - #ifdef IRON_IOS +#ifdef IRON_IOS char *document_directory = iron_save_dialog("", ""); - document_directory = string_copy(substring(document_directory, 0, string_length(document_directory) - 8)); // Strip /"untitled" - path = string_join(document_directory, path); - #endif + document_directory = string_copy(substring(document_directory, 0, string_length(document_directory) - 8)); // Strip /"untitled" + path = string("%s%s", document_directory, path); +#endif - char *icon_path = string_join(substring(path, 0, string_length(path) - 4), "_icon.png"); + char *icon_path = string("%s_icon.png", substring(path, 0, string_length(path) - 4)); if (box_projects_icon_map == NULL) { gc_unroot(box_projects_icon_map); box_projects_icon_map = any_map_create(); @@ -150,9 +150,9 @@ void box_projects_tab() { ui->_x = uix; ui_fill(0, 0, 128, 128, 0x66000000); ui->_x = _uix; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) console_toast(tr("Opening project", NULL)); - #endif +#endif sys_notify_on_next_frame(&box_projects_tab_on_next_frame, path); } @@ -205,11 +205,11 @@ void box_projects_recent_tab() { ui->enabled = true; for (i32 i = 0; i < config_raw->recent_projects->length; ++i) { char *path = config_raw->recent_projects->buffer[i]; - #ifdef IRON_WINDOWS - path = string_copy(string_replace_all(path, "/", "\\")); - #else - path = string_copy(string_replace_all(path, "\\", "/")); - #endif +#ifdef IRON_WINDOWS + path = string_copy(string_replace_all(path, "/", "\\")); +#else + path = string_copy(string_replace_all(path, "\\", "/")); +#endif char *file = substring(path, string_last_index_of(path, PATH_SEP) + 1, string_length(path)); if (string_index_of(to_lower_case(file), to_lower_case(box_projects_hsearch->text)) < 0) { @@ -261,13 +261,13 @@ void box_projects_get_started_tab() { ui_separator(UI_ELEMENT_H(), false); if (ui_icon_button(tr("Manual", NULL), ICON_HELP, UI_ALIGN_CENTER)) { - iron_load_url(string_join(manifest_url, "/manual")); + iron_load_url(string("%s/manual", manifest_url)); } if (ui_icon_button(tr("How To", NULL), ICON_HELP, UI_ALIGN_CENTER)) { - iron_load_url(string_join(manifest_url, "/howto")); + iron_load_url(string("%s/howto", manifest_url)); } if (ui_icon_button(tr("What's New", NULL), ICON_LINK, UI_ALIGN_CENTER)) { - iron_load_url(string_join(manifest_url, "/notes")); + iron_load_url(string("%s/notes", manifest_url)); } } } diff --git a/paint/sources/brush_nodes/input_node.c b/paint/sources/brush_nodes/input_node.c index c2475835..57a7d776 100644 --- a/paint/sources/brush_nodes/input_node.c +++ b/paint/sources/brush_nodes/input_node.c @@ -20,12 +20,9 @@ void input_node_update(float_node_t *self) { } bool decal_mask = context_is_decal_mask_paint(); - - bool lazy_paint = context_raw->brush_lazy_radius > 0 && - (operator_shortcut(any_map_get(config_keymap, "action_paint"), SHORTCUT_TYPE_DOWN) || - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "brush_ruler"), "+"), any_map_get(config_keymap, "action_paint")), - SHORTCUT_TYPE_DOWN) || - decal_mask); + char *ruler_paint = string("%s+%s", any_map_get(config_keymap, "brush_ruler"), any_map_get(config_keymap, "action_paint")); + bool lazy_paint = context_raw->brush_lazy_radius > 0 && (operator_shortcut(any_map_get(config_keymap, "action_paint"), SHORTCUT_TYPE_DOWN) || + operator_shortcut(ruler_paint, SHORTCUT_TYPE_DOWN) || decal_mask); f32 paint_x = mouse_view_x() / (float)sys_w(); f32 paint_y = mouse_view_y() / (float)sys_h(); @@ -44,8 +41,7 @@ void input_node_update(float_node_t *self) { input_node_start_y = pen_view_y() / (float)sys_h(); } - if (operator_shortcut(string_join(string_join(any_map_get(config_keymap, "brush_ruler"), "+"), any_map_get(config_keymap, "action_paint")), - SHORTCUT_TYPE_DOWN)) { + if (operator_shortcut(ruler_paint, SHORTCUT_TYPE_DOWN)) { if (input_node_lock_x) { paint_x = input_node_start_x; } diff --git a/paint/sources/brush_nodes/tex_image_node.c b/paint/sources/brush_nodes/tex_image_node.c index a8ae6d00..0d1752dd 100644 --- a/paint/sources/brush_nodes/tex_image_node.c +++ b/paint/sources/brush_nodes/tex_image_node.c @@ -15,11 +15,11 @@ logic_node_value_t *tex_image_node_get(tex_image_node_t *self, i32 from) { char *file = ar->buffer[i]; if (from == 0) { - logic_node_value_t *v = GC_ALLOC_INIT(logic_node_value_t, {._str = string_join(file, ".rgb")}); + logic_node_value_t *v = GC_ALLOC_INIT(logic_node_value_t, {._str = string("%s.rgb", file)}); return v; } else { - logic_node_value_t *v = GC_ALLOC_INIT(logic_node_value_t, {._str = string_join(file, ".a")}); + logic_node_value_t *v = GC_ALLOC_INIT(logic_node_value_t, {._str = string("%s.a", file)}); return v; } } diff --git a/paint/sources/config.c b/paint/sources/config.c index ad95be36..ac83ab88 100644 --- a/paint/sources/config.c +++ b/paint/sources/config.c @@ -4,12 +4,12 @@ void config_load() { char *path = ""; if (path_is_protected()) { - path = string_join(path, iron_internal_save_path()); + path = iron_internal_save_path(); } - path = string_join(path, "config.json"); + path = string("%sconfig.json", path); buffer_t *blob = data_get_blob(path); - #ifdef IRON_LINUX +#ifdef IRON_LINUX if (blob == NULL) { // Detect protected path config_init(); config_save(); @@ -20,7 +20,7 @@ void config_load() { return; } } - #endif +#endif if (blob != NULL) { char *config_string = sys_buffer_to_string(blob); @@ -36,15 +36,13 @@ void config_load() { void config_save() { // Use system application data folder // when running from protected path like "Program Files" - char *path = ""; + char *path; if (path_is_protected()) { - path = string_join(path, iron_internal_save_path()); + path = string("%sconfig.json", iron_internal_save_path()); } else { - path = string_join(path, path_data()); - path = string_join(path, PATH_SEP); + path = string("%s%sconfig.json", path_data(), PATH_SEP); } - path = string_join(path, "config.json"); json_encode_begin(); json_encode_string("version", config_raw->version); @@ -139,93 +137,93 @@ void config_init() { config_raw->window_maximizable = true; config_raw->window_w = 1720; config_raw->window_h = 960; - #ifdef IRON_MACOS +#ifdef IRON_MACOS config_raw->window_w *= 2; config_raw->window_h *= 2; - #endif +#endif config_raw->window_x = -1; config_raw->window_y = -1; config_raw->window_scale = 1.0; if (sys_display_width() >= 2560 && sys_display_height() >= 1600) { config_raw->window_scale = 2.0; } - #if defined(IRON_ANDROID) || defined(IRON_IOS) || defined(IRON_MACOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) || defined(IRON_MACOS) config_raw->window_scale = 2.0; - #endif - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#endif +#if defined(IRON_ANDROID) || defined(IRON_IOS) if (sys_display_ppi() > 330) { config_raw->window_scale = 2.5; } if (sys_display_ppi() > 400) { config_raw->window_scale = 3.0; } - #endif +#endif config_raw->window_vsync = true; config_raw->window_frequency = sys_display_frequency(); config_raw->rp_bloom = false; config_raw->rp_vignette = 0.2; config_raw->rp_grain = 0.09; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->rp_ssao = false; - #else +#else config_raw->rp_ssao = true; - #endif +#endif config_raw->rp_supersample = 1.0; - #ifdef IRON_ANDROID +#ifdef IRON_ANDROID if (sys_display_width() >= 3200 && sys_display_height() >= 2136) { config_raw->window_scale = 2.5; config_raw->rp_supersample = 0.5; } - #endif +#endif config_raw->recent_projects = any_array_create_from_raw((void *[]){}, 0); config_raw->bookmarks = any_array_create_from_raw((void *[]){}, 0); config_raw->plugins = any_array_create_from_raw((void *[]){}, 0); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->keymap = "touch.json"; - #else +#else config_raw->keymap = "default.json"; - #endif +#endif config_raw->theme = "default.json"; config_raw->server = "https://cloud.armory3d.com"; config_raw->undo_steps = 4; config_raw->pressure_radius = true; - #if defined(IRON_IOS) || defined(IRON_LINUX) +#if defined(IRON_IOS) || defined(IRON_LINUX) config_raw->pressure_sensitivity = 1.0; - #else +#else config_raw->pressure_sensitivity = 2.0; - #endif +#endif config_raw->camera_fov = 0.69; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->camera_zoom_speed = 0.5; config_raw->camera_pan_speed = 0.5; config_raw->camera_rotation_speed = 0.5; - #else +#else config_raw->camera_zoom_speed = 1.0; config_raw->camera_pan_speed = 1.0; config_raw->camera_rotation_speed = 1.0; - #endif +#endif config_raw->camera_upside_down = false; config_raw->zoom_direction = ZOOM_DIRECTION_VERTICAL; config_raw->displace_strength = 0.0; config_raw->wrap_mouse = false; config_raw->camera_controls = CAMERA_CONTROLS_ORBIT; config_raw->layer_res = TEXTURE_RES_RES2048; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->touch_ui = true; config_raw->splash_screen = true; - #else +#else config_raw->touch_ui = false; config_raw->splash_screen = false; - #endif +#endif config_raw->node_previews = false; config_raw->pressure_hardness = true; config_raw->pressure_angle = false; config_raw->pressure_opacity = false; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->material_live = false; - #else +#else config_raw->material_live = true; - #endif +#endif config_raw->brush_depth_reject = true; config_raw->brush_angle_reject = true; config_raw->brush_alpha_discard = 0.1; @@ -238,11 +236,11 @@ void config_init() { config_raw->grid_snap = false; config_raw->experimental = false; config_raw->neural_backend = NEURAL_BACKEND_VULKAN; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) config_raw->render_mode = RENDER_MODE_FORWARD; - #else +#else config_raw->render_mode = RENDER_MODE_DEFERRED; - #endif +#endif config_raw->workspace = WORKSPACE_PAINT_3D; } else { @@ -256,11 +254,11 @@ void config_init() { ui_touch_control = config_raw->touch_ui; ui_touch_speed = 1.0; - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) if (sys_display_ppi() > 400) { ui_touch_speed = 0.5; } - #endif +#endif base_res_handle->i = config_raw->layer_res; keymap_load(); } @@ -274,24 +272,24 @@ void config_init_layout() { i32_array_push(new_layout, math_floor(iron_window_height() / (float)2)); // LayoutSidebarH0 i32_array_push(new_layout, math_floor(iron_window_height() / (float)2)); // LayoutSidebarH1 - #ifdef IRON_IOS +#ifdef IRON_IOS i32_array_push(new_layout, show2d ? math_floor((sys_w() + raw->layout->buffer[LAYOUT_SIZE_NODES_W]) * 0.473) : math_floor(sys_w() * 0.473)); // LayoutNodesW - #elif defined(IRON_ANDROID) +#elif defined(IRON_ANDROID) i32_array_push(new_layout, show2d ? math_floor((sys_w() + raw->layout->buffer[LAYOUT_SIZE_NODES_W]) * 0.473) : math_floor(sys_w() * 0.473)); - #else +#else i32_array_push(new_layout, show2d ? math_floor((sys_w() + raw->layout->buffer[LAYOUT_SIZE_NODES_W]) * 0.515) : math_floor(sys_w() * 0.515)); // Align with ui header controls - #endif +#endif i32_array_push(new_layout, math_floor(sys_h() / (float)2)); // LayoutNodesH i32_array_push(new_layout, math_floor(ui_statusbar_default_h * raw->window_scale)); // LayoutStatusH - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) i32_array_push(new_layout, 0); // LayoutHeader - #else +#else i32_array_push(new_layout, 1); - #endif +#endif raw->layout_tabs = i32_array_create_from_raw( (i32[]){ @@ -334,7 +332,7 @@ iron_window_options_t *config_get_options() { if (config_raw->window_minimizable) { features |= IRON_WINDOW_FEATURES_MINIMIZABLE; } - char *title = string_join("untitled - ", manifest_title); + char *title = string("untitled - %s", manifest_title); iron_window_options_t *ops = GC_ALLOC_INIT(iron_window_options_t, {.title = title, .width = config_raw->window_w, .height = config_raw->window_h, @@ -452,7 +450,7 @@ void config_load_theme(char *theme, bool tag_redraw) { gc_root(base_theme); if (!string_equals(theme, "default.json")) { - buffer_t *b = data_get_blob(string_join("themes/", theme)); + buffer_t *b = data_get_blob(string("themes/%s", theme)); ui_theme_t *parsed = json_parse(sys_buffer_to_string(b)); gc_unroot(base_theme); base_theme = parsed; diff --git a/paint/sources/context.c b/paint/sources/context.c index cd0c97e4..b45449fd 100644 --- a/paint/sources/context.c +++ b/paint/sources/context.c @@ -2,91 +2,91 @@ #include "global.h" context_t *context_create() { - context_t *c = GC_ALLOC_INIT(context_t, {0}); - c->merged_object_is_atlas = false; // Only objects referenced by atlas are merged - c->ddirty = 0; // depth - c->pdirty = 0; // paint - c->rdirty = 0; // render - c->brush_blend_dirty = true; - c->split_view = false; - c->view_index = -1; - c->view_index_last = -1; - c->picked_color = project_make_swatch(0xffffffff); - c->envmap_loaded = false; - c->show_envmap = false; - c->show_envmap_handle = ui_handle_create(); - c->show_envmap_blur = false; - c->show_envmap_blur_handle = ui_handle_create(); - c->envmap_angle = 0.0; - c->light_angle = 0.0; - c->cull_backfaces = true; - c->texture_filter = true; - c->format_type = TEXTURE_LDR_FORMAT_PNG; - c->format_quality = 100.0; - c->layers_destination = EXPORT_DESTINATION_DISK; - c->split_by = SPLIT_TYPE_OBJECT; - c->select_time = 0.0; - c->viewport_mode = config_raw->viewport_mode == 0 ? VIEWPORT_MODE_LIT : VIEWPORT_MODE_PATH_TRACE; - c->hscale_was_changed = false; - c->export_mesh_format = MESH_FORMAT_OBJ; - c->export_mesh_index = 0; - c->pack_assets_on_export = true; - c->paint_vec = vec4_create(0.0, 0.0, 0.0, 1.0); - c->last_paint_x = -1.0; - c->last_paint_y = -1.0; - c->foreground_event = false; - c->painted = 0; - c->brush_time = 0.0; - c->clone_start_x = -1.0; - c->clone_start_y = -1.0; - c->clone_delta_x = 0.0; - c->clone_delta_y = 0.0; - c->show_compass = true; - c->project_aspect_ratio = 0; // 1:1, 2:1, 1:2 - c->last_paint_vec_x = -1.0; - c->last_paint_vec_y = -1.0; - c->prev_paint_vec_x = -1.0; - c->prev_paint_vec_y = -1.0; - c->frame = 0; - c->paint2d_view = false; - c->brush_locked = false; - c->camera_type = CAMERA_TYPE_PERSPECTIVE; - c->cam_handle = ui_handle_create(); - c->fov_handle = ui_handle_create(); - c->texture_export_path = ""; - c->last_status_position = 0; - c->camera_controls = CAMERA_CONTROLS_ORBIT; - c->pen_painting_only = false; // Reject painting with finger when using pen - c->layer_preview_dirty = true; - c->layers_preview_dirty = false; - c->node_preview_name = ""; - c->node_preview_socket_map = any_map_create(); - c->node_preview_map = any_map_create(); - c->selected_node_preview = true; - c->colorid_picked = false; - c->material_preview = false; // Drawing material previews - c->saved_camera = mat4_identity(); - c->materialid_picked = 0; - c->uvx_picked = 0.0; - c->uvy_picked = 0.0; - c->picker_select_material = false; - c->picker_mask_handle = ui_handle_create(); - c->pick_pos_nor_tex = false; - c->posx_picked = 0.0; - c->posy_picked = 0.0; - c->posz_picked = 0.0; - c->norx_picked = 0.0; - c->nory_picked = 0.0; - c->norz_picked = 0.0; - c->draw_wireframe = false; - c->wireframe_handle = ui_handle_create(); - c->draw_texels = false; - c->texels_handle = ui_handle_create(); - c->colorid_handle = ui_handle_create(); - c->layers_export = EXPORT_MODE_VISIBLE; - c->decal_preview = false; - c->decal_x = 0.0; - c->decal_y = 0.0; + context_t *c = GC_ALLOC_INIT(context_t, {0}); + c->merged_object_is_atlas = false; // Only objects referenced by atlas are merged + c->ddirty = 0; // depth + c->pdirty = 0; // paint + c->rdirty = 0; // render + c->brush_blend_dirty = true; + c->split_view = false; + c->view_index = -1; + c->view_index_last = -1; + c->picked_color = project_make_swatch(0xffffffff); + c->envmap_loaded = false; + c->show_envmap = false; + c->show_envmap_handle = ui_handle_create(); + c->show_envmap_blur = false; + c->show_envmap_blur_handle = ui_handle_create(); + c->envmap_angle = 0.0; + c->light_angle = 0.0; + c->cull_backfaces = true; + c->texture_filter = true; + c->format_type = TEXTURE_LDR_FORMAT_PNG; + c->format_quality = 100.0; + c->layers_destination = EXPORT_DESTINATION_DISK; + c->split_by = SPLIT_TYPE_OBJECT; + c->select_time = 0.0; + c->viewport_mode = config_raw->viewport_mode == 0 ? VIEWPORT_MODE_LIT : VIEWPORT_MODE_PATH_TRACE; + c->hscale_was_changed = false; + c->export_mesh_format = MESH_FORMAT_OBJ; + c->export_mesh_index = 0; + c->pack_assets_on_export = true; + c->paint_vec = vec4_create(0.0, 0.0, 0.0, 1.0); + c->last_paint_x = -1.0; + c->last_paint_y = -1.0; + c->foreground_event = false; + c->painted = 0; + c->brush_time = 0.0; + c->clone_start_x = -1.0; + c->clone_start_y = -1.0; + c->clone_delta_x = 0.0; + c->clone_delta_y = 0.0; + c->show_compass = true; + c->project_aspect_ratio = 0; // 1:1, 2:1, 1:2 + c->last_paint_vec_x = -1.0; + c->last_paint_vec_y = -1.0; + c->prev_paint_vec_x = -1.0; + c->prev_paint_vec_y = -1.0; + c->frame = 0; + c->paint2d_view = false; + c->brush_locked = false; + c->camera_type = CAMERA_TYPE_PERSPECTIVE; + c->cam_handle = ui_handle_create(); + c->fov_handle = ui_handle_create(); + c->texture_export_path = ""; + c->last_status_position = 0; + c->camera_controls = CAMERA_CONTROLS_ORBIT; + c->pen_painting_only = false; // Reject painting with finger when using pen + c->layer_preview_dirty = true; + c->layers_preview_dirty = false; + c->node_preview_name = ""; + c->node_preview_socket_map = any_map_create(); + c->node_preview_map = any_map_create(); + c->selected_node_preview = true; + c->colorid_picked = false; + c->material_preview = false; // Drawing material previews + c->saved_camera = mat4_identity(); + c->materialid_picked = 0; + c->uvx_picked = 0.0; + c->uvy_picked = 0.0; + c->picker_select_material = false; + c->picker_mask_handle = ui_handle_create(); + c->pick_pos_nor_tex = false; + c->posx_picked = 0.0; + c->posy_picked = 0.0; + c->posz_picked = 0.0; + c->norx_picked = 0.0; + c->nory_picked = 0.0; + c->norz_picked = 0.0; + c->draw_wireframe = false; + c->wireframe_handle = ui_handle_create(); + c->draw_texels = false; + c->texels_handle = ui_handle_create(); + c->colorid_handle = ui_handle_create(); + c->layers_export = EXPORT_MODE_VISIBLE; + c->decal_preview = false; + c->decal_x = 0.0; + c->decal_y = 0.0; // c.cache_draws = false; c->write_icon_on_export = false; c->particle_hit_x = 0.0; @@ -191,7 +191,7 @@ void context_select_material(i32 i) { context_set_material(project_materials->buffer[i]); } -void context_set_material_on_next_frame(void * _) { +void context_set_material_on_next_frame(void *_) { util_render_make_decal_preview(); } @@ -263,8 +263,8 @@ void context_set_layer(slot_layer_t *l) { context_raw->layer = l; ui_header_handle->redraws = 2; - gpu_texture_t *current = _draw_current; - bool in_use = gpu_in_use; + gpu_texture_t *current = _draw_current; + bool in_use = gpu_in_use; if (in_use) draw_end(); @@ -327,9 +327,9 @@ void context_select_paint_object(mesh_object_t *o) { // context_raw->paint_object->skip_context = ""; // #endif - context_raw->paint_object = o; + context_raw->paint_object = o; - i32 mask = slot_layer_get_object_mask(context_raw->layer); + i32 mask = slot_layer_get_object_mask(context_raw->layer); if (context_layer_filter_used()) { mask = context_raw->layer_filter; } @@ -411,8 +411,7 @@ bool context_is_decal_mask() { bool context_is_decal_mask_paint() { return context_is_decal() && - operator_shortcut(string_join(string_join(any_map_get(config_keymap, "decal_mask"), "+"), any_map_get(config_keymap, "action_paint")), - SHORTCUT_TYPE_DOWN); + operator_shortcut(string("%s+%s", any_map_get(config_keymap, "decal_mask"), any_map_get(config_keymap, "action_paint")), SHORTCUT_TYPE_DOWN); } bool context_is_floating_toolbar() { @@ -493,12 +492,12 @@ void context_update_envmap() { } } -void context_set_viewport_shader(void * viewport_shader) { // JSValue * -> (ns: node_shader_t)=>void +void context_set_viewport_shader(void *viewport_shader) { // JSValue * -> (ns: node_shader_t)=>void context_raw->viewport_shader = viewport_shader; context_set_render_path(); } -void context_set_render_path_on_next_frame(void * _) { +void context_set_render_path_on_next_frame(void *_) { make_material_parse_mesh_material(); } @@ -526,7 +525,7 @@ bool context_enable_import_plugin(char *file) { char *f = box_preferences_files_plugin->buffer[i]; if (starts_with(f, "import_") && string_index_of(f, ext) >= 0) { config_enable_plugin(f); - console_info(string_join(string_join(f, " "), tr("plugin enabled", NULL))); + console_info(string("%s %s", f, tr("plugin enabled", NULL))); return true; } } diff --git a/paint/sources/export_arm.c b/paint/sources/export_arm.c index 5c2aed60..35d008fc 100644 --- a/paint/sources/export_arm.c +++ b/paint/sources/export_arm.c @@ -12,7 +12,7 @@ void export_arm_run_mesh(char *path, mesh_object_t_array_t *paint_objects) { buffer_t *b = util_encode_scene(raw); if (!ends_with(path, ".arm")) { - path = string_join(path, ".arm"); + path = string("%s.arm", path); } iron_file_save_bytes(path, b, b->length + 1); } @@ -60,15 +60,15 @@ void export_arm_run_project() { any_array_push(md, p->data); } - string_t_array_t *texture_files = export_arm_assets_to_files(project_filepath, project_assets); + string_t_array_t *texture_files = export_arm_assets_to_files(project_filepath, project_assets); - string_t_array_t *font_files = export_arm_fonts_to_files(project_filepath, project_fonts); - string_t_array_t *mesh_files = export_arm_meshes_to_files(project_filepath); + string_t_array_t *font_files = export_arm_fonts_to_files(project_filepath, project_fonts); + string_t_array_t *mesh_files = export_arm_meshes_to_files(project_filepath); - i32 bits_pos = base_bits_handle->i; - i32 bpp = bits_pos == TEXTURE_BITS_BITS8 ? 8 : bits_pos == TEXTURE_BITS_BITS16 ? 16 : 32; + i32 bits_pos = base_bits_handle->i; + i32 bpp = bits_pos == TEXTURE_BITS_BITS8 ? 8 : bits_pos == TEXTURE_BITS_BITS16 ? 16 : 32; - layer_data_t_array_t *ld = any_array_create_from_raw((void *[]){}, 0); + layer_data_t_array_t *ld = any_array_create_from_raw((void *[]){}, 0); for (i32 i = 0; i < project_layers->length; ++i) { slot_layer_t *l = project_layers->buffer[i]; layer_data_t *d = GC_ALLOC_INIT(layer_data_t, {.name = l->name, @@ -103,17 +103,17 @@ void export_arm_run_project() { } packed_asset_t_array_t *packed_assets = (project_raw->packed_assets == NULL || project_raw->packed_assets->length == 0) ? NULL : project_raw->packed_assets; - #ifdef IRON_IOS - bool same_drive = false; - #else - bool same_drive = project_raw->envmap != NULL ? char_at(project_filepath, 0) == char_at(project_raw->envmap, 0) : true; - #endif +#ifdef IRON_IOS + bool same_drive = false; +#else + bool same_drive = project_raw->envmap != NULL ? char_at(project_filepath, 0) == char_at(project_raw->envmap, 0) : true; +#endif - project_raw->version = string_copy(manifest_version_project); - project_raw->material_groups = mgroups; - project_raw->assets = texture_files; - project_raw->packed_assets = packed_assets; - project_raw->swatches = project_raw->swatches; + project_raw->version = string_copy(manifest_version_project); + project_raw->material_groups = mgroups; + project_raw->assets = texture_files; + project_raw->packed_assets = packed_assets; + project_raw->swatches = project_raw->swatches; project_raw->envmap = project_raw->envmap != NULL ? (same_drive ? path_to_relative(project_filepath, project_raw->envmap) : project_raw->envmap) : NULL; project_raw->envmap_strength = scene_world->strength; project_raw->envmap_angle = context_raw->envmap_angle; @@ -141,17 +141,17 @@ void export_arm_run_project() { project_raw->atlas_objects = project_atlas_objects; project_raw->atlas_names = project_atlas_names; - #ifdef IRON_BGRA - project_raw->is_bgra = true; - #else - project_raw->is_bgra = false; - #endif +#ifdef IRON_BGRA + project_raw->is_bgra = true; +#else + project_raw->is_bgra = false; +#endif - #if defined(IRON_ANDROID) || defined(IRON_IOS) - render_target_t *rt = any_map_get(render_path_render_targets, "buf"); - gpu_texture_t *tex = rt->_image; - gpu_texture_t *mesh_icon = gpu_create_render_target(256, 256, GPU_TEXTURE_FORMAT_RGBA32); - f32 r = sys_w() / (float)sys_h(); +#if defined(IRON_ANDROID) || defined(IRON_IOS) + render_target_t *rt = any_map_get(render_path_render_targets, "buf"); + gpu_texture_t *tex = rt->_image; + gpu_texture_t *mesh_icon = gpu_create_render_target(256, 256, GPU_TEXTURE_FORMAT_RGBA32); + f32 r = sys_w() / (float)sys_h(); draw_begin(mesh_icon, false, 0); draw_scaled_image(tex, -(256 * r - 256) / (float)2, 0, 256 * r, 256); draw_end(); @@ -161,9 +161,9 @@ void export_arm_run_project() { for (i32 i = 0; i < 256 * 256 * 4; ++i) { u8a->buffer[i] = math_floor(math_pow(u8a->buffer[i] / (float)255, 1.0 / (float)2.2) * 255); } - iron_write_png(string_join(substring(project_filepath, 0, string_length(project_filepath) - 4), "_icon.png"), mesh_icon_pixels, 256, 256, 0); + iron_write_png(string("%s_icon.png", substring(project_filepath, 0, string_length(project_filepath) - 4)), mesh_icon_pixels, 256, 256, 0); gpu_delete_texture(mesh_icon); - #endif +#endif bool is_packed = ends_with(project_filepath, "_packed_.arm"); if (is_packed) { // Pack textures @@ -173,16 +173,16 @@ void export_arm_run_project() { buffer_t *buffer = util_encode_project(project_raw); iron_file_save_bytes(project_filepath, buffer, buffer->length + 1); - // Save to recent - #ifdef IRON_IOS - char *recent_path = substring(project_filepath, string_last_index_of(project_filepath, "/") + 1, string_length(project_filepath)); - #else - char *recent_path = project_filepath; - #endif +// Save to recent +#ifdef IRON_IOS + char *recent_path = substring(project_filepath, string_last_index_of(project_filepath, "/") + 1, string_length(project_filepath)); +#else + char *recent_path = project_filepath; +#endif - #ifdef IRON_WINDOWS - recent_path = string_copy(string_replace_all(recent_path, "\\", "/")); - #endif +#ifdef IRON_WINDOWS + recent_path = string_copy(string_replace_all(recent_path, "\\", "/")); +#endif string_t_array_t *recent = config_raw->recent_projects; char_ptr_array_remove(recent, recent_path); array_insert(recent, 0, recent_path); @@ -211,7 +211,7 @@ void export_arm_export_node(ui_node_t *n, asset_t_array_t *assets) { void export_arm_run_material(char *path) { if (!ends_with(path, ".arm")) { - path = string_join(path, ".arm"); + path = string("%s.arm", path); } ui_node_canvas_t_array_t *mnodes = any_array_create_from_raw((void *[]){}, 0); ui_node_canvas_t_array_t *mgroups = NULL; @@ -247,16 +247,16 @@ void export_arm_run_material(char *path) { buffer_t_array_t *micons = NULL; if (!is_cloud) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *buf = lz4_encode(export_arm_bgra64_swap(gpu_get_texture_pixels(m->image))); - #else +#else buffer_t *buf = lz4_encode(gpu_get_texture_pixels(m->image)); - #endif - micons = any_array_create_from_raw( - (void *[]){ - buf, - }, - 1); +#endif + micons = any_array_create_from_raw( + (void *[]){ + buf, + }, + 1); } project_format_t *raw = GC_ALLOC_INIT(project_format_t, {.version = manifest_version_project, .material_nodes = mnodes, @@ -266,12 +266,12 @@ void export_arm_run_material(char *path) { .packed_assets = packed_assets}); if (context_raw->write_icon_on_export) { // Separate icon files buffer_t *buf = export_arm_rgba64_to_rgba32(gpu_get_texture_pixels(m->image)); - #ifdef IRON_BGRA - buf = export_arm_bgra_swap(buf); - #endif - iron_write_png(string_join(substring(path, 0, string_length(path) - 4), "_icon.png"), buf, m->image->width, m->image->height, 0); +#ifdef IRON_BGRA + buf = export_arm_bgra_swap(buf); +#endif + iron_write_png(string("%s_icon.png", substring(path, 0, string_length(path) - 4)), buf, m->image->width, m->image->height, 0); if (is_cloud) { - iron_write_jpg(string_join(substring(path, 0, string_length(path) - 4), "_icon.jpg"), buf, m->image->width, m->image->height, 0, 50); + iron_write_jpg(string("%s_icon.jpg", substring(path, 0, string_length(path) - 4)), buf, m->image->width, m->image->height, 0, 50); } } @@ -306,7 +306,7 @@ buffer_t *export_arm_bgra64_swap(buffer_t *buffer) { void export_arm_run_brush(char *path) { if (!ends_with(path, ".arm")) { - path = string_join(path, ".arm"); + path = string("%s.arm", path); } ui_node_canvas_t_array_t *bnodes = any_array_create_from_raw((void *[]){}, 0); slot_brush_t *b = context_raw->brush; @@ -330,16 +330,16 @@ void export_arm_run_brush(char *path) { buffer_t_array_t *bicons = NULL; if (!is_cloud) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *buf = lz4_encode(export_arm_bgra_swap(gpu_get_texture_pixels(b->image))); - #else +#else buffer_t *buf = lz4_encode(gpu_get_texture_pixels(b->image)); - #endif - bicons = any_array_create_from_raw( - (void *[]){ - buf, - }, - 1); +#endif + bicons = any_array_create_from_raw( + (void *[]){ + buf, + }, + 1); } project_format_t *raw = GC_ALLOC_INIT( @@ -348,10 +348,10 @@ void export_arm_run_brush(char *path) { if (context_raw->write_icon_on_export) { // Separate icon file buffer_t *buf = export_arm_rgba64_to_rgba32(gpu_get_texture_pixels(b->image)); - #ifdef IRON_BGRA - buf = export_arm_bgra_swap(buf); - #endif - iron_write_png(string_join(substring(path, 0, string_length(path) - 4), "_icon.png"), buf, b->image->width, b->image->height, 0); +#ifdef IRON_BGRA + buf = export_arm_bgra_swap(buf); +#endif + iron_write_png(string("%s_icon.png", substring(path, 0, string_length(path) - 4)), buf, b->image->width, b->image->height, 0); } if (context_raw->pack_assets_on_export) { // Pack textures @@ -365,12 +365,12 @@ void export_arm_run_brush(char *path) { string_t_array_t *export_arm_assets_to_files(char *project_path, asset_t_array_t *assets) { string_t_array_t *texture_files = any_array_create_from_raw((void *[]){}, 0); for (i32 i = 0; i < assets->length; ++i) { - asset_t *a = assets->buffer[i]; - #ifdef IRON_IOS - bool same_drive = false; - #else - bool same_drive = char_at(project_path, 0) == char_at(a->file, 0); - #endif + asset_t *a = assets->buffer[i]; +#ifdef IRON_IOS + bool same_drive = false; +#else + bool same_drive = char_at(project_path, 0) == char_at(a->file, 0); +#endif // Convert image path from absolute to relative if (same_drive) { any_array_push(texture_files, path_to_relative(project_path, a->file)); @@ -385,12 +385,12 @@ string_t_array_t *export_arm_assets_to_files(char *project_path, asset_t_array_t string_t_array_t *export_arm_meshes_to_files(char *project_path) { string_t_array_t *mesh_files = any_array_create_from_raw((void *[]){}, 0); for (i32 i = 0; i < project_mesh_assets->length; ++i) { - char *file = project_mesh_assets->buffer[i]; - #ifdef IRON_IOS - bool same_drive = false; - #else - bool same_drive = char_at(project_path, 0) == char_at(file, 0); - #endif + char *file = project_mesh_assets->buffer[i]; +#ifdef IRON_IOS + bool same_drive = false; +#else + bool same_drive = char_at(project_path, 0) == char_at(file, 0); +#endif // Convert mesh path from absolute to relative if (same_drive) { any_array_push(mesh_files, path_to_relative(project_path, file)); @@ -405,12 +405,12 @@ string_t_array_t *export_arm_meshes_to_files(char *project_path) { string_t_array_t *export_arm_fonts_to_files(char *project_path, slot_font_t_array_t *fonts) { string_t_array_t *font_files = any_array_create_from_raw((void *[]){}, 0); for (i32 i = 1; i < fonts->length; ++i) { - slot_font_t *f = fonts->buffer[i]; - #ifdef IRON_IOS - bool same_drive = false; - #else - bool same_drive = char_at(project_path, 0) == char_at(f->file, 0); - #endif + slot_font_t *f = fonts->buffer[i]; +#ifdef IRON_IOS + bool same_drive = false; +#else + bool same_drive = char_at(project_path, 0) == char_at(f->file, 0); +#endif // Convert font path from absolute to relative if (same_drive) { any_array_push(font_files, path_to_relative(project_path, f->file)); @@ -426,14 +426,14 @@ packed_asset_t_array_t *export_arm_get_packed_assets(char *project_path, string_ packed_asset_t_array_t *packed_assets = NULL; if (project_raw->packed_assets != NULL) { for (i32 i = 0; i < project_raw->packed_assets->length; ++i) { - packed_asset_t *pa = project_raw->packed_assets->buffer[i]; - #ifdef IRON_IOS - bool same_drive = false; - #else - bool same_drive = char_at(project_path, 0) == char_at(pa->name, 0); - #endif + packed_asset_t *pa = project_raw->packed_assets->buffer[i]; +#ifdef IRON_IOS + bool same_drive = false; +#else + bool same_drive = char_at(project_path, 0) == char_at(pa->name, 0); +#endif // Convert path from absolute to relative - pa->name = same_drive ? path_to_relative(project_path, pa->name) : pa->name; + pa->name = same_drive ? path_to_relative(project_path, pa->name) : pa->name; for (i32 i = 0; i < texture_files->length; ++i) { char *tf = texture_files->buffer[i]; if (string_equals(pa->name, tf)) { @@ -478,7 +478,7 @@ void export_arm_pack_assets(project_format_t *raw, asset_t_array_t *assets) { void export_arm_run_swatches(char *path) { if (!ends_with(path, ".arm")) { - path = string_join(path, ".arm"); + path = string("%s.arm", path); } project_format_t *raw = GC_ALLOC_INIT(project_format_t, {.version = manifest_version_project, .swatches = project_raw->swatches}); buffer_t *buffer = util_encode_project(raw); diff --git a/paint/sources/export_obj.c b/paint/sources/export_obj.c index ff7f5f62..fc15654e 100644 --- a/paint/sources/export_obj.c +++ b/paint/sources/export_obj.c @@ -15,26 +15,26 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects, bool apply i32 noff = 0; i32 toff = 0; for (i32 i = 0; i < paint_objects->length; ++i) { - mesh_object_t *p = paint_objects->buffer[i]; - mesh_data_t *mesh = p->data; - f32 inv = 1 / (float)32767; - f32 sc = p->data->scale_pos * inv; - i16_array_t *posa = mesh->vertex_arrays->buffer[0]->values; - i16_array_t *nora = mesh->vertex_arrays->buffer[1]->values; - i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values; - i32 len = math_floor(posa->length / (float)4); + mesh_object_t *p = paint_objects->buffer[i]; + mesh_data_t *mesh = p->data; + f32 inv = 1 / (float)32767; + f32 sc = p->data->scale_pos * inv; + i16_array_t *posa = mesh->vertex_arrays->buffer[0]->values; + i16_array_t *nora = mesh->vertex_arrays->buffer[1]->values; + i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values; + i32 len = math_floor(posa->length / (float)4); // Merge shared vertices and remap indices - i16_array_t *posa2 = i16_array_create(len * 3); - i16_array_t *nora2 = i16_array_create(len * 3); - i16_array_t *texa2 = i16_array_create(len * 2); - i32_array_t *posmap = i32_array_create(len); - i32_array_t *normap = i32_array_create(len); - i32_array_t *texmap = i32_array_create(len); + i16_array_t *posa2 = i16_array_create(len * 3); + i16_array_t *nora2 = i16_array_create(len * 3); + i16_array_t *texa2 = i16_array_create(len * 2); + i32_array_t *posmap = i32_array_create(len); + i32_array_t *normap = i32_array_create(len); + i32_array_t *texmap = i32_array_create(len); - i32 pi = 0; - i32 ni = 0; - i32 ti = 0; + i32 pi = 0; + i32 ni = 0; + i32 ti = 0; for (i32 i = 0; i < len; ++i) { bool found = false; for (i32 j = 0; j < pi; ++j) { @@ -99,38 +99,38 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects, bool apply // } } - export_obj_write_string(o, string_join(string_join("o ", p->base->name), "\n")); + export_obj_write_string(o, string("o %s\n", p->base->name)); for (i32 i = 0; i < pi; ++i) { export_obj_write_string(o, "v "); f32 f = posa2->buffer[i * 3] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = posa2->buffer[i * 3 + 2] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = -posa2->buffer[i * 3 + 1] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } for (i32 i = 0; i < ni; ++i) { export_obj_write_string(o, "vn "); f32 f = nora2->buffer[i * 3] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = nora2->buffer[i * 3 + 2] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = -nora2->buffer[i * 3 + 1] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } for (i32 i = 0; i < ti; ++i) { export_obj_write_string(o, "vt "); f32 f = texa2->buffer[i * 2] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = 1.0 - texa2->buffer[i * 2 + 1] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } @@ -146,23 +146,23 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects, bool apply i32 ti2 = texmap->buffer[inda->buffer[i * 3 + 1]] + 1 + toff; i32 ti3 = texmap->buffer[inda->buffer[i * 3 + 2]] + 1 + toff; export_obj_write_string(o, "f "); - export_obj_write_string(o, string_join(i32_to_string(pi1), "")); + export_obj_write_string(o, i32_to_string(pi1)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti1), "")); + export_obj_write_string(o, i32_to_string(ti1)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni1), "")); + export_obj_write_string(o, i32_to_string(ni1)); export_obj_write_string(o, " "); - export_obj_write_string(o, string_join(i32_to_string(pi2), "")); + export_obj_write_string(o, i32_to_string(pi2)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti2), "")); + export_obj_write_string(o, i32_to_string(ti2)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni2), "")); + export_obj_write_string(o, i32_to_string(ni2)); export_obj_write_string(o, " "); - export_obj_write_string(o, string_join(i32_to_string(pi3), "")); + export_obj_write_string(o, i32_to_string(pi3)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti3), "")); + export_obj_write_string(o, i32_to_string(ti3)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni3), "")); + export_obj_write_string(o, i32_to_string(ni3)); export_obj_write_string(o, "\n"); } poff += pi; @@ -171,7 +171,7 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects, bool apply } if (!ends_with(path, ".obj")) { - path = string_join(path, ".obj"); + path = string("%s.obj", path); } iron_file_save_bytes(path, o, 0); } @@ -194,42 +194,42 @@ void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) { i16_array_t *nora = mesh->vertex_arrays->buffer[1]->values; i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values; - i32 pi = posa->length / (float)4; - i32 ni = pi; - i32 ti = pi; + i32 pi = posa->length / (float)4; + i32 ni = pi; + i32 ti = pi; - export_obj_write_string(o, string_join(string_join("o ", p->base->name), "\n")); + export_obj_write_string(o, string("o %s\n", p->base->name)); for (i32 i = 0; i < pi; ++i) { export_obj_write_string(o, "v "); f32 f = posa->buffer[i * 4] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = posa->buffer[i * 4 + 2] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = -posa->buffer[i * 4 + 1] * sc; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } for (i32 i = 0; i < ni; ++i) { export_obj_write_string(o, "vn "); f32 f = nora->buffer[i * 2] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = posa->buffer[i * 4 + 3] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = -nora->buffer[i * 2 + 1] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } for (i32 i = 0; i < ti; ++i) { export_obj_write_string(o, "vt "); f32 f = texa->buffer[i * 2] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, " "); f = 1.0 - texa->buffer[i * 2 + 1] * inv; - export_obj_write_string(o, string_join(f32_to_string(f), "")); + export_obj_write_string(o, f32_to_string(f)); export_obj_write_string(o, "\n"); } @@ -245,23 +245,23 @@ void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) { i32 ti2 = inda->buffer[i * 3 + 1] + 1 + toff; i32 ti3 = inda->buffer[i * 3 + 2] + 1 + toff; export_obj_write_string(o, "f "); - export_obj_write_string(o, string_join(i32_to_string(pi1), "")); + export_obj_write_string(o, i32_to_string(pi1)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti1), "")); + export_obj_write_string(o, i32_to_string(ti1)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni1), "")); + export_obj_write_string(o, i32_to_string(ni1)); export_obj_write_string(o, " "); - export_obj_write_string(o, string_join(i32_to_string(pi2), "")); + export_obj_write_string(o, i32_to_string(pi2)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti2), "")); + export_obj_write_string(o, i32_to_string(ti2)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni2), "")); + export_obj_write_string(o, i32_to_string(ni2)); export_obj_write_string(o, " "); - export_obj_write_string(o, string_join(i32_to_string(pi3), "")); + export_obj_write_string(o, i32_to_string(pi3)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ti3), "")); + export_obj_write_string(o, i32_to_string(ti3)); export_obj_write_string(o, "/"); - export_obj_write_string(o, string_join(i32_to_string(ni3), "")); + export_obj_write_string(o, i32_to_string(ni3)); export_obj_write_string(o, "\n"); } poff += pi; @@ -270,7 +270,7 @@ void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) { } if (!ends_with(path, ".obj")) { - path = string_join(path, ".obj"); + path = string("%s.obj", path); } iron_file_save_bytes(path, o, 0); } diff --git a/paint/sources/export_texture.c b/paint/sources/export_texture.c index 5fe72f2a..6eb45d8f 100644 --- a/paint/sources/export_texture.c +++ b/paint/sources/export_texture.c @@ -98,18 +98,18 @@ void export_texture_run(char *path, bool bake_material) { } } - #ifdef IRON_IOS +#ifdef IRON_IOS if (config_is_iphone()) { - console_info(string_join(string_join(string_join(tr("Textures exported", NULL), " (\"Files/On My iPhone/"), manifest_title), "\")")); + console_info(string("%s (\"Files/On My iPhone/%s\")", tr("Textures exported", NULL), manifest_title)); } else { - console_info(string_join(string_join(string_join(tr("Textures exported", NULL), " (\"Files/On My iPad/"), manifest_title), "\")")); + console_info(string("%s (\"Files/On My iPad/%s\")", tr("Textures exported", NULL), manifest_title)); } - #elif defined(IRON_ANDROID) - console_info(string_join(string_join(string_join(tr("Textures exported", NULL), " (\"Files/Internal storage/Pictures/"), manifest_title), "\")")); - #else +#elif defined(IRON_ANDROID) + console_info(string("%s (\"Files/Internal storage/Pictures/%s\")", tr("Textures exported", NULL), manifest_title)); +#else console_info(tr("Textures exported", NULL)); - #endif +#endif gc_unroot(ui_files_last_path); ui_files_last_path = ""; gc_root(ui_files_last_path); @@ -164,24 +164,24 @@ void export_texture_run_layers(char *path, slot_layer_t_array_t *layers, char *o i32 texture_size_x = config_get_texture_res_x(); i32 texture_size_y = config_get_texture_res_y(); - #if defined(IRON_ANDROID) || defined(IRON_IOS) +#if defined(IRON_ANDROID) || defined(IRON_IOS) char *f = sys_title(); - #else +#else char *f = ui_files_filename; - #endif +#endif if (string_equals(f, "")) { f = string_copy(tr("untitled", NULL)); } texture_ldr_format_t format_type = context_raw->format_type; i32 bits = base_bits_handle->i == TEXTURE_BITS_BITS8 ? 8 : 16; - char *ext = bits == 16 ? ".exr" : format_type == TEXTURE_LDR_FORMAT_PNG ? ".png" : ".jpg"; + char *ext = bits == 16 ? ".exr" : format_type == TEXTURE_LDR_FORMAT_PNG ? ".png" : ".jpg"; if (ends_with(f, ext)) { f = string_copy(substring(f, 0, string_length(f) - 4)); } bool is_udim = context_raw->layers_export == EXPORT_MODE_PER_UDIM_TILE; if (is_udim) { - ext = string_join(object_name, ext); + ext = string("%s%s", object_name, ext); } layers_make_temp_img(); @@ -192,10 +192,10 @@ void export_texture_run_layers(char *path, slot_layer_t_array_t *layers, char *o // Append object mask name bool export_selected = context_raw->layers_export == EXPORT_MODE_SELECTED; if (export_selected && slot_layer_get_object_mask(layers->buffer[0]) > 0) { - f = string_join(f, string_join("_", project_paint_objects->buffer[slot_layer_get_object_mask(layers->buffer[0]) - 1]->base->name)); + f = string("%s_%s", f, project_paint_objects->buffer[slot_layer_get_object_mask(layers->buffer[0]) - 1]->base->name); } if (!is_udim && !export_selected && !string_equals(object_name, "")) { - f = string_join(f, string_join("_", object_name)); + f = string("%s_%s", f, object_name); } // Clear export layer @@ -343,34 +343,35 @@ void export_texture_run_layers(char *path, slot_layer_t_array_t *layers, char *o for (i32 i = 0; i < preset->textures->length; ++i) { export_preset_texture_t *t = preset->textures->buffer[i]; string_t_array_t *c = t->channels; - char *tex_name = !string_equals(t->name, "") ? string_join("_", t->name) : ""; + char *tex_name = !string_equals(t->name, "") ? string("_%s", t->name) : ""; bool single_channel = c->buffer[0] == c->buffer[1] && c->buffer[1] == c->buffer[2] && string_equals(c->buffer[3], "1.0"); + char *out_path = string("%s%s%s%s%s", path, PATH_SEP, f, tex_name, ext); if (string_equals(c->buffer[0], "base_r") && string_equals(c->buffer[1], "base_g") && string_equals(c->buffer[2], "base_b") && string_equals(c->buffer[3], "1.0") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint, 1, 0); + export_texture_write_texture(out_path, pixpaint, 1, 0); } else if (string_equals(c->buffer[0], "nor_r") && string_equals(c->buffer[1], "nor_g") && string_equals(c->buffer[2], "nor_b") && string_equals(c->buffer[3], "1.0") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_nor, 1, 0); + export_texture_write_texture(out_path, pixpaint_nor, 1, 0); } else if (string_equals(c->buffer[0], "occ") && string_equals(c->buffer[1], "rough") && string_equals(c->buffer[2], "metal") && string_equals(c->buffer[3], "1.0") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_pack, 1, 0); + export_texture_write_texture(out_path, pixpaint_pack, 1, 0); } else if (single_channel && string_equals(c->buffer[0], "occ") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_pack, 2, 0); + export_texture_write_texture(out_path, pixpaint_pack, 2, 0); } else if (single_channel && string_equals(c->buffer[0], "rough") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_pack, 2, 1); + export_texture_write_texture(out_path, pixpaint_pack, 2, 1); } else if (single_channel && string_equals(c->buffer[0], "metal") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_pack, 2, 2); + export_texture_write_texture(out_path, pixpaint_pack, 2, 2); } else if (single_channel && string_equals(c->buffer[0], "height") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint_pack, 2, 3); + export_texture_write_texture(out_path, pixpaint_pack, 2, 3); } else if (single_channel && string_equals(c->buffer[0], "opac") && string_equals(t->color_space, "linear")) { - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pixpaint, 2, 3); + export_texture_write_texture(out_path, pixpaint, 2, 3); } else { if (pix == NULL) { @@ -430,7 +431,7 @@ void export_texture_run_layers(char *path, slot_layer_t_array_t *layers, char *o export_texture_set_channel(255, pix, i, true); } } - export_texture_write_texture(string_join(string_join(string_join(string_join(path, PATH_SEP), f), tex_name), ext), pix, 3, 0); + export_texture_write_texture(out_path, pix, 3, 0); } } @@ -463,15 +464,15 @@ void export_texture_write_texture(char *file, buffer_t *pixels, i32 type, i32 of } if (context_raw->layers_destination == EXPORT_DESTINATION_PACK_INTO_PROJECT) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA if (format == 2) { // RGB1 export_arm_bgra_swap(pixels); } - #endif +#endif gpu_texture_t *image = gpu_create_texture_from_bytes(pixels, res_x, res_y, GPU_TEXTURE_FORMAT_RGBA32); any_map_set(data_cached_images, file, image); string_t_array_t *ar = string_split(file, PATH_SEP); - char *name = ar->buffer[ar->length - 1]; + char *name = ar->buffer[ar->length - 1]; asset_t *asset = GC_ALLOC_INIT(asset_t, {.name = name, .file = file, .id = project_asset_id++}); any_array_push(project_assets, asset); if (project_raw->assets == NULL) { @@ -508,9 +509,9 @@ i32 _export_texture_channel_bgra_swap(i32 c) { #endif void export_texture_copy_channel(buffer_t *from, i32 from_channel, buffer_t *to, i32 to_channel, bool linear) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA from_channel = _export_texture_channel_bgra_swap(from_channel); - #endif +#endif for (i32 i = 0; i < math_floor((to->length) / (float)4); ++i) { buffer_set_u8(to, i * 4 + to_channel, buffer_get_u8(from, i * 4 + from_channel)); } @@ -520,9 +521,9 @@ void export_texture_copy_channel(buffer_t *from, i32 from_channel, buffer_t *to, } void export_texture_copy_channel_inv(buffer_t *from, i32 from_channel, buffer_t *to, i32 to_channel, bool linear) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA from_channel = _export_texture_channel_bgra_swap(from_channel); - #endif +#endif for (i32 i = 0; i < math_floor((to->length) / (float)4); ++i) { buffer_set_u8(to, i * 4 + to_channel, 255 - buffer_get_u8(from, i * 4 + from_channel)); } @@ -532,9 +533,9 @@ void export_texture_copy_channel_inv(buffer_t *from, i32 from_channel, buffer_t } void export_texture_extract_channel(buffer_t *from, i32 from_channel, buffer_t *to, i32 to_channel, i32 step, i32 mask, bool linear) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA from_channel = _export_texture_channel_bgra_swap(from_channel); - #endif +#endif for (i32 i = 0; i < math_floor((to->length) / (float)4); ++i) { buffer_set_u8(to, i * 4 + to_channel, buffer_get_u8(from, i * 4 + from_channel) % step == mask ? 255 : 0); } diff --git a/paint/sources/history.c b/paint/sources/history.c index d173079c..6843f662 100644 --- a/paint/sources/history.c +++ b/paint/sources/history.c @@ -625,7 +625,7 @@ history_step_t *history_push(char *name) { char *filename = string_equals(project_filepath, "") ? ui_files_filename : substring(project_filepath, string_last_index_of(project_filepath, PATH_SEP) + 1, string_length(project_filepath) - 4); - sys_title_set(string_join(string_join(filename, "* - "), manifest_title)); + sys_title_set(string("%s* - %s", filename, manifest_title)); #endif if (config_raw->touch_ui) { @@ -693,28 +693,30 @@ void history_swap_active() { } void history_copy_to_undo(i32 from_id, i32 to_id, bool is_mask) { + char *to_id_s = i32_to_string(to_id); + char *from_id_s = i32_to_string(from_id); if (is_mask) { - render_path_set_target(string_join("texpaint_undo", i32_to_string(to_id)), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0); - render_path_bind_target(string_join("texpaint", i32_to_string(from_id)), "tex"); + render_path_set_target(string("texpaint_undo%s", to_id_s), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0); + render_path_bind_target(string("texpaint%s", from_id_s), "tex"); // render_path_draw_shader("Scene/copy_pass/copyR8_pass"); render_path_draw_shader("Scene/copy_pass/copy_pass"); } else if (context_raw->layer->texpaint_sculpt != NULL) { - render_path_set_target(string_join("texpaint_sculpt_undo", i32_to_string(to_id)), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0); - render_path_bind_target(string_join("texpaint_sculpt", i32_to_string(from_id)), "tex"); + render_path_set_target(string("texpaint_sculpt_undo%s", to_id_s), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0); + render_path_bind_target(string("texpaint_sculpt%s", from_id_s), "tex"); render_path_draw_shader("Scene/copy_pass/copyRGBA128_pass"); } else { string_t_array_t *additional = any_array_create_from_raw( (void *[]){ - string_join("texpaint_nor_undo", i32_to_string(to_id)), - string_join("texpaint_pack_undo", i32_to_string(to_id)), + string("texpaint_nor_undo%s", to_id_s), + string("texpaint_pack_undo%s", to_id_s), }, 2); - render_path_set_target(string_join("texpaint_undo", i32_to_string(to_id)), additional, NULL, GPU_CLEAR_NONE, 0, 0.0); - render_path_bind_target(string_join("texpaint", i32_to_string(from_id)), "tex0"); - render_path_bind_target(string_join("texpaint_nor", i32_to_string(from_id)), "tex1"); - render_path_bind_target(string_join("texpaint_pack", i32_to_string(from_id)), "tex2"); + render_path_set_target(string("texpaint_undo%s", to_id_s), additional, NULL, GPU_CLEAR_NONE, 0, 0.0); + render_path_bind_target(string("texpaint%s", from_id_s), "tex0"); + render_path_bind_target(string("texpaint_nor%s", from_id_s), "tex1"); + render_path_bind_target(string("texpaint_pack%s", from_id_s), "tex2"); gpu_texture_format_t format = base_bits_handle->i == TEXTURE_BITS_BITS8 ? GPU_TEXTURE_FORMAT_RGBA32 : base_bits_handle->i == TEXTURE_BITS_BITS16 ? GPU_TEXTURE_FORMAT_RGBA64 @@ -723,7 +725,7 @@ void history_copy_to_undo(i32 from_id, i32 to_id, bool is_mask) { char *pipe = format == GPU_TEXTURE_FORMAT_RGBA32 ? "copy_mrt3_pass" : format == GPU_TEXTURE_FORMAT_RGBA64 ? "copy_mrt3RGBA64_pass" : "copy_mrt3RGBA128_pass"; - render_path_draw_shader(string_join("Scene/copy_mrt3_pass/", pipe)); + render_path_draw_shader(string("Scene/copy_mrt3_pass/%s", pipe)); } history_undo_i = (history_undo_i + 1) % config_raw->undo_steps; } diff --git a/paint/sources/import_arm.c b/paint/sources/import_arm.c index c47dfc1a..13912cae 100644 --- a/paint/sources/import_arm.c +++ b/paint/sources/import_arm.c @@ -58,7 +58,7 @@ void import_arm_run_project(char *path) { #if defined(IRON_ANDROID) || defined(IRON_IOS) sys_title_set(ui_files_filename); #else - sys_title_set(string_join(string_join(ui_files_filename, " - "), manifest_title)); + sys_title_set(string("%s - %s", ui_files_filename, manifest_title)); #endif // Import as mesh instead diff --git a/paint/sources/material_nodes/blur_node.c b/paint/sources/material_nodes/blur_node.c index 7f87123a..065a2e46 100644 --- a/paint/sources/material_nodes/blur_node.c +++ b/paint/sources/material_nodes/blur_node.c @@ -11,30 +11,19 @@ char *blur_node_vector(ui_node_t *node, ui_node_socket_t *socket) { return parser_material_parse_vector_input(node->inputs->buffer[0]); } char *strength = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *steps = string_join(string_join("(", strength), " * 10.0 + 1.0)"); - char *tex_name = string_join("texblur_", parser_material_node_name(node, NULL)); - node_shader_add_texture(parser_material_kong, string_join("", tex_name), string_join("_", tex_name)); - node_shader_add_constant(parser_material_kong, string_join(string_join("", tex_name), "_size: float2"), string_join(string_join("_size(_", tex_name), ")")); + char *steps = string("(%s * 10.0 + 1.0)", strength); + char *tex_name = string("texblur_%s", parser_material_node_name(node, NULL)); + node_shader_add_texture(parser_material_kong, tex_name, string("_%s", tex_name)); + node_shader_add_constant(parser_material_kong, string("%s_size: float2", tex_name), string("_size(_%s)", tex_name)); char *store = parser_material_store_var_name(node); - parser_material_write(parser_material_kong, string_join(string_join("var ", store), "_res: float3 = float3(0.0, 0.0, 0.0);")); - parser_material_write(parser_material_kong, string_join(string_join("for (var i: int = 0; i <= int(", steps), " * 2.0); i += 1) {")); - parser_material_write(parser_material_kong, string_join(string_join("for (var j: int = 0; j <= int(", steps), " * 2.0); j += 1) {")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(store, "_res += sample("), tex_name), - ", sampler_linear, tex_coord + float2(float(i) - "), - steps), - ", float(j) - "), - steps), - ") / constants."), - tex_name), - "_size).rgb;")); - parser_material_write(parser_material_kong, "}"); - parser_material_write(parser_material_kong, "}"); + parser_material_write(parser_material_kong, string("var %s_res: float3 = float3(0.0, 0.0, 0.0);", store)); + parser_material_write(parser_material_kong, string("for (var i: int = 0; i <= int(%s * 2.0); i += 1) {", steps)); + parser_material_write(parser_material_kong, string("for (var j: int = 0; j <= int(%s * 2.0); j += 1) {", steps)); parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join(string_join(store, "_res = "), store), "_res / (("), steps), - " * 2.0 + 1.0) * ("), - steps), - " * 2.0 + 1.0));")); - return string_join(store, "_res"); + string("%s_res += sample(%s, sampler_linear, tex_coord + float2(float(i) - %s, float(j) - %s) / constants.%s_size).rgb;", store, + tex_name, steps, steps, tex_name)); + parser_material_write(parser_material_kong, "}"); + parser_material_write(parser_material_kong, "}"); + parser_material_write(parser_material_kong, string("%s_res = %s_res / ((%s * 2.0 + 1.0) * (%s * 2.0 + 1.0));", store, store, steps, steps)); + return string("%s_res", store); } diff --git a/paint/sources/material_nodes/brick_texture_node.c b/paint/sources/material_nodes/brick_texture_node.c index 11599f5c..202748f8 100644 --- a/paint/sources/material_nodes/brick_texture_node.c +++ b/paint/sources/material_nodes/brick_texture_node.c @@ -14,21 +14,12 @@ char *brick_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *col2 = parser_material_parse_vector_input(node->inputs->buffer[2]); char *col3 = parser_material_parse_vector_input(node->inputs->buffer[3]); char *scale = parser_material_parse_value_input(node->inputs->buffer[4], false); - char *res = string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("tex_brick(", co), " * "), scale), ", "), - col1), - ", "), - col2), - ", "), - col3), - ")"); - return res; + return string("tex_brick(%s * %s, %s, %s, %s)", co, scale, col1, col2, col3); } char *brick_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_brick); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[4], false); - char *res = string_join(string_join(string_join(string_join("tex_brick_f(", co), " * "), scale), ")"); - return res; + return string("tex_brick_f(%s * %s)", co, scale); } diff --git a/paint/sources/material_nodes/brightness_contrast_node.c b/paint/sources/material_nodes/brightness_contrast_node.c index 6b0547c7..92b0d9f7 100644 --- a/paint/sources/material_nodes/brightness_contrast_node.c +++ b/paint/sources/material_nodes/brightness_contrast_node.c @@ -11,5 +11,5 @@ char *brightness_contrast_node_vector(ui_node_t *node, ui_node_socket_t *socket) char *bright = parser_material_parse_value_input(node->inputs->buffer[1], false); char *contr = parser_material_parse_value_input(node->inputs->buffer[2], false); node_shader_add_function(parser_material_kong, str_brightcontrast); - return string_join(string_join(string_join(string_join(string_join(string_join("brightcontrast(", out_col), ", "), bright), ", "), contr), ")"); + return string("brightcontrast(%s, %s, %s)", out_col, bright, contr); } diff --git a/paint/sources/material_nodes/bump_node.c b/paint/sources/material_nodes/bump_node.c index 24565aba..564c645a 100644 --- a/paint/sources/material_nodes/bump_node.c +++ b/paint/sources/material_nodes/bump_node.c @@ -11,18 +11,8 @@ char *bump_node_vector(ui_node_t *node, ui_node_socket_t *socket) { // char *distance = parser_material_parse_value_input(node->inputs->buffer[1], false); char *height = parser_material_parse_value_input(node->inputs->buffer[2], false); char *nor = parser_material_parse_vector_input(node->inputs->buffer[3]); - char *sample_bump_res = string_join(parser_material_store_var_name(node), "_bump"); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", sample_bump_res), "_x: float = ddx(float("), height), - ")) * ("), - strength), - ") * 16.0;")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", sample_bump_res), "_y: float = ddy(float("), height), - ")) * ("), - strength), - ") * 16.0;")); - return string_join( - string_join(string_join(string_join(string_join(string_join("(normalize(float3(", sample_bump_res), "_x, "), sample_bump_res), "_y, 1.0) + "), nor), - ") * float3(0.5, 0.5, 0.5) + float3(0.5, 0.5, 0.5))"); + char *sample_bump_res = string("%s_bump", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s_x: float = ddx(float(%s)) * (%s) * 16.0;", sample_bump_res, height, strength)); + parser_material_write(parser_material_kong, string("var %s_y: float = ddy(float(%s)) * (%s) * 16.0;", sample_bump_res, height, strength)); + return string("(normalize(float3(%s_x, %s_y, 1.0) + %s) * float3(0.5, 0.5, 0.5) + float3(0.5, 0.5, 0.5))", sample_bump_res, sample_bump_res, nor); } diff --git a/paint/sources/material_nodes/camera_texture_node.c b/paint/sources/material_nodes/camera_texture_node.c index d51b0831..23a976d8 100644 --- a/paint/sources/material_nodes/camera_texture_node.c +++ b/paint/sources/material_nodes/camera_texture_node.c @@ -7,10 +7,9 @@ void camera_texture_node_init() { } char *camera_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *tex_name = string_join("texcamera_", parser_material_node_name(node, NULL)); - node_shader_add_texture(parser_material_kong, string_join("", tex_name), "_camera_texture"); + char *tex_name = string("texcamera_%s", parser_material_node_name(node, NULL)); + node_shader_add_texture(parser_material_kong, tex_name, "_camera_texture"); char *store = parser_material_store_var_name(node); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_res: float3 = sample("), tex_name), - ", sampler_linear, tex_coord).rgb;")); - return string_join(store, "_res"); + parser_material_write(parser_material_kong, string("var %s_res: float3 = sample(%s, sampler_linear, tex_coord).rgb;", store, tex_name)); + return string("%s_res", store); } diff --git a/paint/sources/material_nodes/checker_texture_node.c b/paint/sources/material_nodes/checker_texture_node.c index 41cdc4a1..a0f3e204 100644 --- a/paint/sources/material_nodes/checker_texture_node.c +++ b/paint/sources/material_nodes/checker_texture_node.c @@ -13,17 +13,12 @@ char *checker_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *col1 = parser_material_parse_vector_input(node->inputs->buffer[1]); char *col2 = parser_material_parse_vector_input(node->inputs->buffer[2]); char *scale = parser_material_parse_value_input(node->inputs->buffer[3], false); - char *res = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("tex_checker(", co), ", "), col1), ", "), col2), ", "), - scale), - ")"); - return res; + return string("tex_checker(%s, %s, %s, %s)", co, col1, col2, scale); } char *checker_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_checker); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[3], false); - char *res = string_join(string_join(string_join(string_join("tex_checker_f(", co), ", "), scale), ")"); - return res; + return string("tex_checker_f(%s, %s)", co, scale); } diff --git a/paint/sources/material_nodes/clamp_node.c b/paint/sources/material_nodes/clamp_node.c index a2804f1c..8ae95e81 100644 --- a/paint/sources/material_nodes/clamp_node.c +++ b/paint/sources/material_nodes/clamp_node.c @@ -7,23 +7,16 @@ void clamp_node_init() { } char *clamp_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *val = parser_material_parse_value_input(node->inputs->buffer[0], false); - char *min = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *max = parser_material_parse_value_input(node->inputs->buffer[2], false); + char *val = parser_material_parse_value_input(node->inputs->buffer[0], false); + char *min = parser_material_parse_value_input(node->inputs->buffer[1], false); + char *max = parser_material_parse_value_input(node->inputs->buffer[2], false); ui_node_button_t *but = node->buttons->buffer[0]; // operation; - char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); op = string_copy(string_replace_all(op, " ", "_")); if (string_equals(op, "MIN_MAX")) { - return string_join(string_join(string_join(string_join(string_join(string_join("(clamp(", val), ", "), min), ", "), max), "))"); + return string("(clamp(%s, %s, %s))", val, min, max); } else { // RANGE - return string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("(clamp(", val), ", min("), min), ", "), - max), - "), max("), - min), - ", "), - max), - ")))"); + return string("(clamp(%s, min(%s, %s), max(%s, %s)))", val, min, max, min, max); } } diff --git a/paint/sources/material_nodes/color_mask_node.c b/paint/sources/material_nodes/color_mask_node.c index 192da940..82743b16 100644 --- a/paint/sources/material_nodes/color_mask_node.c +++ b/paint/sources/material_nodes/color_mask_node.c @@ -11,15 +11,6 @@ char *color_mask_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *mask_color = parser_material_parse_vector_input(node->inputs->buffer[1]); char *radius = parser_material_parse_value_input(node->inputs->buffer[2], false); char *fuzziness = parser_material_parse_value_input(node->inputs->buffer[3], false); - return string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("clamp(1.0 - (distance(", input_color), ", "), mask_color), - ") - "), - radius), - ") / max("), - fuzziness), - ", "), - f32_to_string(parser_material_eps)), - "), 0.0, 1.0)"); + return string("clamp(1.0 - (distance(%s, %s) - %s) / max(%s, %s), 0.0, 1.0)", input_color, mask_color, radius, fuzziness, + f32_to_string(parser_material_eps)); } diff --git a/paint/sources/material_nodes/color_ramp_node.c b/paint/sources/material_nodes/color_ramp_node.c index abc0653f..24137901 100644 --- a/paint/sources/material_nodes/color_ramp_node.c +++ b/paint/sources/material_nodes/color_ramp_node.c @@ -8,94 +8,51 @@ void color_ramp_node_init() { } char *color_ramp_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); + char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); i32 data0 = node->buttons->buffer[0]->data->buffer[0]; - char *interp = data0 == 0 ? "LINEAR" : "CONSTANT"; + char *interp = data0 == 0 ? "LINEAR" : "CONSTANT"; f32_array_t *elems = node->buttons->buffer[0]->default_value; i32 len = elems->length / (float)5; if (len == 1) { return parser_material_vec3(elems); } // Write cols array - char *cols_var = string_join(parser_material_node_name(node, NULL), "_cols"); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("var ", cols_var), ": float3["), i32_to_string(len)), "];")); // TODO: Make const + char *cols_var = string("%s_cols", parser_material_node_name(node, NULL)); + parser_material_write(parser_material_kong, string("var %s: float3[%s];", cols_var, i32_to_string(len))); // TODO: Make const for (i32 i = 0; i < len; ++i) { f32_array_t *tmp = f32_array_create_from_raw((f32[]){}, 0); f32_array_push(tmp, elems->buffer[i * 5]); f32_array_push(tmp, elems->buffer[i * 5 + 1]); f32_array_push(tmp, elems->buffer[i * 5 + 2]); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join(string_join(cols_var, "["), i32_to_string(i)), "] = "), - parser_material_vec3(tmp)), - ";")); + parser_material_write(parser_material_kong, string("%s[%s] = %s;", cols_var, i32_to_string(i), parser_material_vec3(tmp))); } // Get index - char *fac_var = string_join(parser_material_node_name(node, NULL), "_fac"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", fac_var), ": float = "), fac), ";")); + char *fac_var = string("%s_fac", parser_material_node_name(node, NULL)); + parser_material_write(parser_material_kong, string("var %s: float = %s;", fac_var, fac)); char *index = "0"; for (i32 i = 1; i < len; ++i) { f32 e = elems->buffer[i * 5 + 4]; - index = string_join(index, string_join(string_join(string_join(string_join(" + (", fac_var), " > "), f32_to_string(e)), " ? 1 : 0)")); + index = string("%s + (%s > %s ? 1 : 0)", index, fac_var, f32_to_string(e)); } // Write index - char *index_var = string_join(parser_material_node_name(node, NULL), "_i"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", index_var), ": int = "), index), ";")); + char *index_var = string("%s_i", parser_material_node_name(node, NULL)); + parser_material_write(parser_material_kong, string("var %s: int = %s;", index_var, index)); if (string_equals(interp, "CONSTANT")) { - return string_join(string_join(string_join(cols_var, "["), index_var), "]"); + return string("%s[%s]", cols_var, index_var); } else { // Linear // Write facs array - char *facs_var = string_join(parser_material_node_name(node, NULL), "_facs"); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("var ", facs_var), ": float["), i32_to_string(len)), "];")); // TODO: Make const + char *facs_var = string("%s_facs", parser_material_node_name(node, NULL)); + parser_material_write(parser_material_kong, string("var %s: float[%s];", facs_var, i32_to_string(len))); // TODO: Make const for (i32 i = 0; i < len; ++i) { f32 e = elems->buffer[i * 5 + 4]; - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(facs_var, "["), i32_to_string(i)), "] = "), f32_to_string(e)), - ";")); + parser_material_write(parser_material_kong, string("%s[%s] = %s;", facs_var, i32_to_string(i), f32_to_string(e))); } // Mix color // float f = (pos - start) * (1.0 / (finish - start)) // TODO: index_var + 1 out of bounds - return string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join("lerp3(", cols_var), - "["), - index_var), - "], "), - cols_var), - "["), - index_var), - " + 1], ("), - fac_var), - " - "), - facs_var), - "["), - index_var), - "]) * (1.0 / ("), - facs_var), - "["), - index_var), - " + 1] - "), - facs_var), - "["), - index_var), - "]) ))"); + return string("lerp3(%s[%s], %s[%s + 1], (%s - %s[%s]) * (1.0 / (%s[%s + 1] - %s[%s])) ))", cols_var, index_var, cols_var, index_var, fac_var, facs_var, + index_var, facs_var, index_var, facs_var, index_var); } } diff --git a/paint/sources/material_nodes/combine_xyz_node.c b/paint/sources/material_nodes/combine_xyz_node.c index e62bf993..ee70ab09 100644 --- a/paint/sources/material_nodes/combine_xyz_node.c +++ b/paint/sources/material_nodes/combine_xyz_node.c @@ -10,5 +10,5 @@ char *combine_xyz_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *x = parser_material_parse_value_input(node->inputs->buffer[0], false); char *y = parser_material_parse_value_input(node->inputs->buffer[1], false); char *z = parser_material_parse_value_input(node->inputs->buffer[2], false); - return string_join(string_join(string_join(string_join(string_join(string_join("float3(", x), ", "), y), ", "), z), ")"); + return string("float3(%s, %s, %s)", x, y, z); } diff --git a/paint/sources/material_nodes/curvature_bake_node.c b/paint/sources/material_nodes/curvature_bake_node.c index f425312c..72a9d162 100644 --- a/paint/sources/material_nodes/curvature_bake_node.c +++ b/paint/sources/material_nodes/curvature_bake_node.c @@ -19,10 +19,9 @@ char *curvature_bake_node_value(ui_node_t *node, ui_node_socket_t *socket) { gc_root(parser_material_bake_passthrough_offset); return "0.0"; } - char *tex_name = string_join("texbake_", parser_material_node_name(node, NULL)); - node_shader_add_texture(parser_material_kong, string_join("", tex_name), string_join("_", tex_name)); + char *tex_name = string("texbake_%s", parser_material_node_name(node, NULL)); + node_shader_add_texture(parser_material_kong, tex_name, string("_%s", tex_name)); char *store = parser_material_store_var_name(node); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_res: float = sample("), tex_name), - ", sampler_linear, tex_coord).r;")); - return string_join(store, "_res"); + parser_material_write(parser_material_kong, string("var %s_res: float = sample(%s, sampler_linear, tex_coord).r;", store, tex_name)); + return string("%s_res", store); } diff --git a/paint/sources/material_nodes/fresnel_node.c b/paint/sources/material_nodes/fresnel_node.c index 8426a224..c6c5fb0d 100644 --- a/paint/sources/material_nodes/fresnel_node.c +++ b/paint/sources/material_nodes/fresnel_node.c @@ -7,7 +7,7 @@ void fresnel_node_init() { } char *fresnel_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *ior = parser_material_parse_value_input(node->inputs->buffer[0], false); + char *ior = parser_material_parse_value_input(node->inputs->buffer[0], false); parser_material_kong->frag_dotnv = true; - return string_join(string_join("pow(1.0 - dotnv, 7.25 / ", ior), ")"); + return string("pow(1.0 - dotnv, 7.25 / %s)", ior); } diff --git a/paint/sources/material_nodes/gabor_texture_node.c b/paint/sources/material_nodes/gabor_texture_node.c index 84ae7dc8..f098724a 100644 --- a/paint/sources/material_nodes/gabor_texture_node.c +++ b/paint/sources/material_nodes/gabor_texture_node.c @@ -13,21 +13,14 @@ char *gabor_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *frequency = parser_material_parse_value_input(node->inputs->buffer[2], false); char *anisotropy = parser_material_parse_value_input(node->inputs->buffer[3], false); char *orientation = parser_material_parse_vector_input(node->inputs->buffer[4]); - char *res = string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("tex_gabor(", co), ", "), scale), ", "), - frequency), - ", "), - anisotropy), - ", "), - orientation), - ")"); + char *res = string("tex_gabor(%s, %s, %s, %s, %s)", co, scale, frequency, anisotropy, orientation); if (socket == node->outputs->buffer[0]) { // Value - return string_join(res, ".x"); + return string("%s.x", res); } else if (socket == node->outputs->buffer[1]) { // Phase - return string_join(res, ".y"); + return string("%s.y", res); } else { // Intensity - return string_join(res, ".z"); + return string("%s.z", res); } } diff --git a/paint/sources/material_nodes/gamma_node.c b/paint/sources/material_nodes/gamma_node.c index b2af17d1..ab1471af 100644 --- a/paint/sources/material_nodes/gamma_node.c +++ b/paint/sources/material_nodes/gamma_node.c @@ -9,5 +9,5 @@ void gamma_node_init() { char *gamma_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *out_col = parser_material_parse_vector_input(node->inputs->buffer[0]); char *gamma = parser_material_parse_value_input(node->inputs->buffer[1], false); - return string_join(string_join(string_join(string_join("pow3(", out_col), ", "), parser_material_to_vec3(gamma)), ")"); + return string("pow3(%s, %s)", out_col, parser_material_to_vec3(gamma)); } diff --git a/paint/sources/material_nodes/geometry_node.c b/paint/sources/material_nodes/geometry_node.c index 60bdacee..9a050a00 100644 --- a/paint/sources/material_nodes/geometry_node.c +++ b/paint/sources/material_nodes/geometry_node.c @@ -40,37 +40,18 @@ char *geometry_node_value(ui_node_t *node, ui_node_socket_t *socket) { // return "(1.0 - float(gl_FrontFacing))"; } else if (socket == node->outputs->buffer[7]) { // Pointiness - f32 strength = 1.0; - f32 radius = 1.0; - f32 offset = 0.0; - char *store = parser_material_store_var_name(node); + f32 strength = 1.0; + f32 radius = 1.0; + f32 offset = 0.0; + char *store = parser_material_store_var_name(node); parser_material_kong->frag_n = true; - parser_material_write(parser_material_kong, string_join(string_join("var ", store), "_dx: float3 = ddx3(n);")); - parser_material_write(parser_material_kong, string_join(string_join("var ", store), "_dy: float3 = ddy3(n);")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("var ", store), - "_curvature: float = max(dot("), - store), - "_dx, "), - store), - "_dx), dot("), - store), - "_dy, "), - store), - "_dy));")); - parser_material_write( - parser_material_kong, - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(store, "_curvature = clamp(pow("), store), - "_curvature, (1.0 / "), - f32_to_string(radius)), - ") * 0.25) * "), - f32_to_string(strength)), - " * 2.0 + "), - f32_to_string(offset)), - " / 10.0, 0.0, 1.0);")); - return string_join(store, "_curvature"); + parser_material_write(parser_material_kong, string("var %s_dx: float3 = ddx3(n);", store)); + parser_material_write(parser_material_kong, string("var %s_dy: float3 = ddy3(n);", store)); + parser_material_write(parser_material_kong, + string("var %s_curvature: float = max(dot(%s_dx, %s_dx), dot(%s_dy, %s_dy));", store, store, store, store, store)); + parser_material_write(parser_material_kong, string("%s_curvature = clamp(pow(%s_curvature, (1.0 / %s) * 0.25) * %s * 2.0 + %s / 10.0, 0.0, 1.0);", + store, store, f32_to_string(radius), f32_to_string(strength), f32_to_string(offset))); + return string("%s_curvature", store); } else { // Random Per Island return "0.0"; diff --git a/paint/sources/material_nodes/gradient_texture_node.c b/paint/sources/material_nodes/gradient_texture_node.c index aa9b307e..c7c516c2 100644 --- a/paint/sources/material_nodes/gradient_texture_node.c +++ b/paint/sources/material_nodes/gradient_texture_node.c @@ -9,7 +9,7 @@ void gradient_texture_node_init() { char *parser_material_get_gradient(char *grad, char *co) { if (string_equals(grad, "LINEAR")) { - return string_join(co, ".x"); + return string("%s.x", co); } else if (string_equals(grad, "QUADRATIC")) { return "0.0"; @@ -18,48 +18,33 @@ char *parser_material_get_gradient(char *grad, char *co) { return "0.0"; } else if (string_equals(grad, "DIAGONAL")) { - return string_join(string_join(string_join(string_join("(", co), ".x + "), co), ".y) * 0.5"); + return string("(%s.x + %s.y) * 0.5", co, co); } else if (string_equals(grad, "RADIAL")) { - return string_join(string_join(string_join(string_join("atan2(", co), ".x, "), co), ".y) / (3.141592 * 2.0) + 0.5"); + return string("atan2(%s.x, %s.y) / (3.141592 * 2.0) + 0.5", co, co); } else if (string_equals(grad, "QUADRATIC_SPHERE")) { return "0.0"; } else { // "SPHERICAL" - return string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("max(1.0 - sqrt(", co), ".x * "), co), - ".x + "), - co), - ".y * "), - co), - ".y + "), - co), - ".z * "), - co), - ".z), 0.0)"); + return string("max(1.0 - sqrt(%s.x * %s.x + %s.y * %s.y + %s.z * %s.z), 0.0)", co, co, co, co, co, co); } } char *gradient_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *co = parser_material_get_coord(node); + char *co = parser_material_get_coord(node); ui_node_button_t *but = node->buttons->buffer[0]; // gradient_type; - char *grad = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *grad = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); grad = string_copy(string_replace_all(grad, " ", "_")); - char *f = parser_material_get_gradient(grad, co); - char *res = parser_material_to_vec3(string_join(string_join("clamp(", f), ", 0.0, 1.0)")); - return res; + char *f = parser_material_get_gradient(grad, co); + return parser_material_to_vec3(string("clamp(%s, 0.0, 1.0)", f)); } char *gradient_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *co = parser_material_get_coord(node); + char *co = parser_material_get_coord(node); ui_node_button_t *but = node->buttons->buffer[0]; // gradient_type; - char *grad = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *grad = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); grad = string_copy(string_replace_all(grad, " ", "_")); - char *f = parser_material_get_gradient(grad, co); - char *res = string_join(string_join("(clamp(", f), ", 0.0, 1.0))"); - return res; + char *f = parser_material_get_gradient(grad, co); + return string("(clamp(%s, 0.0, 1.0))", f); } diff --git a/paint/sources/material_nodes/group_node.c b/paint/sources/material_nodes/group_node.c index baca99a2..685a108b 100644 --- a/paint/sources/material_nodes/group_node.c +++ b/paint/sources/material_nodes/group_node.c @@ -22,11 +22,11 @@ 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_join(string_join(tr("Group", NULL), " "), i32_to_string(i)); + node->name = string("%s %s", tr("Group", NULL), 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; + char *cname = g->canvas->name; if (string_equals(cname, node->name)) { found = true; break; @@ -82,7 +82,7 @@ void nodes_material_new_group_button(i32 node_id) { 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; + char *cname = g->canvas->name; if (string_equals(cname, node->name)) { group = g; break; @@ -195,7 +195,7 @@ char *nodes_material_get_socket_name(char *type) { } 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) { + 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, diff --git a/paint/sources/material_nodes/hue_saturation_value_node.c b/paint/sources/material_nodes/hue_saturation_value_node.c index 62fd1fb7..5683cedd 100644 --- a/paint/sources/material_nodes/hue_saturation_value_node.c +++ b/paint/sources/material_nodes/hue_saturation_value_node.c @@ -13,13 +13,5 @@ char *hue_saturation_value_node_vector(ui_node_t *node, ui_node_socket_t *socket char *val = parser_material_parse_value_input(node->inputs->buffer[2], false); char *fac = parser_material_parse_value_input(node->inputs->buffer[3], false); char *col = parser_material_parse_vector_input(node->inputs->buffer[4]); - return string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("hue_sat(", col), ", float4("), hue), " - 0.5, "), - sat), - ", "), - val), - ", 1.0 - "), - fac), - "))"); + return string("hue_sat(%s, float4(%s - 0.5, %s, %s, 1.0 - %s))", col, hue, sat, val, fac); } diff --git a/paint/sources/material_nodes/image_texture_node.c b/paint/sources/material_nodes/image_texture_node.c index dc4780cc..3595dcac 100644 --- a/paint/sources/material_nodes/image_texture_node.c +++ b/paint/sources/material_nodes/image_texture_node.c @@ -10,7 +10,7 @@ void image_texture_node_init() { char *parser_material_texture_store(ui_node_t *node, bind_tex_t *tex, char *tex_name, i32 color_space) { any_array_push(parser_material_matcon->bind_textures, tex); node_shader_context_add_elem(parser_material_kong->context, "tex", "short2norm"); - node_shader_add_texture(parser_material_kong, string_join("", tex_name), NULL); + node_shader_add_texture(parser_material_kong, tex_name, NULL); char *uv_name = ""; if (string_equals(node->type, "TEX_IMAGE") && parser_material_get_input_link(node->inputs->buffer[0]) != NULL) { uv_name = string_copy(parser_material_parse_vector_input(node->inputs->buffer[0])); @@ -20,102 +20,51 @@ char *parser_material_texture_store(ui_node_t *node, bind_tex_t *tex, char *tex_ } char *tex_store = parser_material_store_var_name(node); if (parser_material_sample_keep_aspect) { - node_shader_add_constant(parser_material_kong, string_join(tex_name, "_size: float2"), string_join(string_join("_size(", tex_name), ")")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("var ", tex_store), "_size: float2 = constants."), tex_name), "_size;")); + node_shader_add_constant(parser_material_kong, string("%s_size: float2", tex_name), string("_size(%s)", tex_name)); + parser_material_write(parser_material_kong, string("var %s_size: float2 = constants.%s_size;", tex_store, tex_name)); + parser_material_write(parser_material_kong, string("var %s_ax: float = %s_size.x / %s_size.y;", tex_store, tex_store, tex_store)); + parser_material_write(parser_material_kong, string("var %s_ay: float = %s_size.y / %s_size.x;", tex_store, tex_store, tex_store)); parser_material_write( parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", tex_store), "_ax: float = "), tex_store), "_size.x / "), tex_store), - "_size.y;")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", tex_store), "_ay: float = "), tex_store), "_size.y / "), tex_store), - "_size.x;")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("var ", tex_store), - "_uv: float2 = (("), - uv_name), - ".xy / float("), - parser_material_sample_uv_scale), - ") - float2(0.5, 0.5)) * float2(max("), - tex_store), - "_ay, 1.0), max("), - tex_store), - "_ax, 1.0))) + float2(0.5, 0.5);")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("if (", tex_store), "_uv.x < 0.0 || "), tex_store), - "_uv.y < 0.0 || "), - tex_store), - "_uv.x > 1.0 || "), - tex_store), - "_uv.y > 1.0) { discard; }")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(tex_store, "_uv = "), tex_store), "_uv * float("), - parser_material_sample_uv_scale), - ");")); - uv_name = string_join(tex_store, "_uv"); + string("var %s_uv: float2 = ((%s.xy / float(%s) - float2(0.5, 0.5)) * float2(max(%s_ay, 1.0), max(%s_ax, 1.0))) + float2(0.5, 0.5);", tex_store, + uv_name, parser_material_sample_uv_scale, tex_store, tex_store)); + parser_material_write(parser_material_kong, string("if (%s_uv.x < 0.0 || %s_uv.y < 0.0 || %s_uv.x > 1.0 || %s_uv.y > 1.0) { discard; }", tex_store, + tex_store, tex_store, tex_store)); + parser_material_write(parser_material_kong, string("%s_uv = %s_uv * float(%s);", tex_store, tex_store, parser_material_sample_uv_scale)); + uv_name = string("%s_uv", tex_store); } if (parser_material_triplanar) { - parser_material_write(parser_material_kong, string_join(string_join("var ", tex_store), ": float4 = float4(0.0, 0.0, 0.0, 0.0);")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (tex_coord_blend.x > 0.0) {", tex_store), " += sample("), tex_name), - ", sampler_linear, "), - uv_name), - ".xy) * tex_coord_blend.x; }")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (tex_coord_blend.y > 0.0) {", tex_store), " += sample("), tex_name), - ", sampler_linear, "), - uv_name), - "1.xy) * tex_coord_blend.y; }")); - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (tex_coord_blend.z > 0.0) {", tex_store), " += sample("), tex_name), - ", sampler_linear, "), - uv_name), - "2.xy) * tex_coord_blend.z; }")); + parser_material_write(parser_material_kong, string("var %s: float4 = float4(0.0, 0.0, 0.0, 0.0);", tex_store)); + parser_material_write(parser_material_kong, string("if (tex_coord_blend.x > 0.0) {%s += sample(%s, sampler_linear, %s.xy) * tex_coord_blend.x; }", + tex_store, tex_name, uv_name)); + parser_material_write(parser_material_kong, string("if (tex_coord_blend.y > 0.0) {%s += sample(%s, sampler_linear, %s1.xy) * tex_coord_blend.y; }", + tex_store, tex_name, uv_name)); + parser_material_write(parser_material_kong, string("if (tex_coord_blend.z > 0.0) {%s += sample(%s, sampler_linear, %s2.xy) * tex_coord_blend.z; }", + tex_store, tex_name, uv_name)); } else { if (parser_material_is_frag) { - any_map_set(parser_material_texture_map, tex_store, - string_join(string_join(string_join(string_join("sample(", tex_name), ", sampler_linear, "), uv_name), ".xy)")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", tex_store), ": float4 = sample("), tex_name), - ", sampler_linear, "), - uv_name), - ".xy);")); + any_map_set(parser_material_texture_map, tex_store, string("sample(%s, sampler_linear, %s.xy)", tex_name, uv_name)); + parser_material_write(parser_material_kong, string("var %s: float4 = sample(%s, sampler_linear, %s.xy);", tex_store, tex_name, uv_name)); } else { - any_map_set(parser_material_texture_map, tex_store, - string_join(string_join(string_join(string_join("sample_lod(", tex_name), ", sampler_linear, "), uv_name), ".xy, 0.0)")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", tex_store), ": float4 = sample_lod("), - tex_name), - ", sampler_linear, "), - uv_name), - ".xy, 0.0);")); + any_map_set(parser_material_texture_map, tex_store, string("sample_lod(%s, sampler_linear, %s.xy, 0.0)", tex_name, uv_name)); + parser_material_write(parser_material_kong, string("var %s: float4 = sample_lod(%s, sampler_linear, %s.xy, 0.0);", tex_store, tex_name, uv_name)); } if (!ends_with(tex->file, ".jpg")) { // Pre-mult alpha - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(tex_store, ".rgb = "), tex_store), ".rgb * "), tex_store), - ".a;")); + parser_material_write(parser_material_kong, string("%s.rgb = %s.rgb * %s.a;", tex_store, tex_store, tex_store)); } } if (parser_material_transform_color_space) { // Base color socket auto-converts from sRGB to linear if (color_space == COLOR_SPACE_LINEAR && parser_material_parsing_basecolor) { // Linear to sRGB - parser_material_write(parser_material_kong, - string_join(string_join(string_join(tex_store, ".rgb = pow3("), tex_store), ".rgb, float3(2.2, 2.2, 2.2));")); + parser_material_write(parser_material_kong, string("%s.rgb = pow3(%s.rgb, float3(2.2, 2.2, 2.2));", tex_store, tex_store)); } else if (color_space == COLOR_SPACE_SRGB && !parser_material_parsing_basecolor) { // sRGB to linear - parser_material_write(parser_material_kong, string_join(string_join(string_join(tex_store, ".rgb = pow3("), tex_store), - ".rgb, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2));")); + parser_material_write(parser_material_kong, string("%s.rgb = pow3(%s.rgb, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2));", tex_store, tex_store)); } else if (color_space == COLOR_SPACE_DIRECTX_NORMAL_MAP) { // DirectX normal map to OpenGL normal map - parser_material_write(parser_material_kong, string_join(string_join(string_join(tex_store, ".y = 1.0 - "), tex_store), ".y;")); + parser_material_write(parser_material_kong, string("%s.y = 1.0 - %s.y;", tex_store, tex_store)); } } return tex_store; @@ -137,19 +86,19 @@ char *image_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { // Already fetched if (char_ptr_array_index_of(parser_material_parsed, parser_material_res_var_name(node, node->outputs->buffer[1])) >= 0) { // TODO: node.outputs[0] char *varname = parser_material_store_var_name(node); - return string_join(varname, ".rgb"); + return string("%s.rgb", varname); } - char *tex_name = parser_material_node_name(node, NULL); + char *tex_name = parser_material_node_name(node, NULL); bind_tex_t *tex = parser_material_make_texture(node, tex_name); if (tex != NULL) { - i32 color_space = node->buttons->buffer[1]->default_value->buffer[0]; + i32 color_space = node->buttons->buffer[1]->default_value->buffer[0]; char *texstore = parser_material_texture_store(node, tex, tex_name, color_space); - return string_join(texstore, ".rgb"); + return string("%s.rgb", texstore); } else { char *tex_store = parser_material_store_var_name(node); // Pink color for missing texture - parser_material_write(parser_material_kong, string_join(string_join("var ", tex_store), ": float4 = float4(1.0, 0.0, 1.0, 1.0);")); - return string_join(tex_store, ".rgb"); + parser_material_write(parser_material_kong, string("var %s: float4 = float4(1.0, 0.0, 1.0, 1.0);", tex_store)); + return string("%s.rgb", tex_store); } } @@ -157,14 +106,14 @@ char *image_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { // Already fetched if (char_ptr_array_index_of(parser_material_parsed, parser_material_res_var_name(node, node->outputs->buffer[0])) >= 0) { // TODO: node.outputs[1] char *varname = parser_material_store_var_name(node); - return string_join(varname, ".a"); + return string("%s.a", varname); } - char *tex_name = parser_material_node_name(node, NULL); + char *tex_name = parser_material_node_name(node, NULL); bind_tex_t *tex = parser_material_make_texture(node, tex_name); if (tex != NULL) { - i32 color_space = node->buttons->buffer[1]->default_value->buffer[0]; + i32 color_space = node->buttons->buffer[1]->default_value->buffer[0]; char *texstore = parser_material_texture_store(node, tex, tex_name, color_space); - return string_join(texstore, ".a"); + return string("%s.a", texstore); } return "0.0"; } diff --git a/paint/sources/material_nodes/invert_color_node.c b/paint/sources/material_nodes/invert_color_node.c index 491194f8..08bddf8c 100644 --- a/paint/sources/material_nodes/invert_color_node.c +++ b/paint/sources/material_nodes/invert_color_node.c @@ -9,6 +9,5 @@ void invert_color_node_init() { char *invert_color_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); char *out_col = parser_material_parse_vector_input(node->inputs->buffer[1]); - return string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", out_col), ", float3(1.0, 1.0, 1.0) - ("), out_col), "), "), fac), - ")"); + return string("lerp3(%s, float3(1.0, 1.0, 1.0) - (%s), %s)", out_col, out_col, fac); } diff --git a/paint/sources/material_nodes/layer_mask_node.c b/paint/sources/material_nodes/layer_mask_node.c index 6320025a..e9f18562 100644 --- a/paint/sources/material_nodes/layer_mask_node.c +++ b/paint/sources/material_nodes/layer_mask_node.c @@ -8,6 +8,6 @@ void layer_mask_node_init() { char *layer_mask_node_value(ui_node_t *node, ui_node_socket_t *socket) { i32 l = node->buttons->buffer[0]->default_value->buffer[0]; - node_shader_add_texture(parser_material_kong, string_join("texpaint", i32_to_string(l)), string_join("_texpaint", i32_to_string(l))); - return string_join(string_join("sample(texpaint", i32_to_string(l)), ", sampler_linear, tex_coord).r"); + node_shader_add_texture(parser_material_kong, string("texpaint%s", i32_to_string(l)), string("_texpaint%s", i32_to_string(l))); + return string("sample(texpaint%s, sampler_linear, tex_coord).r", i32_to_string(l)); } diff --git a/paint/sources/material_nodes/layer_node.c b/paint/sources/material_nodes/layer_node.c index 77728f4b..98c594f3 100644 --- a/paint/sources/material_nodes/layer_node.c +++ b/paint/sources/material_nodes/layer_node.c @@ -8,41 +8,43 @@ void layer_node_init() { } char *layer_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - i32 l = node->buttons->buffer[0]->default_value->buffer[0]; + i32 l = node->buttons->buffer[0]->default_value->buffer[0]; + char *ls = i32_to_string(l); if (socket == node->outputs->buffer[0]) { // Base - node_shader_add_texture(parser_material_kong, string_join("texpaint", i32_to_string(l)), string_join("_texpaint", i32_to_string(l))); - return string_join(string_join("sample(texpaint", i32_to_string(l)), ", sampler_linear, tex_coord).rgb"); + node_shader_add_texture(parser_material_kong, string("texpaint%s", ls), string("_texpaint%s", ls)); + return string("sample(texpaint%s, sampler_linear, tex_coord).rgb", ls); } else { // Normal - node_shader_add_texture(parser_material_kong, string_join("texpaint_nor", i32_to_string(l)), string_join("_texpaint_nor", i32_to_string(l))); - return string_join(string_join("sample(texpaint_nor", i32_to_string(l)), ", sampler_linear, tex_coord).rgb"); + node_shader_add_texture(parser_material_kong, string("texpaint_nor%s", ls), string("_texpaint_nor%s", ls)); + return string("sample(texpaint_nor%s, sampler_linear, tex_coord).rgb", ls); } } char *layer_node_value(ui_node_t *node, ui_node_socket_t *socket) { - i32 l = node->buttons->buffer[0]->default_value->buffer[0]; + i32 l = node->buttons->buffer[0]->default_value->buffer[0]; + char *ls = i32_to_string(l); if (socket == node->outputs->buffer[1]) { // Opac - node_shader_add_texture(parser_material_kong, string_join("texpaint", i32_to_string(l)), string_join("_texpaint", i32_to_string(l))); - return string_join(string_join("sample(texpaint", i32_to_string(l)), ", sampler_linear, tex_coord).a"); + node_shader_add_texture(parser_material_kong, string("texpaint%s", ls), string("_texpaint%s", ls)); + return string("sample(texpaint%s, sampler_linear, tex_coord).a", ls); } else if (socket == node->outputs->buffer[2]) { // Occ - node_shader_add_texture(parser_material_kong, string_join("texpaint_pack", i32_to_string(l)), string_join("_texpaint_pack", i32_to_string(l))); - return string_join(string_join("sample(texpaint_pack", i32_to_string(l)), ", sampler_linear, tex_coord).r"); + node_shader_add_texture(parser_material_kong, string("texpaint_pack%s", ls), string("_texpaint_pack%s", ls)); + return string("sample(texpaint_pack%s, sampler_linear, tex_coord).r", ls); } else if (socket == node->outputs->buffer[3]) { // Rough - node_shader_add_texture(parser_material_kong, string_join("texpaint_pack", i32_to_string(l)), string_join("_texpaint_pack", i32_to_string(l))); - return string_join(string_join("sample(texpaint_pack", i32_to_string(l)), ", sampler_linear, tex_coord).g"); + node_shader_add_texture(parser_material_kong, string("texpaint_pack%s", ls), string("_texpaint_pack%s", ls)); + return string("sample(texpaint_pack%s, sampler_linear, tex_coord).g", ls); } else if (socket == node->outputs->buffer[4]) { // Metal - node_shader_add_texture(parser_material_kong, string_join("texpaint_pack", i32_to_string(l)), string_join("_texpaint_pack", i32_to_string(l))); - return string_join(string_join("sample(texpaint_pack", i32_to_string(l)), ", sampler_linear, tex_coord).b"); + node_shader_add_texture(parser_material_kong, string("texpaint_pack%s", ls), string("_texpaint_pack%s", ls)); + return string("sample(texpaint_pack%s, sampler_linear, tex_coord).b", ls); } else if (socket == node->outputs->buffer[6]) { return "0.0"; } // Emission else if (socket == node->outputs->buffer[7]) { // Height - node_shader_add_texture(parser_material_kong, string_join("texpaint_pack", i32_to_string(l)), string_join("_texpaint_pack", i32_to_string(l))); - return string_join(string_join("sample(texpaint_pack", i32_to_string(l)), ", sampler_linear, tex_coord).a"); + node_shader_add_texture(parser_material_kong, string("texpaint_pack%s", ls), string("_texpaint_pack%s", ls)); + return string("sample(texpaint_pack%s, sampler_linear, tex_coord).a", ls); } else { return "0.0"; diff --git a/paint/sources/material_nodes/layer_weight_node.c b/paint/sources/material_nodes/layer_weight_node.c index eeec914e..fe9a7715 100644 --- a/paint/sources/material_nodes/layer_weight_node.c +++ b/paint/sources/material_nodes/layer_weight_node.c @@ -10,10 +10,10 @@ char *layer_weight_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *blend = parser_material_parse_value_input(node->inputs->buffer[0], false); if (socket == node->outputs->buffer[0]) { // Fresnel parser_material_kong->frag_dotnv = true; - return string_join(string_join("clamp(pow(1.0 - dotnv, (1.0 - ", blend), ") * 10.0), 0.0, 1.0)"); + return string("clamp(pow(1.0 - dotnv, (1.0 - %s) * 10.0), 0.0, 1.0)", blend); } else { // Facing parser_material_kong->frag_dotnv = true; - return string_join(string_join("((1.0 - dotnv) * ", blend), ")"); + return string("((1.0 - dotnv) * %s)", blend); } } diff --git a/paint/sources/material_nodes/magic_texture_node.c b/paint/sources/material_nodes/magic_texture_node.c index e9b3a153..0e00ebe4 100644 --- a/paint/sources/material_nodes/magic_texture_node.c +++ b/paint/sources/material_nodes/magic_texture_node.c @@ -11,14 +11,12 @@ char *magic_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_magic); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = string_join(string_join(string_join(string_join("tex_magic(", co), " * "), scale), " * 4.0)"); - return res; + return string("tex_magic(%s * %s * 4.0)", co, scale); } char *magic_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_magic); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = string_join(string_join(string_join(string_join("tex_magic_f(", co), " * "), scale), " * 4.0)"); - return res; + return string("tex_magic_f(%s * %s * 4.0)", co, scale); } diff --git a/paint/sources/material_nodes/map_range_node.c b/paint/sources/material_nodes/map_range_node.c index cd849f3a..f036434d 100644 --- a/paint/sources/material_nodes/map_range_node.c +++ b/paint/sources/material_nodes/map_range_node.c @@ -12,17 +12,11 @@ char *map_range_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *fmax = parser_material_parse_value_input(node->inputs->buffer[2], false); char *tmin = parser_material_parse_value_input(node->inputs->buffer[3], false); char *tmax = parser_material_parse_value_input(node->inputs->buffer[4], false); - bool use_clamp = node->buttons->buffer[0]->default_value->buffer[0] > 0; - char *a = string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("((", tmin), " - "), tmax), ") / ("), fmin), " - "), fmax), "))"); - char *out_val = string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("(", a), " * "), val), " + "), tmin), " - "), a), - " * "), - fmin), - ")"); + bool use_clamp = node->buttons->buffer[0]->default_value->buffer[0] > 0; + char *a = string("((%s - %s) / (%s - %s))", tmin, tmax, fmin, fmax); + char *out_val = string("(%s * %s + %s - %s * %s)", a, val, tmin, a, fmin); if (use_clamp) { - return string_join(string_join(string_join(string_join(string_join(string_join("(clamp(", out_val), ", "), tmin), ", "), tmax), "))"); + return string("(clamp(%s, %s, %s))", out_val, tmin, tmax); } else { return out_val; diff --git a/paint/sources/material_nodes/mapping_node.c b/paint/sources/material_nodes/mapping_node.c index 2430a0c6..8cbb69d3 100644 --- a/paint/sources/material_nodes/mapping_node.c +++ b/paint/sources/material_nodes/mapping_node.c @@ -12,36 +12,17 @@ char *mapping_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *node_rotation = parser_material_parse_vector_input(node->inputs->buffer[2]); char *node_scale = parser_material_parse_vector_input(node->inputs->buffer[3]); if (!string_equals(node_scale, "float3(1, 1, 1)")) { - out = string_join(string_join(string_join(string_join("(", out), " * "), node_scale), ")"); + out = string("(%s * %s)", out, node_scale); } if (!string_equals(node_rotation, "float3(0, 0, 0)")) { // ZYX rotation, Z axis for now.. - char *a = string_join(node_rotation, ".z * (3.1415926535 / 180)"); + char *a = string("%s.z * (3.1415926535 / 180)", node_rotation); // x * cos(theta) - y * sin(theta) // x * sin(theta) + y * cos(theta) - out = string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("float3(", out), - ".x * cos("), - a), - ") - "), - out), - ".y * sin("), - a), - "), "), - out), - ".x * sin("), - a), - ") + "), - out), - ".y * cos("), - a), - "), 0.0)"); + out = string("float3(%s.x * cos(%s) - %s.y * sin(%s), %s.x * sin(%s) + %s.y * cos(%s), 0.0)", out, a, out, a, out, a, out, a); + } + if (!string_equals(node_translation, "float3(0, 0, 0)")) { + out = string("(%s + %s)", out, node_translation); } // if node.rotation[1] != 0.0: // a = node.rotation[1] @@ -49,9 +30,6 @@ char *mapping_node_vector(ui_node_t *node, ui_node_socket_t *socket) { // if node.rotation[0] != 0.0: // a = node.rotation[0] // out = "float3({0}.y * {1} - {0}.z * {2}, {0}.y * {2} + {0}.z * {1}, 0.0)".format(out, math_cos(a), math_sin(a)) - if (!string_equals(node_translation, "float3(0, 0, 0)")) { - out = string_join(string_join(string_join(string_join("(", out), " + "), node_translation), ")"); - } // if node.use_min: // out = "max({0}, float3({1}, {2}, {3}))".format(out, node.min[0], node.min[1]) // if node.use_max: diff --git a/paint/sources/material_nodes/math2_node.c b/paint/sources/material_nodes/math2_node.c index d150aea7..3a481f6f 100644 --- a/paint/sources/material_nodes/math2_node.c +++ b/paint/sources/material_nodes/math2_node.c @@ -7,161 +7,135 @@ void math2_node_init() { } char *math2_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *val1 = parser_material_parse_value_input(node->inputs->buffer[0], false); - char *val2 = parser_material_parse_value_input(node->inputs->buffer[1], false); + char *val1 = parser_material_parse_value_input(node->inputs->buffer[0], false); + char *val2 = parser_material_parse_value_input(node->inputs->buffer[1], false); ui_node_button_t *but = node->buttons->buffer[0]; // operation - char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); op = string_copy(string_replace_all(op, " ", "_")); - bool use_clamp = node->buttons->buffer[1]->default_value->buffer[0] > 0; - char *out_val = ""; + bool use_clamp = node->buttons->buffer[1]->default_value->buffer[0] > 0; + char *out_val = ""; if (string_equals(op, "ADD")) { - out_val = string_join(string_join(string_join(string_join("(", val1), " + "), val2), ")"); + out_val = string("(%s + %s)", val1, val2); } else if (string_equals(op, "SUBTRACT")) { - out_val = string_join(string_join(string_join(string_join("(", val1), " - "), val2), ")"); + out_val = string("(%s - %s)", val1, val2); } else if (string_equals(op, "MULTIPLY")) { - out_val = string_join(string_join(string_join(string_join("(", val1), " * "), val2), ")"); + out_val = string("(%s * %s)", val1, val2); } else if (string_equals(op, "DIVIDE")) { - char *store = string_join(parser_material_store_var_name(node), "_divide"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), ": float = "), val2), ";")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (", store), " == 0.0) { "), store), " = "), - f32_to_string(parser_material_eps)), - "; }")); - out_val = string_join(string_join(string_join(string_join("(", val1), " / "), store), ")"); + char *store = string("%s_divide", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s: float = %s;", store, val2)); + parser_material_write(parser_material_kong, string("if (%s == 0.0) { %s = %s; }", store, store, f32_to_string(parser_material_eps))); + out_val = string("(%s / %s)", val1, store); } else if (string_equals(op, "POWER")) { - out_val = string_join(string_join(string_join(string_join("pow(", val1), ", "), val2), ")"); + out_val = string("pow(%s, %s)", val1, val2); } else if (string_equals(op, "LOGARITHM")) { - out_val = string_join(string_join("log(", val1), ")"); + out_val = string("log(%s)", val1); } else if (string_equals(op, "SQUARE_ROOT")) { - out_val = string_join(string_join("sqrt(", val1), ")"); + out_val = string("sqrt(%s)", val1); } else if (string_equals(op, "INVERSE_SQUARE_ROOT")) { - out_val = string_join(string_join("rsqrt(", val1), ")"); + out_val = string("rsqrt(%s)", val1); } else if (string_equals(op, "EXPONENT")) { - out_val = string_join(string_join("exp(", val1), ")"); + out_val = string("exp(%s)", val1); } else if (string_equals(op, "ABSOLUTE")) { - out_val = string_join(string_join("abs(", val1), ")"); + out_val = string("abs(%s)", val1); } else if (string_equals(op, "MINIMUM")) { - out_val = string_join(string_join(string_join(string_join("min(", val1), ", "), val2), ")"); + out_val = string("min(%s, %s)", val1, val2); } else if (string_equals(op, "MAXIMUM")) { - out_val = string_join(string_join(string_join(string_join("max(", val1), ", "), val2), ")"); + out_val = string("max(%s, %s)", val1, val2); } else if (string_equals(op, "LESS_THAN")) { // out_val = "float(" + val1 + " < " + val2 + ")"; - char *store = string_join(parser_material_store_var_name(node), "_lessthan"); - parser_material_write(parser_material_kong, string_join(string_join("var ", store), ": float = 0.0;")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (", val1), " < "), val2), ") { "), store), - " = 1.0; }")); + char *store = string("%s_lessthan", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s: float = 0.0;", store)); + parser_material_write(parser_material_kong, string("if (%s < %s) { %s = 1.0; }", val1, val2, store)); out_val = string_copy(store); } else if (string_equals(op, "GREATER_THAN")) { // out_val = "float(" + val1 + " > " + val2 + ")"; - char *store = string_join(parser_material_store_var_name(node), "_greaterthan"); - parser_material_write(parser_material_kong, string_join(string_join("var ", store), ": float = 0.0;")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("if (", val1), " > "), val2), ") { "), store), - " = 1.0; }")); + char *store = string("%s_greaterthan", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s: float = 0.0;", store)); + parser_material_write(parser_material_kong, string("if (%s > %s) { %s = 1.0; }", val1, val2, store)); out_val = string_copy(store); } else if (string_equals(op, "SIGN")) { - out_val = string_join(string_join("sign(", val1), ")"); + out_val = string("sign(%s)", val1); } else if (string_equals(op, "ROUND")) { - out_val = string_join(string_join("floor(", val1), " + 0.5)"); + out_val = string("floor(%s + 0.5)", val1); } else if (string_equals(op, "FLOOR")) { - out_val = string_join(string_join("floor(", val1), ")"); + out_val = string("floor(%s)", val1); } else if (string_equals(op, "CEIL")) { - out_val = string_join(string_join("ceil(", val1), ")"); + out_val = string("ceil(%s)", val1); } else if (string_equals(op, "SNAP")) { - out_val = string_join(string_join(string_join(string_join(string_join(string_join("(floor(", val1), " / "), val2), ") * "), val2), ")"); + out_val = string("(floor(%s / %s) * %s)", val1, val2, val2); } else if (string_equals(op, "TRUNCATE")) { - out_val = string_join(string_join("trunc(", val1), ")"); + out_val = string("trunc(%s)", val1); } else if (string_equals(op, "FRACTION")) { - out_val = string_join(string_join("frac(", val1), ")"); + out_val = string("frac(%s)", val1); } else if (string_equals(op, "MODULO")) { - out_val = string_join(string_join(string_join(string_join("(", val1), " % "), val2), ")"); + out_val = string("(%s %% %s)", val1, val2); } else if (string_equals(op, "PING-PONG")) { - char *store = string_join(parser_material_store_var_name(node), "_pingpong"); - parser_material_write(parser_material_kong, string_join(string_join("var ", store), ": float = 0.0;")); - parser_material_write( - parser_material_kong, - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("if (", val2), - " != 0.0) { "), - store), - " = abs(frac(("), - val1), - " - "), - val2), - ") / ("), - val2), - " * 2.0)) * "), - val2), - " * 2.0 - "), - val2), - "); }")); + char *store = string("%s_pingpong", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s: float = 0.0;", store)); + parser_material_write(parser_material_kong, + string("if (%s != 0.0) { %s = abs(frac((%s - %s) / (%s * 2.0)) * %s * 2.0 - %s); }", val2, store, val1, val2, val2, val2, val2)); out_val = string_copy(store); } else if (string_equals(op, "SINE")) { - out_val = string_join(string_join("sin(", val1), ")"); + out_val = string("sin(%s)", val1); } else if (string_equals(op, "COSINE")) { - out_val = string_join(string_join("cos(", val1), ")"); + out_val = string("cos(%s)", val1); } else if (string_equals(op, "TANGENT")) { - out_val = string_join(string_join("tan(", val1), ")"); + out_val = string("tan(%s)", val1); } else if (string_equals(op, "ARCSINE")) { - out_val = string_join(string_join("asin(", val1), ")"); + out_val = string("asin(%s)", val1); } else if (string_equals(op, "ARCCOSINE")) { - out_val = string_join(string_join("acos(", val1), ")"); + out_val = string("acos(%s)", val1); } else if (string_equals(op, "ARCTANGENT")) { - out_val = string_join(string_join("atan(", val1), ")"); + out_val = string("atan(%s)", val1); } else if (string_equals(op, "ARCTAN2")) { - out_val = string_join(string_join(string_join(string_join("atan2(", val1), ", "), val2), ")"); + out_val = string("atan2(%s, %s)", val1, val2); } else if (string_equals(op, "HYPERBOLIC_SINE")) { - out_val = string_join(string_join("sinh(", val1), ")"); + out_val = string("sinh(%s)", val1); } else if (string_equals(op, "HYPERBOLIC_COSINE")) { - out_val = string_join(string_join("cosh(", val1), ")"); + out_val = string("cosh(%s)", val1); } else if (string_equals(op, "HYPERBOLIC_TANGENT")) { - out_val = string_join(string_join("tanh(", val1), ")"); + out_val = string("tanh(%s)", val1); } else if (string_equals(op, "TO_RADIANS")) { - out_val = string_join(string_join("radians(", val1), ")"); + out_val = string("radians(%s)", val1); } else if (string_equals(op, "TO_DEGREES")) { - out_val = string_join(string_join("degrees(", val1), ")"); + out_val = string("degrees(%s)", val1); } if (use_clamp) { - return string_join(string_join("clamp(", out_val), ", 0.0, 1.0)"); + return string("clamp(%s, 0.0, 1.0)", out_val); } else { return out_val; diff --git a/paint/sources/material_nodes/mix_color_node.c b/paint/sources/material_nodes/mix_color_node.c index 1a4ab172..c23b3260 100644 --- a/paint/sources/material_nodes/mix_color_node.c +++ b/paint/sources/material_nodes/mix_color_node.c @@ -8,63 +8,39 @@ void mix_color_node_init() { char *mix_color_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); - char *fac_var = string_join(parser_material_node_name(node, NULL), "_fac"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", fac_var), ": float = "), fac), ";")); - char *col1 = parser_material_parse_vector_input(node->inputs->buffer[1]); - char *col2 = parser_material_parse_vector_input(node->inputs->buffer[2]); + char *fac_var = string("%s_fac", parser_material_node_name(node, NULL)); + parser_material_write(parser_material_kong, string("var %s: float = %s;", fac_var, fac)); + char *col1 = parser_material_parse_vector_input(node->inputs->buffer[1]); + char *col2 = parser_material_parse_vector_input(node->inputs->buffer[2]); ui_node_button_t *but = node->buttons->buffer[0]; // blend_type - char *blend = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *blend = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); blend = string_copy(string_replace_all(blend, " ", "_")); - bool use_clamp = node->buttons->buffer[1]->default_value->buffer[0] > 0; - char *out_col = ""; + bool use_clamp = node->buttons->buffer[1]->default_value->buffer[0] > 0; + char *out_col = ""; if (string_equals(blend, "MIX")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", "), col2), ", "), fac_var), ")"); + out_col = string("lerp3(%s, %s, %s)", col1, col2, fac_var); } else if (string_equals(blend, "DARKEN")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join("min3(", col1), ", "), col2), " * "), fac_var), ")"); + out_col = string("min3(%s, %s * %s)", col1, col2, fac_var); } else if (string_equals(blend, "MULTIPLY")) { - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", "), col1), " * "), col2), ", "), - fac_var), - ")"); + out_col = string("lerp3(%s, %s * %s, %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "BURN")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), - ", float3(1.0, 1.0, 1.0) - (float3(1.0, 1.0, 1.0) - "), - col1), - ") / "), - col2), - ", "), - fac_var), - ")"); + out_col = string("lerp3(%s, float3(1.0, 1.0, 1.0) - (float3(1.0, 1.0, 1.0) - %s) / %s, %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "LIGHTEN")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join("max3(", col1), ", "), col2), " * "), fac_var), ")"); + out_col = string("max3(%s, %s * %s)", col1, col2, fac_var); } else if (string_equals(blend, "SCREEN")) { - char *v3 = parser_material_to_vec3(string_join("1.0 - ", fac_var)); - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("(float3(1.0, 1.0, 1.0) - (", v3), " + "), fac_var), - " * (float3(1.0, 1.0, 1.0) - "), - col2), - ")) * (float3(1.0, 1.0, 1.0) - "), - col1), - "))"); + char *v3 = parser_material_to_vec3(string("1.0 - %s", fac_var)); + out_col = string("(float3(1.0, 1.0, 1.0) - (%s + %s * (float3(1.0, 1.0, 1.0) - %s)) * (float3(1.0, 1.0, 1.0) - %s))", v3, fac_var, col2, col1); } else if (string_equals(blend, "DODGE")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", "), col1), - " / (float3(1.0, 1.0, 1.0) - "), - col2), - "), "), - fac_var), - ")"); + out_col = string("lerp3(%s, %s / (float3(1.0, 1.0, 1.0) - %s), %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "ADD")) { - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", "), col1), " + "), col2), ", "), - fac_var), - ")"); + out_col = string("lerp3(%s, %s + %s, %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "OVERLAY")) { // out_col = "lerp3(" + col1 + ", float3( \ @@ -72,230 +48,61 @@ char *mix_color_node_vector(ui_node_t *node, ui_node_socket_t *socket) { // " + col1 + ".g < 0.5 ? 2.0 * " + col1 + ".g * " + col2 + ".g : 1.0 - 2.0 * (1.0 - " + col1 + ".g) * (1.0 - " + col2 + ".g), \ // " + col1 + ".b < 0.5 ? 2.0 * " + col1 + ".b * " + col2 + ".b : 1.0 - 2.0 * (1.0 - " + col1 + ".b) * (1.0 - " + col2 + ".b) \ // ), " + fac_var + ")"; - char *res_r = string_join(parser_material_node_name(node, NULL), "_res_r"); - char *res_g = string_join(parser_material_node_name(node, NULL), "_res_g"); - char *res_b = string_join(parser_material_node_name(node, NULL), "_res_b"); - parser_material_write(parser_material_kong, string_join(string_join("var ", res_r), ": float;")); - parser_material_write(parser_material_kong, string_join(string_join("var ", res_g), ": float;")); - parser_material_write(parser_material_kong, string_join(string_join("var ", res_b), ": float;")); - parser_material_write( - parser_material_kong, - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("if (", col1), - ".r < 0.5) { "), - res_r), - " = 2.0 * "), - col1), - ".r * "), - col2), - ".r; } else { "), - res_r), - " = 1.0 - 2.0 * (1.0 - "), - col1), - ".r) * (1.0 - "), - col2), - ".r); }")); - parser_material_write( - parser_material_kong, - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("if (", col1), - ".g < 0.5) { "), - res_g), - " = 2.0 * "), - col1), - ".g * "), - col2), - ".g; } else { "), - res_g), - " = 1.0 - 2.0 * (1.0 - "), - col1), - ".g) * (1.0 - "), - col2), - ".g); }")); - parser_material_write( - parser_material_kong, - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("if (", col1), - ".b < 0.5) { "), - res_b), - " = 2.0 * "), - col1), - ".b * "), - col2), - ".b; } else { "), - res_b), - " = 1.0 - 2.0 * (1.0 - "), - col1), - ".b) * (1.0 - "), - col2), - ".b); }")); - out_col = string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", float3("), res_r), ", "), - res_g), - ", "), - res_b), - "), "), - fac_var), - ")"); + char *node_name = parser_material_node_name(node, NULL); + char *res_r = string("%s_res_r", node_name); + char *res_g = string("%s_res_g", node_name); + char *res_b = string("%s_res_b", node_name); + parser_material_write(parser_material_kong, string("var %s: float;", res_r)); + parser_material_write(parser_material_kong, string("var %s: float;", res_g)); + parser_material_write(parser_material_kong, string("var %s: float;", res_b)); + parser_material_write(parser_material_kong, string("if (%s.r < 0.5) { %s = 2.0 * %s.r * %s.r; } else { %s = 1.0 - 2.0 * (1.0 - %s.r) * (1.0 - %s.r); }", + col1, res_r, col1, col2, res_r, col1, col2)); + parser_material_write(parser_material_kong, string("if (%s.g < 0.5) { %s = 2.0 * %s.g * %s.g; } else { %s = 1.0 - 2.0 * (1.0 - %s.g) * (1.0 - %s.g); }", + col1, res_g, col1, col2, res_g, col1, col2)); + parser_material_write(parser_material_kong, string("if (%s.b < 0.5) { %s = 2.0 * %s.b * %s.b; } else { %s = 1.0 - 2.0 * (1.0 - %s.b) * (1.0 - %s.b); }", + col1, res_b, col1, col2, res_b, col1, col2)); + out_col = string("lerp3(%s, float3(%s, %s, %s), %s)", col1, res_r, res_g, res_b, fac_var); } else if (string_equals(blend, "SOFT_LIGHT")) { - out_col = string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join("((1.0 - ", fac_var), ") * "), - col1), - " + "), - fac_var), - " * ((float3(1.0, 1.0, 1.0) - "), - col1), - ") * "), - col2), - " * "), - col1), - " + "), - col1), - " * (float3(1.0, 1.0, 1.0) - (float3(1.0, 1.0, 1.0) - "), - col2), - ") * (float3(1.0, 1.0, 1.0) - "), - col1), - "))))"); + out_col = string("((1.0 - %s) * %s + %s * ((float3(1.0, 1.0, 1.0) - %s) * %s * %s + %s * (float3(1.0, 1.0, 1.0) - (float3(1.0, 1.0, 1.0) - %s) * " + "(float3(1.0, 1.0, 1.0) - %s))))", + fac_var, col1, fac_var, col1, col2, col1, col1, col2, col1); } else if (string_equals(blend, "LINEAR_LIGHT")) { - out_col = string_join(string_join(string_join(string_join(string_join(string_join("(", col1), " + "), fac_var), " * (float3(2.0, 2.0, 2.0) * ("), col2), - " - float3(0.5, 0.5, 0.5))))"); + out_col = string("(%s + %s * (float3(2.0, 2.0, 2.0) * (%s - float3(0.5, 0.5, 0.5))))", col1, fac_var, col2); } else if (string_equals(blend, "DIFFERENCE")) { - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", abs3("), col1), " - "), col2), - "), "), - fac_var), - ")"); + out_col = string("lerp3(%s, abs3(%s - %s), %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "SUBTRACT")) { - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), ", "), col1), " - "), col2), ", "), - fac_var), - ")"); + out_col = string("lerp3(%s, %s - %s, %s)", col1, col1, col2, fac_var); } else if (string_equals(blend, "DIVIDE")) { - f32 eps = 0.000001; - col2 = string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("max3(", col2), ", float3("), f32_to_string(eps)), ", "), - f32_to_string(eps)), - ", "), - f32_to_string(eps)), - "))"); - char *v3 = string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join("(float3(1.0, 1.0, 1.0) - float3(", - fac_var), - ", "), - fac_var), - ", "), - fac_var), - ")) * "), - col1), - " + float3("), - fac_var), - ", "), - fac_var), - ", "), - fac_var), - ") * "), - col1), - " / "), - col2); - out_col = string_join(string_join("(", v3), ")"); + f32 eps = 0.000001; + char *eps_s = f32_to_string(eps); + col2 = string("max3(%s, float3(%s, %s, %s))", col2, eps_s, eps_s, eps_s); + char *v3 = string("(float3(1.0, 1.0, 1.0) - float3(%s, %s, %s)) * %s + float3(%s, %s, %s) * %s / %s", fac_var, fac_var, fac_var, col1, fac_var, fac_var, + fac_var, col1, col2); + out_col = string("(%s)", v3); } else if (string_equals(blend, "HUE")) { node_shader_add_function(parser_material_kong, str_hue_sat); - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), - ", hsv_to_rgb(float3(rgb_to_hsv("), - col2), - ").r, rgb_to_hsv("), - col1), - ").g, rgb_to_hsv("), - col1), - ").b)), "), - fac_var), - ")"); + out_col = string("lerp3(%s, hsv_to_rgb(float3(rgb_to_hsv(%s).r, rgb_to_hsv(%s).g, rgb_to_hsv(%s).b)), %s)", col1, col2, col1, col1, fac_var); } else if (string_equals(blend, "SATURATION")) { node_shader_add_function(parser_material_kong, str_hue_sat); - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), - ", hsv_to_rgb(float3(rgb_to_hsv("), - col1), - ").r, rgb_to_hsv("), - col2), - ").g, rgb_to_hsv("), - col1), - ").b)), "), - fac_var), - ")"); + out_col = string("lerp3(%s, hsv_to_rgb(float3(rgb_to_hsv(%s).r, rgb_to_hsv(%s).g, rgb_to_hsv(%s).b)), %s)", col1, col1, col2, col1, fac_var); } else if (string_equals(blend, "COLOR")) { node_shader_add_function(parser_material_kong, str_hue_sat); - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), - ", hsv_to_rgb(float3(rgb_to_hsv("), - col2), - ").r, rgb_to_hsv("), - col2), - ").g, rgb_to_hsv("), - col1), - ").b)), "), - fac_var), - ")"); + out_col = string("lerp3(%s, hsv_to_rgb(float3(rgb_to_hsv(%s).r, rgb_to_hsv(%s).g, rgb_to_hsv(%s).b)), %s)", col1, col2, col2, col1, fac_var); } else if (string_equals(blend, "VALUE")) { node_shader_add_function(parser_material_kong, str_hue_sat); - out_col = - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", col1), - ", hsv_to_rgb(float3(rgb_to_hsv("), - col1), - ").r, rgb_to_hsv("), - col1), - ").g, rgb_to_hsv("), - col2), - ").b)), "), - fac_var), - ")"); + out_col = string("lerp3(%s, hsv_to_rgb(float3(rgb_to_hsv(%s).r, rgb_to_hsv(%s).g, rgb_to_hsv(%s).b)), %s)", col1, col1, col1, col2, fac_var); } if (use_clamp) { - return string_join(string_join("clamp3(", out_col), ", float3(0.0, 0.0, 0.0), float3(1.0, 1.0, 1.0))"); + return string("clamp3(%s, float3(0.0, 0.0, 0.0), float3(1.0, 1.0, 1.0))", out_col); } else { return out_col; diff --git a/paint/sources/material_nodes/mix_normal_map_node.c b/paint/sources/material_nodes/mix_normal_map_node.c index 74a5a853..1a3782c7 100644 --- a/paint/sources/material_nodes/mix_normal_map_node.c +++ b/paint/sources/material_nodes/mix_normal_map_node.c @@ -7,61 +7,28 @@ void mix_normal_map_node_init() { } char *mix_normal_map_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *nm1 = parser_material_parse_vector_input(node->inputs->buffer[0]); - char *nm2 = parser_material_parse_vector_input(node->inputs->buffer[1]); + char *nm1 = parser_material_parse_vector_input(node->inputs->buffer[0]); + char *nm2 = parser_material_parse_vector_input(node->inputs->buffer[1]); ui_node_button_t *but = node->buttons->buffer[0]; - char *blend = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); // blend_type + char *blend = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); // blend_type blend = string_copy(string_replace_all(blend, " ", "_")); - char *store = parser_material_store_var_name(node); + char *store = parser_material_store_var_name(node); // The blending algorithms are based on the paper "Blending in Detail" by Colin Barré-Brisebois and Stephen Hill 2012 // https://blog.selfshadow.com/publications/blending-in-detail/ if (string_equals(blend, "PARTIAL_DERIVATIVE")) { // partial derivate blending - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_n1: float3 = "), nm1), " * 2.0 - 1.0;")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_n2: float3 = "), nm2), " * 2.0 - 1.0;")); - return string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("0.5 * normalize(float3(", store), "_n1.xy * "), - store), - "_n2.z + "), - store), - "_n2.xy * "), - store), - "_n1.z, "), - store), - "_n1.z * "), - store), - "_n2.z)) + 0.5"); + parser_material_write(parser_material_kong, string("var %s_n1: float3 = %s * 2.0 - 1.0;", store, nm1)); + parser_material_write(parser_material_kong, string("var %s_n2: float3 = %s * 2.0 - 1.0;", store, nm2)); + return string("0.5 * normalize(float3(%s_n1.xy * %s_n2.z + %s_n2.xy * %s_n1.z, %s_n1.z * %s_n2.z)) + 0.5", store, store, store, store, store, store); } else if (string_equals(blend, "WHITEOUT")) { // whiteout blending - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_n1: float3 = "), nm1), " * 2.0 - 1.0;")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_n2: float3 = "), nm2), " * 2.0 - 1.0;")); - return string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("0.5 * normalize(float3(", store), "_n1.xy + "), store), - "_n2.xy, "), - store), - "_n1.z * "), - store), - "_n2.z)) + 0.5"); + parser_material_write(parser_material_kong, string("var %s_n1: float3 = %s * 2.0 - 1.0;", store, nm1)); + parser_material_write(parser_material_kong, string("var %s_n2: float3 = %s * 2.0 - 1.0;", store, nm2)); + return string("0.5 * normalize(float3(%s_n1.xy + %s_n2.xy, %s_n1.z * %s_n2.z)) + 0.5", store, store, store, store); } else { // REORIENTED - reoriented normal mapping - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("var ", store), "_n1: float3 = "), nm1), " * 2.0 - float3(1.0, 1.0, 0.0);")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_n2: float3 = "), nm2), - " * float3(-2.0, -2.0, 2.0) - float3(-1.0, -1.0, 1.0);")); - return string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("0.5 * normalize(", store), "_n1 * dot("), store), - "_n1, "), - store), - "_n2) - "), - store), - "_n2 * "), - store), - "_n1.z) + 0.5"); + parser_material_write(parser_material_kong, string("var %s_n1: float3 = %s * 2.0 - float3(1.0, 1.0, 0.0);", store, nm1)); + parser_material_write(parser_material_kong, string("var %s_n2: float3 = %s * float3(-2.0, -2.0, 2.0) - float3(-1.0, -1.0, 1.0);", store, nm2)); + return string("0.5 * normalize(%s_n1 * dot(%s_n1, %s_n2) - %s_n2 * %s_n1.z) + 0.5", store, store, store, store, store); } } diff --git a/paint/sources/material_nodes/noise_texture_node.c b/paint/sources/material_nodes/noise_texture_node.c index be521e3a..5dd5f167 100644 --- a/paint/sources/material_nodes/noise_texture_node.c +++ b/paint/sources/material_nodes/noise_texture_node.c @@ -11,27 +11,12 @@ char *noise_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_noise); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("float3(tex_noise(", co), " * "), scale), - "), tex_noise("), - co), - " * "), - scale), - " + 0.33), tex_noise("), - co), - " * "), - scale), - " + 0.66))"); - return res; + return string("float3(tex_noise(%s * %s), tex_noise(%s * %s + 0.33), tex_noise(%s * %s + 0.66))", co, scale, co, scale, co, scale); } char *noise_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_noise); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = string_join(string_join(string_join(string_join("tex_noise(", co), " * "), scale), ")"); - return res; + return string("tex_noise(%s * %s)", co, scale); } diff --git a/paint/sources/material_nodes/normal_map_node.c b/paint/sources/material_nodes/normal_map_node.c index 93540e43..b7f16bf8 100644 --- a/paint/sources/material_nodes/normal_map_node.c +++ b/paint/sources/material_nodes/normal_map_node.c @@ -10,12 +10,10 @@ char *normal_map_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *strength = parser_material_parse_value_input(node->inputs->buffer[0], false); char *norm = parser_material_parse_vector_input(node->inputs->buffer[1]); - char *store = parser_material_store_var_name(node); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_texn: float3 = "), norm), " * 2.0 - 1.0;")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("", store), "_texn.xy = "), strength), " * "), store), - "_texn.xy;")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("", store), "_texn = normalize("), store), "_texn);")); + char *store = parser_material_store_var_name(node); + parser_material_write(parser_material_kong, string("var %s_texn: float3 = %s * 2.0 - 1.0;", store, norm)); + parser_material_write(parser_material_kong, string("%s_texn.xy = %s * %s_texn.xy;", store, strength, store)); + parser_material_write(parser_material_kong, string("%s_texn = normalize(%s_texn);", store, store)); - return string_join(string_join("(0.5 * ", store), "_texn + 0.5)"); + return string("(0.5 * %s_texn + 0.5)", store); } diff --git a/paint/sources/material_nodes/normal_node.c b/paint/sources/material_nodes/normal_node.c index a05304f6..45b99ac4 100644 --- a/paint/sources/material_nodes/normal_node.c +++ b/paint/sources/material_nodes/normal_node.c @@ -14,5 +14,5 @@ char *normal_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *normal_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *nor = parser_material_parse_vector_input(node->inputs->buffer[0]); char *norout = parser_material_vec3(node->outputs->buffer[0]->default_value); - return string_join(string_join(string_join(string_join("dot(", norout), ", "), nor), ")"); + return string("dot(%s, %s)", norout, nor); } diff --git a/paint/sources/material_nodes/quantize_node.c b/paint/sources/material_nodes/quantize_node.c index 596fdb64..08ae5378 100644 --- a/paint/sources/material_nodes/quantize_node.c +++ b/paint/sources/material_nodes/quantize_node.c @@ -9,6 +9,5 @@ void quantize_node_init() { char *quantize_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *strength = parser_material_parse_value_input(node->inputs->buffer[0], false); char *col = parser_material_parse_vector_input(node->inputs->buffer[1]); - return string_join(string_join(string_join(string_join(string_join(string_join("(floor3(100.0 * ", strength), " * "), col), ") / (100.0 * "), strength), - "))"); + return string("(floor3(100.0 * %s * %s) / (100.0 * %s))", strength, col, strength); } diff --git a/paint/sources/material_nodes/replace_color_node.c b/paint/sources/material_nodes/replace_color_node.c index 9389106f..4b7f53bb 100644 --- a/paint/sources/material_nodes/replace_color_node.c +++ b/paint/sources/material_nodes/replace_color_node.c @@ -12,22 +12,6 @@ char *replace_color_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *new_color = parser_material_parse_vector_input(node->inputs->buffer[2]); char *radius = parser_material_parse_value_input(node->inputs->buffer[3], false); char *fuzziness = parser_material_parse_value_input(node->inputs->buffer[4], false); - return string_join( - string_join( - string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("lerp3(", new_color), ", "), - input_color), - ", clamp((distance("), - old_color), - ", "), - input_color), - ") - "), - radius), - ") / max("), - fuzziness), - ", "), - f32_to_string(parser_material_eps)), - "), 0.0, 1.0))"); + return string("lerp3(%s, %s, clamp((distance(%s, %s) - %s) / max(%s, %s), 0.0, 1.0))", new_color, input_color, old_color, input_color, radius, fuzziness, + f32_to_string(parser_material_eps)); } diff --git a/paint/sources/material_nodes/rgb_to_bw_node.c b/paint/sources/material_nodes/rgb_to_bw_node.c index 651377b0..2c1f61e1 100644 --- a/paint/sources/material_nodes/rgb_to_bw_node.c +++ b/paint/sources/material_nodes/rgb_to_bw_node.c @@ -8,6 +8,5 @@ void rgb_to_bw_node_init() { char *rgb_to_bw_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *col = parser_material_parse_vector_input(node->inputs->buffer[0]); - return string_join(string_join(string_join(string_join(string_join(string_join("(((", col), ".r * 0.3 + "), col), ".g * 0.59 + "), col), - ".b * 0.11) / 3.0) * 2.5)"); + return string("(((%s.r * 0.3 + %s.g * 0.59 + %s.b * 0.11) / 3.0) * 2.5)", col, col, col); } diff --git a/paint/sources/material_nodes/script_node.c b/paint/sources/material_nodes/script_node.c index 1a07871f..4a1c2054 100644 --- a/paint/sources/material_nodes/script_node.c +++ b/paint/sources/material_nodes/script_node.c @@ -13,9 +13,9 @@ char *script_node_value(ui_node_t *node, ui_node_socket_t *socket) { gc_root(parser_material_script_links); } buffer_t *script = node->buttons->buffer[0]->default_value; - char *str = sys_buffer_to_string(script); - char *link = parser_material_node_name(node, NULL); + char *str = sys_buffer_to_string(script); + char *link = parser_material_node_name(node, NULL); any_map_set(parser_material_script_links, link, str); - node_shader_add_constant(parser_material_kong, string_join(string_join("", link), ": float"), string_join("_", link)); - return string_join("constants.", link); + node_shader_add_constant(parser_material_kong, string("%s: float", link), string("_%s", link)); + return string("constants.%s", link); } diff --git a/paint/sources/material_nodes/separate_xyz_node.c b/paint/sources/material_nodes/separate_xyz_node.c index 59727cff..098ac331 100644 --- a/paint/sources/material_nodes/separate_xyz_node.c +++ b/paint/sources/material_nodes/separate_xyz_node.c @@ -9,12 +9,12 @@ void separate_xyz_node_init() { char *separate_xyz_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *vec = parser_material_parse_vector_input(node->inputs->buffer[0]); if (socket == node->outputs->buffer[0]) { - return string_join(vec, ".x"); + return string("%s.x", vec); } else if (socket == node->outputs->buffer[1]) { - return string_join(vec, ".y"); + return string("%s.y", vec); } else { - return string_join(vec, ".z"); + return string("%s.z", vec); } } diff --git a/paint/sources/material_nodes/text_texture_node.c b/paint/sources/material_nodes/text_texture_node.c index 01da14a5..6bea064e 100644 --- a/paint/sources/material_nodes/text_texture_node.c +++ b/paint/sources/material_nodes/text_texture_node.c @@ -8,12 +8,12 @@ void text_texture_node_init() { } void _parser_material_cache_tex_text_node_on_next_frame(char *text) { - char *_text_tool_text = context_raw->text_tool_text; + char *_text_tool_text = context_raw->text_tool_text; gpu_texture_t *_text_tool_image = context_raw->text_tool_image; context_raw->text_tool_text = string_copy(text); context_raw->text_tool_image = NULL; util_render_make_text_preview(); - char *file = string_join("tex_text_", text); + char *file = string("tex_text_%s", text); // TODO: remove old cache any_map_set(data_cached_images, file, context_raw->text_tool_image); context_raw->text_tool_text = string_copy(_text_tool_text); @@ -27,23 +27,23 @@ void _parser_material_cache_tex_text_node(char *file, char *text) { } char *text_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *tex_name = parser_material_node_name(node, NULL); + char *tex_name = parser_material_node_name(node, NULL); buffer_t *text_buffer = node->buttons->buffer[0]->default_value; - char *text = sys_buffer_to_string(text_buffer); - char *file = string_join("tex_text_", text); + char *text = sys_buffer_to_string(text_buffer); + char *file = string("tex_text_%s", text); _parser_material_cache_tex_text_node(file, text); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, file); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".rrr"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.rrr", texstore); } char *text_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *tex_name = parser_material_node_name(node, NULL); + char *tex_name = parser_material_node_name(node, NULL); buffer_t *text_buffer = node->buttons->buffer[0]->default_value; - char *text = sys_buffer_to_string(text_buffer); - char *file = string_join("tex_text_", text); + char *text = sys_buffer_to_string(text_buffer); + char *file = string("tex_text_%s", text); _parser_material_cache_tex_text_node(file, text); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, file); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".r"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.r", texstore); } diff --git a/paint/sources/material_nodes/vector_curves_node.c b/paint/sources/material_nodes/vector_curves_node.c index ae822fa6..0867189c 100644 --- a/paint/sources/material_nodes/vector_curves_node.c +++ b/paint/sources/material_nodes/vector_curves_node.c @@ -9,33 +9,30 @@ void vector_curves_node_init() { char *parser_material_vector_curve(char *name, char *fac, f32 *points, i32 num) { // Write Ys array - char *ys_var = string_join(name, "_ys"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", ys_var), ": float["), i32_to_string(num)), "];")); // TODO: Make const + char *ys_var = string("%s_ys", name); + parser_material_write(parser_material_kong, string("var %s: float[%s];", ys_var, i32_to_string(num))); // TODO: Make const for (i32 i = 0; i < num; ++i) { f32 p = points[i * 2 + 1]; - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(ys_var, "["), i32_to_string(i)), "] = "), f32_to_string(p)), ";")); + parser_material_write(parser_material_kong, string("%s[%s] = %s;", ys_var, i32_to_string(i), f32_to_string(p))); } // Get index - char *fac_var = string_join(name, "_fac"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", fac_var), ": float = "), fac), ";")); + char *fac_var = string("%s_fac", name); + parser_material_write(parser_material_kong, string("var %s: float = %s;", fac_var, fac)); char *index = "0"; for (i32 i = 1; i < num; ++i) { f32 p = points[i * 2 + 0]; - index = string_join(index, string_join(string_join(string_join(string_join(" + (", fac_var), " > "), f32_to_string(p)), " ? 1 : 0)")); + index = string("%s + (%s > %s ? 1 : 0)", index, fac_var, f32_to_string(p)); } // Write index - char *index_var = string_join(name, "_i"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", index_var), ": int = "), index), ";")); + char *index_var = string("%s_i", name); + parser_material_write(parser_material_kong, string("var %s: int = %s;", index_var, index)); // Linear // Write Xs array - char *facs_var = string_join(name, "_xs"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", facs_var), ": float["), i32_to_string(num)), "];")); // TODO: Make const + char *facs_var = string("%s_xs", name); + parser_material_write(parser_material_kong, string("var %s: float[%s];", facs_var, i32_to_string(num))); // TODO: Make const for (i32 i = 0; i < num; ++i) { f32 p = points[i * 2 + 0]; - parser_material_write( - parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("", facs_var), "["), i32_to_string(i)), "] = "), f32_to_string(p)), ";")); + parser_material_write(parser_material_kong, string("%s[%s] = %s;", facs_var, i32_to_string(i), f32_to_string(p))); } // Map vector return "0.0"; //// @@ -45,8 +42,8 @@ char *parser_material_vector_curve(char *name, char *fac, f32 *points, i32 num) } char *vector_curves_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); - char *vec = parser_material_parse_vector_input(node->inputs->buffer[1]); + char *fac = parser_material_parse_value_input(node->inputs->buffer[0], false); + char *vec = parser_material_parse_vector_input(node->inputs->buffer[1]); f32_array_t *curves = node->buttons->buffer[0]->default_value; if (curves->buffer[96] == 0.0) { curves->buffer[96] = 1.0; @@ -54,13 +51,11 @@ char *vector_curves_node_vector(ui_node_t *node, ui_node_socket_t *socket) { curves->buffer[98] = 1.0; } char *name = parser_material_node_name(node, NULL); - char *vc0 = parser_material_vector_curve(string_join(name, "0"), string_join(vec, ".x"), curves->buffer + 32 * 0, curves->buffer[96]); - char *vc1 = parser_material_vector_curve(string_join(name, "1"), string_join(vec, ".y"), curves->buffer + 32 * 1, curves->buffer[97]); - char *vc2 = parser_material_vector_curve(string_join(name, "2"), string_join(vec, ".z"), curves->buffer + 32 * 2, curves->buffer[98]); + char *vc0 = parser_material_vector_curve(string("%s0", name), string("%s.x", vec), curves->buffer + 32 * 0, curves->buffer[96]); + char *vc1 = parser_material_vector_curve(string("%s1", name), string("%s.y", vec), curves->buffer + 32 * 1, curves->buffer[97]); + char *vc2 = parser_material_vector_curve(string("%s2", name), string("%s.z", vec), curves->buffer + 32 * 2, curves->buffer[98]); // mapping.curves[0].points[0].handle_type // bezier curve - return string_join(string_join(string_join(string_join(string_join(string_join(string_join(string_join("(float3(", vc0), ", "), vc1), ", "), vc2), ") * "), - fac), - ")"); + return string("(float3(%s, %s, %s) * %s)", vc0, vc1, vc2, fac); } void nodes_material_vector_curves_button(i32 node_id) { diff --git a/paint/sources/material_nodes/vector_math2_node.c b/paint/sources/material_nodes/vector_math2_node.c index da576dec..acc90276 100644 --- a/paint/sources/material_nodes/vector_math2_node.c +++ b/paint/sources/material_nodes/vector_math2_node.c @@ -8,114 +8,104 @@ void vector_math2_node_init() { } char *vector_math2_node_vector(ui_node_t *node, ui_node_socket_t *socket) { - char *vec1 = parser_material_parse_vector_input(node->inputs->buffer[0]); - char *vec2 = parser_material_parse_vector_input(node->inputs->buffer[1]); + char *vec1 = parser_material_parse_vector_input(node->inputs->buffer[0]); + char *vec2 = parser_material_parse_vector_input(node->inputs->buffer[1]); ui_node_button_t *but = node->buttons->buffer[0]; // operation; - char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); op = string_copy(string_replace_all(op, " ", "_")); if (string_equals(op, "ADD")) { - return string_join(string_join(string_join(string_join("(", vec1), " + "), vec2), ")"); + return string("(%s + %s)", vec1, vec2); } else if (string_equals(op, "SUBTRACT")) { - return string_join(string_join(string_join(string_join("(", vec1), " - "), vec2), ")"); + return string("(%s - %s)", vec1, vec2); } else if (string_equals(op, "AVERAGE")) { - return string_join(string_join(string_join(string_join("((", vec1), " + "), vec2), ") / 2.0)"); + return string("((%s + %s) / 2.0)", vec1, vec2); } else if (string_equals(op, "DOT_PRODUCT")) { - return parser_material_to_vec3(string_join(string_join(string_join(string_join("dot(", vec1), ", "), vec2), ")")); + return parser_material_to_vec3(string("dot(%s, %s)", vec1, vec2)); } else if (string_equals(op, "LENGTH")) { - return parser_material_to_vec3(string_join(string_join("length(", vec1), ")")); + return parser_material_to_vec3(string("length(%s)", vec1)); } else if (string_equals(op, "DISTANCE")) { - return parser_material_to_vec3(string_join(string_join(string_join(string_join("distance(", vec1), ", "), vec2), ")")); + return parser_material_to_vec3(string("distance(%s, %s)", vec1, vec2)); } else if (string_equals(op, "CROSS_PRODUCT")) { - return string_join(string_join(string_join(string_join("cross(", vec1), ", "), vec2), ")"); + return string("cross(%s, %s)", vec1, vec2); } else if (string_equals(op, "NORMALIZE")) { - return string_join(string_join("normalize(", vec1), ")"); + return string("normalize(%s)", vec1); } else if (string_equals(op, "MULTIPLY")) { - return string_join(string_join(string_join(string_join("(", vec1), " * "), vec2), ")"); + return string("(%s * %s)", vec1, vec2); } else if (string_equals(op, "DIVIDE")) { - char *store = string_join(parser_material_store_var_name(node), "_vec2"); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), ": float3 = "), vec2), ";")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("if (", store), ".x == 0.0) { "), store), ".x = 0.000001; }")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("if (", store), ".y == 0.0) { "), store), ".y = 0.000001; }")); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join("if (", store), ".z == 0.0) { "), store), ".z = 0.000001; }")); - return string_join(string_join(string_join(string_join("(", vec1), " / "), vec2), ")"); + char *store = string("%s_vec2", parser_material_store_var_name(node)); + parser_material_write(parser_material_kong, string("var %s: float3 = %s;", store, vec2)); + parser_material_write(parser_material_kong, string("if (%s.x == 0.0) { %s.x = 0.000001; }", store, store)); + parser_material_write(parser_material_kong, string("if (%s.y == 0.0) { %s.y = 0.000001; }", store, store)); + parser_material_write(parser_material_kong, string("if (%s.z == 0.0) { %s.z = 0.000001; }", store, store)); + return string("(%s / %s)", vec1, vec2); } else if (string_equals(op, "PROJECT")) { - return string_join( - string_join( - string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("(dot(", vec1), ", "), vec2), ") / dot("), vec2), ", "), - vec2), - ") * "), - vec2), - ")"); + return string("(dot(%s, %s) / dot(%s, %s) * %s)", vec1, vec2, vec2, vec2, vec2); } else if (string_equals(op, "REFLECT")) { - return string_join(string_join(string_join(string_join("reflect(", vec1), ", normalize("), vec2), "))"); + return string("reflect(%s, normalize(%s))", vec1, vec2); } else if (string_equals(op, "SCALE")) { - return string_join(string_join(string_join(string_join("(", vec2), ".x * "), vec1), ")"); + return string("(%s.x * %s)", vec2, vec1); } else if (string_equals(op, "ABSOLUTE")) { - return string_join(string_join("abs3(", vec1), ")"); + return string("abs3(%s)", vec1); } else if (string_equals(op, "MINIMUM")) { - return string_join(string_join(string_join(string_join("min3(", vec1), ", "), vec2), ")"); + return string("min3(%s, %s)", vec1, vec2); } else if (string_equals(op, "MAXIMUM")) { - return string_join(string_join(string_join(string_join("max3(", vec1), ", "), vec2), ")"); + return string("max3(%s, %s)", vec1, vec2); } else if (string_equals(op, "FLOOR")) { - return string_join(string_join("floor3(", vec1), ")"); + return string("floor3(%s)", vec1); } else if (string_equals(op, "CEIL")) { - return string_join(string_join("ceil3(", vec1), ")"); + return string("ceil3(%s)", vec1); } else if (string_equals(op, "FRACTION")) { - return string_join(string_join("frac3(", vec1), ")"); + return string("frac3(%s)", vec1); } else if (string_equals(op, "MODULO")) { - return string_join(string_join(string_join(string_join("(", vec1), " % "), vec2), ")"); + return string("(%s %% %s)", vec1, vec2); } else if (string_equals(op, "SNAP")) { - return string_join(string_join(string_join(string_join(string_join(string_join("(floor3(", vec1), " / "), vec2), ") * "), vec2), ")"); + return string("(floor3(%s / %s) * %s)", vec1, vec2, vec2); } else if (string_equals(op, "SINE")) { - return string_join(string_join(string_join(string_join(string_join(string_join("float3(sin(", vec1), ".x), sin("), vec1), ".y), sin("), vec1), ".z))"); + return string("float3(sin(%s.x), sin(%s.y), sin(%s.z))", vec1, vec1, vec1); } else if (string_equals(op, "COSINE")) { - return string_join(string_join(string_join(string_join(string_join(string_join("float3(cos(", vec1), ".x), cos("), vec1), ".y), cos("), vec1), ".z))"); + return string("float3(cos(%s.x), cos(%s.y), cos(%s.z))", vec1, vec1, vec1); } else { // TANGENT - return string_join(string_join(string_join(string_join(string_join(string_join("float3(tan(", vec1), ".x), tan("), vec1), ".y), tan("), vec1), ".z))"); + return string("float3(tan(%s.x), tan(%s.y), tan(%s.z))", vec1, vec1, vec1); } } char *vector_math2_node_value(ui_node_t *node, ui_node_socket_t *socket) { - char *vec1 = parser_material_parse_vector_input(node->inputs->buffer[0]); - char *vec2 = parser_material_parse_vector_input(node->inputs->buffer[1]); + char *vec1 = parser_material_parse_vector_input(node->inputs->buffer[0]); + char *vec2 = parser_material_parse_vector_input(node->inputs->buffer[1]); ui_node_button_t *but = node->buttons->buffer[0]; // operation; - char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *op = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); op = string_copy(string_replace_all(op, " ", "_")); if (string_equals(op, "DOT_PRODUCT")) { - return string_join(string_join(string_join(string_join("dot(", vec1), ", "), vec2), ")"); + return string("dot(%s, %s)", vec1, vec2); } else if (string_equals(op, "LENGTH")) { - return string_join(string_join("length(", vec1), ")"); + return string("length(%s)", vec1); } else if (string_equals(op, "DISTANCE")) { - return string_join(string_join(string_join(string_join("distance(", vec1), ", "), vec2), ")"); + return string("distance(%s, %s)", vec1, vec2); } else { return "0.0"; diff --git a/paint/sources/material_nodes/voronoi_texture_node.c b/paint/sources/material_nodes/voronoi_texture_node.c index b3fc8f18..1cd14591 100644 --- a/paint/sources/material_nodes/voronoi_texture_node.c +++ b/paint/sources/material_nodes/voronoi_texture_node.c @@ -10,18 +10,17 @@ void voronoi_texture_node_init() { char *voronoi_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_voronoi); node_shader_add_texture(parser_material_kong, "snoise256", "$noise256.k"); - char *co = parser_material_get_coord(node); - char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); + char *co = parser_material_get_coord(node); + char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); ui_node_button_t *but = node->buttons->buffer[0]; // coloring; - char *coloring = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *coloring = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); coloring = string_copy(string_replace_all(coloring, " ", "_")); - char *res = ""; + char *res = ""; if (string_equals(coloring, "INTENSITY")) { - char *voronoi = string_join(string_join(string_join(string_join("tex_voronoi(", co), " * "), scale), ").a"); - res = string_copy(parser_material_to_vec3(voronoi)); + res = string_copy(parser_material_to_vec3(string("tex_voronoi(%s * %s).a", co, scale))); } else { // Cells - res = string_join(string_join(string_join(string_join("tex_voronoi(", co), " * "), scale), ").rgb"); + res = string("tex_voronoi(%s * %s).rgb", co, scale); } return res; } @@ -29,17 +28,17 @@ char *voronoi_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *voronoi_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_voronoi); node_shader_add_texture(parser_material_kong, "snoise256", "$noise256.k"); - char *co = parser_material_get_coord(node); - char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); + char *co = parser_material_get_coord(node); + char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); ui_node_button_t *but = node->buttons->buffer[0]; // coloring - char *coloring = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); + char *coloring = to_upper_case(u8_array_string_at(but->data, but->default_value->buffer[0])); coloring = string_copy(string_replace_all(coloring, " ", "_")); - char *res = ""; + char *res = ""; if (string_equals(coloring, "INTENSITY")) { - res = string_join(string_join(string_join(string_join("tex_voronoi(", co), " * "), scale), ").a"); + res = string("tex_voronoi(%s * %s).a", co, scale); } else { // Cells - res = string_join(string_join(string_join(string_join("tex_voronoi(", co), " * "), scale), ").r"); + res = string("tex_voronoi(%s * %s).r", co, scale); } return res; } diff --git a/paint/sources/material_nodes/warp_node.c b/paint/sources/material_nodes/warp_node.c index 6e9b2945..83981a20 100644 --- a/paint/sources/material_nodes/warp_node.c +++ b/paint/sources/material_nodes/warp_node.c @@ -12,22 +12,12 @@ char *warp_node_vector(ui_node_t *node, ui_node_socket_t *socket) { } char *angle = parser_material_parse_value_input(node->inputs->buffer[1], true); char *mask = parser_material_parse_value_input(node->inputs->buffer[2], true); - char *tex_name = string_join("texwarp_", parser_material_node_name(node, NULL)); - node_shader_add_texture(parser_material_kong, string_join("", tex_name), string_join("_", tex_name)); + char *tex_name = string("texwarp_%s", parser_material_node_name(node, NULL)); + node_shader_add_texture(parser_material_kong, tex_name, string("_%s", tex_name)); char *store = parser_material_store_var_name(node); - f32 pi = math_pi(); - parser_material_write(parser_material_kong, - string_join(string_join(string_join(string_join(string_join(string_join("var ", store), "_rad: float = "), angle), " * ("), - f32_to_string(pi)), - " / 180.0);")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_x: float = cos("), store), "_rad);")); - parser_material_write(parser_material_kong, string_join(string_join(string_join(string_join("var ", store), "_y: float = sin("), store), "_rad);")); - return string_join( - string_join(string_join(string_join(string_join(string_join(string_join(string_join("sample(", tex_name), ", sampler_linear, tex_coord + float2("), - store), - "_x, "), - store), - "_y) * "), - mask), - ").rgb"); + f32 pi = math_pi(); + parser_material_write(parser_material_kong, string("var %s_rad: float = %s * (%s / 180.0);", store, angle, f32_to_string(pi))); + parser_material_write(parser_material_kong, string("var %s_x: float = cos(%s_rad);", store, store)); + parser_material_write(parser_material_kong, string("var %s_y: float = sin(%s_rad);", store, store)); + return string("sample(%s, sampler_linear, tex_coord + float2(%s_x, %s_y) * %s).rgb", tex_name, store, store, mask); } diff --git a/paint/sources/material_nodes/wave_texture_node.c b/paint/sources/material_nodes/wave_texture_node.c index 3fe17056..addc8f3c 100644 --- a/paint/sources/material_nodes/wave_texture_node.c +++ b/paint/sources/material_nodes/wave_texture_node.c @@ -11,14 +11,12 @@ char *wave_texture_node_vector(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_wave); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = parser_material_to_vec3(string_join(string_join(string_join(string_join("tex_wave_f(", co), " * "), scale), ")")); - return res; + return parser_material_to_vec3(string("tex_wave_f(%s * %s)", co, scale)); } char *wave_texture_node_value(ui_node_t *node, ui_node_socket_t *socket) { node_shader_add_function(parser_material_kong, str_tex_wave); char *co = parser_material_get_coord(node); char *scale = parser_material_parse_value_input(node->inputs->buffer[1], false); - char *res = string_join(string_join(string_join(string_join("tex_wave_f(", co), " * "), scale), ")"); - return res; + return string("tex_wave_f(%s * %s)", co, scale); } diff --git a/paint/sources/neural_nodes/edit_image_node.c b/paint/sources/neural_nodes/edit_image_node.c index 57bf7ed6..887d4eba 100644 --- a/paint/sources/neural_nodes/edit_image_node.c +++ b/paint/sources/neural_nodes/edit_image_node.c @@ -10,7 +10,7 @@ void edit_image_node_init() { void edit_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( @@ -18,22 +18,22 @@ void edit_image_node_button(i32 node_id) { "Qwen Image Edit", }, 1); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { ui_node_t *from_node = neural_from_node(node->inputs->buffer[0], 0); gpu_texture_t *input = ui_nodes_get_node_preview_image(from_node); if (input != NULL) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif +#endif char *dir = neural_node_dir(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); if (string_equals(prompt, "")) { prompt = "."; @@ -41,15 +41,15 @@ void edit_image_node_button(i32 node_id) { string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-edit-2511-Q4_K_S.gguf"), + string("%s/qwen-image-edit-2511-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--offload-to-cpu", "--diffusion-fa", "--steps", @@ -68,9 +68,9 @@ void edit_image_node_button(i32 node_id) { "-p", prompt, "-r", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 31); diff --git a/paint/sources/neural_nodes/image_to_3d_mesh_node.c b/paint/sources/neural_nodes/image_to_3d_mesh_node.c index 6a6a35e3..59d8a4cb 100644 --- a/paint/sources/neural_nodes/image_to_3d_mesh_node.c +++ b/paint/sources/neural_nodes/image_to_3d_mesh_node.c @@ -19,7 +19,7 @@ buffer_t *image_to_3d_mesh_node_remove_background(buffer_t *buffer) { void image_to_3d_mesh_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -33,29 +33,25 @@ void image_to_3d_mesh_node_button(i32 node_id) { if (input != NULL) { char *dir = neural_node_dir(); - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = image_to_3d_mesh_node_remove_background(export_arm_bgra_swap(gpu_get_texture_pixels(input))); - #else +#else buffer_t *input_buf = image_to_3d_mesh_node_remove_background(gpu_get_texture_pixels(input)); - #endif - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); +#endif + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); dir = string_copy(string_replace_all(dir, "\\", "/")); string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(dir, "/Hunyuan3D_win64/python/python.exe"), + string("%s/Hunyuan3D_win64/python/python.exe", dir), "-s", "-B", "-c", - string_join( - string_join(string_join(string_join(string_join(string_join("from hy3dshape.pipelines import Hunyuan3DDiTFlowMatchingPipeline; " - "shape_pipeline = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('", - dir), - "/Hunyuan3D_win64/Hunyuan3D-2.1'); mesh = shape_pipeline(image='"), - dir), - "/input.png', octree_resolution=512, num_chunks=64000)[0]; mesh.export('"), - dir), - "/output.obj')"), + string("from hy3dshape.pipelines import Hunyuan3DDiTFlowMatchingPipeline; " + "shape_pipeline = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('%s/Hunyuan3D_win64/Hunyuan3D-2.1'); " + "mesh = shape_pipeline(image='%s/input.png', octree_resolution=512, num_chunks=64000)[0]; " + "mesh.export('%s/output.obj')", + dir, dir, dir), NULL, }, 6); @@ -72,7 +68,7 @@ void image_to_3d_mesh_node_check_result(ui_node_t *node) { gc_root(neural_node_current); iron_delay_idle_sleep(); if (iron_exec_async_done == 1) { - char *file = string_join(string_join(neural_node_dir(), PATH_SEP), "output.obj"); + char *file = string("%s%soutput.obj", neural_node_dir(), PATH_SEP); if (iron_file_exists(file)) { // let result: gpu_texture_t = ; // map_set(neural_node_results, node.id, result); diff --git a/paint/sources/neural_nodes/image_to_depth_node.c b/paint/sources/neural_nodes/image_to_depth_node.c index 648efaa7..df46cef6 100644 --- a/paint/sources/neural_nodes/image_to_depth_node.c +++ b/paint/sources/neural_nodes/image_to_depth_node.c @@ -10,7 +10,7 @@ void image_to_depth_node_init() { void image_to_depth_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -24,18 +24,18 @@ void image_to_depth_node_button(i32 node_id) { if (input != NULL) { char *dir = neural_node_dir(); - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); +#endif + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/marigold-depth-v1-1.q8_0.gguf"), + string("%s/marigold-depth-v1-1.q8_0.gguf", dir), "--sampling-method", "ddim_trailing", "--steps", @@ -49,9 +49,9 @@ void image_to_depth_node_button(i32 node_id) { "-p", "_height", "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 20); diff --git a/paint/sources/neural_nodes/image_to_normal_map_node.c b/paint/sources/neural_nodes/image_to_normal_map_node.c index 5aef5c4a..4803323f 100644 --- a/paint/sources/neural_nodes/image_to_normal_map_node.c +++ b/paint/sources/neural_nodes/image_to_normal_map_node.c @@ -10,7 +10,7 @@ void image_to_normal_map_node_init() { void image_to_normal_map_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -24,18 +24,18 @@ void image_to_normal_map_node_button(i32 node_id) { if (input != NULL) { char *dir = neural_node_dir(); - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); +#endif + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/marigold-normals-v1-1.q8_0.gguf"), + string("%s/marigold-normals-v1-1.q8_0.gguf", dir), "--sampling-method", "ddim_trailing", "--steps", @@ -49,9 +49,9 @@ void image_to_normal_map_node_button(i32 node_id) { "-p", "_normals", "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 20); diff --git a/paint/sources/neural_nodes/image_to_pbr_node.c b/paint/sources/neural_nodes/image_to_pbr_node.c index 3ef2c350..c92ae4f5 100644 --- a/paint/sources/neural_nodes/image_to_pbr_node.c +++ b/paint/sources/neural_nodes/image_to_pbr_node.c @@ -20,11 +20,11 @@ char *image_to_pbr_node_vector(ui_node_t *node, ui_node_socket_t *socket) { if (result == NULL) { return "float3(0.0, 0.0, 0.0)"; } - char *tex_name = string_join(parser_material_node_name(node, NULL), i32_to_string(socket->id)); + char *tex_name = string("%s%s", parser_material_node_name(node, NULL), i32_to_string(socket->id)); any_map_set(data_cached_images, tex_name, result); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, tex_name); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".rgb"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.rgb", texstore); } char *image_to_pbr_node_value(ui_node_t *node, ui_node_socket_t *socket) { @@ -46,20 +46,20 @@ char *image_to_pbr_node_value(ui_node_t *node, ui_node_socket_t *socket) { return "0.0"; } - char *tex_name = string_join(parser_material_node_name(node, NULL), i32_to_string(socket->id)); + char *tex_name = string("%s%s", parser_material_node_name(node, NULL), i32_to_string(socket->id)); any_map_set(data_cached_images, tex_name, result); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, tex_name); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".r"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.r", texstore); } void image_to_pbr_node_run_sd(char *model, char *prompt, void (*done)(gpu_texture_t *)) { - char *dir = neural_node_dir(); + char *dir = neural_node_dir(); string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(string_join(dir, "/"), model), + string("%s/%s", dir, model), "--sampling-method", "ddim_trailing", "--steps", @@ -73,9 +73,9 @@ void image_to_pbr_node_run_sd(char *model, char *prompt, void (*done)(gpu_textur "-p", prompt, "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 20); @@ -84,7 +84,7 @@ void image_to_pbr_node_run_sd(char *model, char *prompt, void (*done)(gpu_textur sys_notify_on_update(image_to_pbr_node_check_result, done); } -void image_to_pbr_node_all_done(void * _) { +void image_to_pbr_node_all_done(void *_) { render_target_t *occmap; { render_target_t *t = render_target_create(); @@ -157,7 +157,7 @@ void image_to_pbr_node_normals_done(gpu_texture_t *tex) { void image_to_pbr_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -171,12 +171,12 @@ void image_to_pbr_node_button(i32 node_id) { if (input != NULL) { char *dir = neural_node_dir(); - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); +#endif + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); image_to_pbr_node_run_sd("marigold-normals-v1-1.q8_0.gguf", "_normals", &image_to_pbr_node_normals_done); } @@ -187,7 +187,7 @@ void image_to_pbr_node_check_result(void (*done)(gpu_texture_t *)) { iron_delay_idle_sleep(); if (iron_exec_async_done == 1) { char *dir = neural_node_dir(); - char *file = string_join(string_join(dir, PATH_SEP), "output.png"); + char *file = string("%s%soutput.png", dir, PATH_SEP); if (iron_file_exists(file)) { gpu_texture_t *tex = iron_load_texture(file); done(tex); diff --git a/paint/sources/neural_nodes/inpaint_image_node.c b/paint/sources/neural_nodes/inpaint_image_node.c index c647b90e..31cf1a8f 100644 --- a/paint/sources/neural_nodes/inpaint_image_node.c +++ b/paint/sources/neural_nodes/inpaint_image_node.c @@ -14,10 +14,10 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { gpu_texture_t *mask = ui_nodes_get_node_preview_image(mask_node); if (input != NULL && mask != NULL) { - char *node_name = parser_material_node_name(node, NULL); + 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 *prompt = ui_nest(h, 1)->text; if (string_equals(prompt, "")) { prompt = "."; @@ -25,13 +25,13 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { char *dir = neural_node_dir(); if (model == 0) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); - iron_write_png(string_join(string_join(dir, PATH_SEP), "mask.png"), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); +#endif + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); + iron_write_png(string("%s%smask.png", dir, PATH_SEP), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); } else { gpu_texture_t *masked = gpu_create_render_target(512, 512, GPU_TEXTURE_FORMAT_RGBA32); @@ -42,16 +42,16 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { draw_scaled_image(mask, 0, 0, 512, 512); draw_set_pipeline(NULL); draw_end(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), gpu_get_texture_pixels(masked), masked->width, masked->height, 0); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), gpu_get_texture_pixels(masked), masked->width, masked->height, 0); } string_t_array_t *argv; if (model == 0) { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/v1-5-pruned-emaonly.safetensors"), + string("%s/v1-5-pruned-emaonly.safetensors", dir), "--steps", "30", "-s", @@ -67,11 +67,11 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { "-p", prompt, "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "--mask", - string_join(dir, "/mask.png"), + string("%s/mask.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 24); @@ -79,15 +79,15 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { else { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-edit-2511-Q4_K_S.gguf"), + string("%s/qwen-image-edit-2511-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--offload-to-cpu", "--diffusion-fa", "--qwen-image-zero-cond-t", @@ -102,9 +102,9 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { "-p", "inpaint red area", "-r", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 27); @@ -118,7 +118,7 @@ void inpaint_image_node_button_on_next_frame(ui_node_t *node) { void inpaint_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -126,8 +126,8 @@ void inpaint_image_node_button(i32 node_id) { "Qwen Image Edit", }, 2); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { diff --git a/paint/sources/neural_nodes/neural_node.c b/paint/sources/neural_nodes/neural_node.c index 97ffe988..4ed524c2 100644 --- a/paint/sources/neural_nodes/neural_node.c +++ b/paint/sources/neural_nodes/neural_node.c @@ -9,8 +9,8 @@ char *neural_node_vector(ui_node_t *node, ui_node_socket_t *socket) { char *tex_name = parser_material_node_name(node, NULL); any_map_set(data_cached_images, tex_name, result); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, tex_name); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".rgb"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.rgb", texstore); } char *neural_node_value(ui_node_t *node, ui_node_socket_t *socket) { @@ -21,8 +21,8 @@ char *neural_node_value(ui_node_t *node, ui_node_socket_t *socket) { char *tex_name = parser_material_node_name(node, NULL); any_map_set(data_cached_images, tex_name, result); bind_tex_t *tex = parser_material_make_bind_tex(tex_name, tex_name); - char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); - return string_join(texstore, ".r"); + char *texstore = parser_material_texture_store(node, tex, tex_name, COLOR_SPACE_AUTO); + return string("%s.r", texstore); } ui_node_t *neural_from_node(ui_node_socket_t *inp, i32 socket) { @@ -38,7 +38,7 @@ ui_node_t *neural_from_node(ui_node_socket_t *inp, i32 socket) { return result; } -void neural_node_button_on_next_frame(void * _) { +void neural_node_button_on_next_frame(void *_) { box_preferences_htab->i = PREFERENCE_TAB_NEURAL; box_preferences_show(); } @@ -46,7 +46,7 @@ void neural_node_button_on_next_frame(void * _) { bool neural_node_button(ui_node_t *node, char *model) { char *url = box_preferneces_model_url_from_name(model); char *file_name = box_preferences_file_name_from_url(url); - bool found = box_preferences_model_exists(file_name); + bool found = box_preferences_model_exists(file_name); if (iron_exec_async_done == 0) { if (node != neural_node_current) { ui->enabled = false; @@ -71,7 +71,7 @@ void neural_node_check_result(ui_node_t *node) { gc_root(neural_node_current); iron_delay_idle_sleep(); if (iron_exec_async_done == 1) { - char *file = string_join(string_join(neural_node_dir(), PATH_SEP), "output.png"); + 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); @@ -83,38 +83,38 @@ void neural_node_check_result(ui_node_t *node) { } char *neural_node_sd_bin_ext() { - #ifdef IRON_WINDOWS +#ifdef IRON_WINDOWS return ".exe"; - #else +#else return ""; - #endif +#endif } char *neural_node_sd_bin() { if (config_raw->neural_backend == NEURAL_BACKEND_VULKAN) { - return string_join("sd_vulkan", neural_node_sd_bin_ext()); + return string("sd_vulkan%s", neural_node_sd_bin_ext()); } if (config_raw->neural_backend == NEURAL_BACKEND_CUDA) { - return string_join("sd_cuda", neural_node_sd_bin_ext()); + return string("sd_cuda%s", neural_node_sd_bin_ext()); } - return string_join("sd_cpu", neural_node_sd_bin_ext()); + return string("sd_cpu%s", neural_node_sd_bin_ext()); } char *neural_node_dir() { char *dir; if (path_is_protected()) { - dir = string_join(iron_internal_save_path(), "models"); + dir = string("%smodels", iron_internal_save_path()); } else { - dir = string_join(string_join(iron_internal_files_location(), PATH_SEP), "models"); + dir = string("%s%smodels", iron_internal_files_location(), PATH_SEP); } return dir; } #ifdef WITH_COMPRESS -void neural_node_download_done_untar(void * _) { - char *tar = string_join(neural_node_dir(), "/Hunyuan3D_win64.tar"); +void neural_node_download_done_untar(void *_) { + char *tar = string("%s/Hunyuan3D_win64.tar", neural_node_dir()); untar_here(tar); } @@ -122,32 +122,32 @@ void neural_node_download_done_untar(void * _) { void neural_node_download_done(char *url) { neural_node_downloading--; - console_log(string_join(string_join(tr("Downloaded file from", NULL), " "), url)); + console_log(string("%s %s", tr("Downloaded file from", NULL), url)); - #ifdef IRON_LINUX +#ifdef IRON_LINUX // todo if (ends_with(url, "sd_vulkan")) { - char *bin = string_join(neural_node_dir(), "/sd_vulkan"); - iron_sys_command(string_join(string_join("chmod +x \"", bin), "\"")); + char *bin = string("%s/sd_vulkan", neural_node_dir()); + iron_sys_command(string("chmod +x \"%s\"", bin)); } else if (ends_with(url, "sd_cpu")) { - char *bin = string_join(neural_node_dir(), "/sd_cpu"); - iron_sys_command(string_join(string_join("chmod +x \"", bin), "\"")); + char *bin = string("%s/sd_cpu", neural_node_dir()); + iron_sys_command(string("chmod +x \"%s\"", bin)); } - #endif +#endif - #ifdef WITH_COMPRESS +#ifdef WITH_COMPRESS if (ends_with(url, "Hunyuan3D_win64.tar")) { console_toast(tr("Unpacking Hunyuan3D_win64.tar", NULL)); sys_notify_on_next_frame(&neural_node_download_done_untar, NULL); } - #endif +#endif } void neural_node_download(char *url) { char *file_name = substring(url, string_last_index_of(url, "/") + 1, string_length(url)); - char *file_path = string_join(string_join(neural_node_dir(), PATH_SEP), file_name); - bool found = iron_file_exists(file_path); + char *file_path = string("%s%s%s", neural_node_dir(), PATH_SEP, file_name); + bool found = iron_file_exists(file_path); if (found) { return; } @@ -161,17 +161,17 @@ void neural_node_download_models(string_t_array_t *models) { iron_create_directory(neural_node_dir()); } - #ifdef IRON_WINDOWS +#ifdef IRON_WINDOWS neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/windows_x64/sd_cpu.exe"); neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/windows_x64/sd_vulkan.exe"); neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/windows_x64/sd_cuda.exe"); - #elif defined(IRON_LINUX) +#elif defined(IRON_LINUX) neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/linux_x64/sd_cpu"); neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/linux_x64/sd_vulkan"); - #else +#else neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/macos/sd_cpu"); neural_node_download("https://huggingface.co/armory3d/sd_bin/resolve/main/macos/sd_vulkan"); - #endif +#endif iron_net_bytes_downloaded = 0; diff --git a/paint/sources/neural_nodes/outpaint_image_node.c b/paint/sources/neural_nodes/outpaint_image_node.c index 25e52bc6..1eef2f06 100644 --- a/paint/sources/neural_nodes/outpaint_image_node.c +++ b/paint/sources/neural_nodes/outpaint_image_node.c @@ -12,10 +12,10 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { gpu_texture_t *input = ui_nodes_get_node_preview_image(from_node); if (input != NULL) { - char *node_name = parser_material_node_name(node, NULL); + 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 *prompt = ui_nest(h, 1)->text; if (string_equals(prompt, "")) { prompt = "."; @@ -39,17 +39,16 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { // #endif char *dir = neural_node_dir(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), gpu_get_texture_pixels(input_scaled), input_scaled->width, input_scaled->height, - 0); - iron_write_png(string_join(string_join(dir, PATH_SEP), "mask.png"), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), gpu_get_texture_pixels(input_scaled), input_scaled->width, input_scaled->height, 0); + iron_write_png(string("%s%smask.png", dir, PATH_SEP), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); string_t_array_t *argv; if (model == 0) { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/v1-5-pruned-emaonly.safetensors"), + string("%s/v1-5-pruned-emaonly.safetensors", dir), "--offload-to-cpu", "--steps", "30", @@ -66,11 +65,11 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { "-p", prompt, "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "--mask", - string_join(dir, "/mask.png"), + string("%s/mask.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 25); @@ -78,15 +77,15 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { else { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-edit-2511-Q4_K_S.gguf"), + string("%s/qwen-image-edit-2511-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--offload-to-cpu", "--diffusion-fa", "--qwen-image-zero-cond-t", @@ -101,9 +100,9 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { "-p", "replace red squares by extending image contents", // prompt, "-r", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 27); @@ -117,7 +116,7 @@ void outpaint_image_node_button_on_next_frame(ui_node_t *node) { void outpaint_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -125,8 +124,8 @@ void outpaint_image_node_button(i32 node_id) { "Qwen Image Edit", }, 2); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { diff --git a/paint/sources/neural_nodes/text_to_image_node.c b/paint/sources/neural_nodes/text_to_image_node.c index b6b3595f..f4813279 100644 --- a/paint/sources/neural_nodes/text_to_image_node.c +++ b/paint/sources/neural_nodes/text_to_image_node.c @@ -10,9 +10,9 @@ void text_to_image_node_init() { string_t_array_t *text_to_image_node_sd_args(char *dir, char *prompt) { string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/v1-5-pruned-emaonly.safetensors"), + string("%s/v1-5-pruned-emaonly.safetensors", dir), "--offload-to-cpu", "-W", "512", @@ -23,9 +23,9 @@ string_t_array_t *text_to_image_node_sd_args(char *dir, char *prompt) { "-s", "-1", "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), "-p", - string_join(string_join("'", prompt), "'"), + string("'%s'", prompt), NULL, }, 17); @@ -35,13 +35,13 @@ string_t_array_t *text_to_image_node_sd_args(char *dir, char *prompt) { string_t_array_t *text_to_image_node_zimage_args(char *dir, char *prompt) { string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/z_image_turbo-Q4_K.gguf"), + string("%s/z_image_turbo-Q4_K.gguf", dir), "--vae", - string_join(dir, "/ae.safetensors"), + string("%s/ae.safetensors", dir), "--llm", - string_join(dir, "/Qwen3-4B-Instruct-2507-Q4_K_S.gguf"), + string("%s/Qwen3-4B-Instruct-2507-Q4_K_S.gguf", dir), "--diffusion-fa", "--offload-to-cpu", "--cfg-scale", @@ -55,9 +55,9 @@ string_t_array_t *text_to_image_node_zimage_args(char *dir, char *prompt) { "-s", "-1", "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), "-p", - string_join(string_join("'", prompt), "'"), + string("'%s'", prompt), NULL, }, 24); @@ -67,15 +67,15 @@ string_t_array_t *text_to_image_node_zimage_args(char *dir, char *prompt) { string_t_array_t *text_to_image_node_qwen_args(char *dir, char *prompt) { string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-2512-Q4_K_S.gguf"), + string("%s/qwen-image-2512-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--sampling-method", "euler", "--offload-to-cpu", @@ -88,9 +88,9 @@ string_t_array_t *text_to_image_node_qwen_args(char *dir, char *prompt) { "-s", "-1", "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), "-p", - string_join(string_join("'", prompt), "'"), + string("'%s'", prompt), NULL, }, 25); @@ -100,17 +100,17 @@ string_t_array_t *text_to_image_node_qwen_args(char *dir, char *prompt) { string_t_array_t *text_to_image_node_wan_args(char *dir, char *prompt) { string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-M", "vid_gen", "--diffusion-model", - string_join(dir, "/Wan2.2-T2V-A14B-LowNoise-Q4_K_S.gguf"), + string("%s/Wan2.2-T2V-A14B-LowNoise-Q4_K_S.gguf", dir), "--high-noise-diffusion-model", - string_join(dir, "/Wan2.2-T2V-A14B-HighNoise-Q4_K_S.gguf"), + string("%s/Wan2.2-T2V-A14B-HighNoise-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Wan2.1_VAE.safetensors"), + string("%s/Wan2.1_VAE.safetensors", dir), "--t5xxl", - string_join(dir, "/umt5-xxl-encoder-Q4_K_S.gguf"), + string("%s/umt5-xxl-encoder-Q4_K_S.gguf", dir), "--sampling-method", "euler", "--steps", @@ -127,7 +127,7 @@ string_t_array_t *text_to_image_node_wan_args(char *dir, char *prompt) { "-s", "-1", "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), "-p", prompt, NULL, @@ -138,7 +138,7 @@ string_t_array_t *text_to_image_node_wan_args(char *dir, char *prompt) { 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); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -148,8 +148,8 @@ void text_to_image_node_button(i32 node_id) { "Wan", }, 4); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { diff --git a/paint/sources/neural_nodes/tile_image_node.c b/paint/sources/neural_nodes/tile_image_node.c index 07fe6440..82e1cbf5 100644 --- a/paint/sources/neural_nodes/tile_image_node.c +++ b/paint/sources/neural_nodes/tile_image_node.c @@ -11,10 +11,10 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { ui_node_t *from_node = neural_from_node(node->inputs->buffer[0], 0); gpu_texture_t *input = ui_nodes_get_node_preview_image(from_node); if (input != NULL) { - char *node_name = parser_material_node_name(node, NULL); + 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 *prompt = ui_nest(h, 1)->text; gpu_texture_t *tile = gpu_create_render_target(512, 512, GPU_TEXTURE_FORMAT_RGBA32); draw_begin(tile, false, 0); draw_scaled_image(input, -256, -256, 512, 512); @@ -38,9 +38,9 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { // u8a[i] = (x > 256 - l && x < 256 + l) ? 128 : 0; } gpu_texture_t *mask = gpu_create_texture_from_bytes(u8a, 512, 512, GPU_TEXTURE_FORMAT_R8); - char *dir = neural_node_dir(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), gpu_get_texture_pixels(tile), tile->width, tile->height, 0); - iron_write_png(string_join(string_join(dir, PATH_SEP), "mask.png"), gpu_get_texture_pixels(mask), mask->width, mask->height, 1); + char *dir = neural_node_dir(); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), gpu_get_texture_pixels(tile), tile->width, tile->height, 0); + iron_write_png(string("%s%smask.png", dir, PATH_SEP), gpu_get_texture_pixels(mask), mask->width, mask->height, 1); if (string_equals(prompt, "")) { prompt = "."; @@ -50,9 +50,9 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { if (model == 0) { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/v1-5-pruned-emaonly.safetensors"), + string("%s/v1-5-pruned-emaonly.safetensors", dir), "--offload-to-cpu", "--steps", "30", @@ -65,11 +65,11 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { "-p", prompt, "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "--mask", - string_join(dir, "/mask.png"), + string("%s/mask.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 21); @@ -77,15 +77,15 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { else { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-edit-2511-Q4_K_S.gguf"), + string("%s/qwen-image-edit-2511-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--offload-to-cpu", "--diffusion-fa", "--qwen-image-zero-cond-t", @@ -100,9 +100,9 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { "-p", "replace red area by extending image contents. modify red area only", "-r", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 27); @@ -116,7 +116,7 @@ void tile_image_node_button_on_next_frame(ui_node_t *node) { void tile_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -124,8 +124,8 @@ void tile_image_node_button(i32 node_id) { "Qwen Image Edit", }, 2); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) { diff --git a/paint/sources/neural_nodes/upscale_image_node.c b/paint/sources/neural_nodes/upscale_image_node.c index 4d32aa12..78359d61 100644 --- a/paint/sources/neural_nodes/upscale_image_node.c +++ b/paint/sources/neural_nodes/upscale_image_node.c @@ -10,7 +10,7 @@ void upscale_image_node_init() { void upscale_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -22,26 +22,26 @@ void upscale_image_node_button(i32 node_id) { ui_node_t *from_node = neural_from_node(node->inputs->buffer[0], 0); gpu_texture_t *input = ui_nodes_get_node_preview_image(from_node); if (input != NULL) { - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif +#endif char *dir = neural_node_dir(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); string_t_array_t *argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-M", "upscale", "--upscale-model", - string_join(dir, "/RealESRGAN_x4plus.pth"), + string("%s/RealESRGAN_x4plus.pth", dir), "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 10); diff --git a/paint/sources/neural_nodes/vary_image_node.c b/paint/sources/neural_nodes/vary_image_node.c index b30a67a3..6ace63d1 100644 --- a/paint/sources/neural_nodes/vary_image_node.c +++ b/paint/sources/neural_nodes/vary_image_node.c @@ -16,20 +16,20 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { draw_begin(mask, true, 0xffffffff); draw_end(); - #ifdef IRON_BGRA +#ifdef IRON_BGRA buffer_t *input_buf = export_arm_bgra_swap(gpu_get_texture_pixels(input)); // Vulkan non-rt textures need a flip - #else +#else buffer_t *input_buf = gpu_get_texture_pixels(input); - #endif +#endif char *dir = neural_node_dir(); - iron_write_png(string_join(string_join(dir, PATH_SEP), "input.png"), input_buf, input->width, input->height, 0); - iron_write_png(string_join(string_join(dir, PATH_SEP), "mask.png"), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); + iron_write_png(string("%s%sinput.png", dir, PATH_SEP), input_buf, input->width, input->height, 0); + iron_write_png(string("%s%smask.png", dir, PATH_SEP), gpu_get_texture_pixels(mask), mask->width, mask->height, 0); - char *node_name = parser_material_node_name(node, NULL); + 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 *prompt = ui_nest(h, 1)->text; if (string_equals(prompt, "")) { prompt = "."; @@ -39,9 +39,9 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { if (model == 0) { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "-m", - string_join(dir, "/v1-5-pruned-emaonly.safetensors"), + string("%s/v1-5-pruned-emaonly.safetensors", dir), "--offload-to-cpu", "--steps", "30", @@ -58,11 +58,11 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { "-p", prompt, "-i", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "--mask", - string_join(dir, "/mask.png"), + string("%s/mask.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 25); @@ -70,15 +70,15 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { else { argv = any_array_create_from_raw( (void *[]){ - string_join(string_join(dir, "/"), neural_node_sd_bin()), + string("%s/%s", dir, neural_node_sd_bin()), "--diffusion-model", - string_join(dir, "/qwen-image-edit-2511-Q4_K_S.gguf"), + string("%s/qwen-image-edit-2511-Q4_K_S.gguf", dir), "--vae", - string_join(dir, "/Qwen_Image-VAE.safetensors"), + string("%s/Qwen_Image-VAE.safetensors", dir), "--llm", - string_join(dir, "/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf"), + string("%s/Qwen2.5-VL-7B-Instruct-Q4_K_S.gguf", dir), "--llm_vision", - string_join(dir, "/mmproj-F16.gguf"), + string("%s/mmproj-F16.gguf", dir), "--offload-to-cpu", "--diffusion-fa", "--qwen-image-zero-cond-t", @@ -98,9 +98,9 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { "vary contents of the image", // prompt, "-r", - string_join(dir, "/input.png"), + string("%s/input.png", dir), "-o", - string_join(dir, "/output.png"), + string("%s/output.png", dir), NULL, }, 27); @@ -114,7 +114,7 @@ void vary_image_node_button_on_next_frame(ui_node_t *node) { void vary_image_node_button(i32 node_id) { ui_node_canvas_t *canvas = ui_nodes_get_canvas(true); ui_node_t *node = ui_get_node(canvas->nodes, node_id); - char *node_name = parser_material_node_name(node, NULL); + char *node_name = parser_material_node_name(node, NULL); ui_handle_t *h = ui_handle(node_name); string_t_array_t *models = any_array_create_from_raw( (void *[]){ @@ -122,8 +122,8 @@ void vary_image_node_button(i32 node_id) { "Qwen Image Edit", }, 2); - i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); - char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); + i32 model = ui_combo(ui_nest(h, 0), models, tr("Model", NULL), false, UI_ALIGN_LEFT, true); + char *prompt = ui_text_area(ui_nest(h, 1), UI_ALIGN_LEFT, true, tr("prompt", NULL), true); node->buttons->buffer[0]->height = string_split(prompt, "\n")->length + 2; if (neural_node_button(node, models->buffer[model])) {