Files
armorpaint/paint/sources/ui/tab_materials.c
T

452 lines
16 KiB
C
Raw Normal View History

2026-03-09 13:17:15 +01:00
2026-06-04 11:00:05 +02:00
#include "../global.h"
2026-03-09 13:17:15 +01:00
2026-04-05 16:09:00 +02:00
i32 _tab_materials_draw_slots;
2026-04-21 07:59:19 +02:00
i32 tab_materials_drag_pos = -1;
2026-04-05 16:09:00 +02:00
2026-03-06 12:56:38 +01:00
void tab_materials_button_nodes() {
2026-03-15 11:37:45 +01:00
if (ui_button(tr("Nodes"), UI_ALIGN_CENTER, "")) {
2026-03-06 12:56:38 +01:00
ui_base_show_material_nodes();
}
2026-06-08 11:42:44 +02:00
else if (g_ui->is_hovered) {
2026-06-08 11:31:49 +02:00
ui_tooltip(string("%s (%s)", tr("Show Node Editor"), (char *)any_map_get(g_keymap, "toggle_node_editor")));
2026-03-06 12:56:38 +01:00
}
}
2026-04-04 21:38:20 +02:00
void tab_materials_draw_slots_update_fill_layers(void *_) {
layers_update_fill_layers();
}
void tab_materials_update_material() {
ui_header_handle->redraws = 2;
ui_nodes_hwnd->redraws = 2;
gc_unroot(ui_nodes_group_stack);
ui_nodes_group_stack = any_array_create_from_raw((void *[]){}, 0);
gc_root(ui_nodes_group_stack);
make_material_parse_paint_material(true);
util_render_make_material_preview();
bool decal = context_is_decal();
if (decal) {
util_render_make_decal_preview();
}
2026-04-15 10:10:17 +02:00
base_update_workflow();
2026-04-04 21:38:20 +02:00
}
2026-03-10 21:00:00 +01:00
void tab_materials_draw_slots_duplicate(void *_) {
2026-04-15 22:34:47 +02:00
i32 i = _tab_materials_draw_slots;
2026-06-05 20:34:10 +02:00
g_context->material = slot_material_create(g_project->_->materials->buffer[0]->data, NULL);
any_array_push(g_project->_->materials, g_context->material);
ui_node_canvas_t *cloned = util_clone_canvas(g_project->_->materials->buffer[i]->canvas);
2026-04-05 16:41:00 +02:00
g_context->material->canvas = cloned;
2026-03-09 23:02:08 +01:00
tab_materials_update_material();
history_duplicate_material();
}
2026-04-04 21:38:20 +02:00
void tab_materials_update_material_pointers(ui_node_t_array_t *nodes, i32 i) {
for (i32 i = 0; i < nodes->length; ++i) {
ui_node_t *n = nodes->buffer[i];
if (string_equals(n->type, "MATERIAL")) {
if (n->buttons->buffer[0]->default_value->buffer[0] == i) {
n->buttons->buffer[0]->default_value->buffer[0] = 9999; // Material deleted
}
else if (n->buttons->buffer[0]->default_value->buffer[0] > i) {
n->buttons->buffer[0]->default_value->buffer[0]--; // Offset by deleted material
}
}
}
}
void tab_materials_delete_material(slot_material_t *m) {
2026-06-05 20:34:10 +02:00
i32 i = array_index_of(g_project->_->materials, m);
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
slot_layer_t *l = g_project->_->layers->buffer[i];
2026-05-13 17:11:52 +02:00
if (l->fill_material == m) {
l->fill_material = NULL;
2026-04-04 21:38:20 +02:00
}
}
history_delete_material();
2026-06-05 20:34:10 +02:00
context_select_material(i == g_project->_->materials->length - 1 ? i - 1 : i + 1);
array_splice(g_project->_->materials, i, 1);
2026-04-04 21:38:20 +02:00
ui_base_hwnds->buffer[1]->redraws = 2;
2026-06-05 20:34:10 +02:00
for (i32 i = 0; i < g_project->_->materials->length; ++i) {
slot_material_t *m = g_project->_->materials->buffer[i];
2026-04-04 21:38:20 +02:00
tab_materials_update_material_pointers(m->canvas->nodes, i);
}
for (i32 i = 0; i < m->canvas->nodes->length; ++i) {
ui_node_t *n = m->canvas->nodes->buffer[i];
ui_viewnodes_on_node_remove(n);
}
}
2026-03-09 23:02:08 +01:00
void tab_materials_draw_slots_menu() {
i32 i = _tab_materials_draw_slots;
2026-06-05 20:34:10 +02:00
slot_material_t *m = g_project->_->materials->buffer[i];
2026-03-09 23:02:08 +01:00
2026-03-15 11:37:45 +01:00
if (ui_menu_button(tr("To Fill Layer"), "", ICON_SPHERE)) {
2026-03-09 23:02:08 +01:00
context_select_material(i);
2026-04-05 23:00:47 +02:00
layers_create_fill_layer(UV_TYPE_UVMAP, mat4_nan(), -1);
2026-03-09 23:02:08 +01:00
}
2026-03-15 11:37:45 +01:00
if (ui_menu_button(tr("Export"), "", ICON_EXPORT)) {
2026-03-09 23:02:08 +01:00
context_select_material(i);
box_export_show_material();
}
2026-03-15 11:37:45 +01:00
if (ui_menu_button(tr("Bake"), "", ICON_BAKE)) {
2026-03-09 23:02:08 +01:00
context_select_material(i);
box_export_show_bake_material();
}
2026-04-18 14:14:54 +02:00
if (ui_menu_button(tr("Duplicate"), "ctrl+d", ICON_DUPLICATE)) {
2026-03-09 23:02:08 +01:00
sys_notify_on_next_frame(&tab_materials_draw_slots_duplicate, NULL);
}
2026-06-05 20:34:10 +02:00
if (g_project->_->materials->length > 1 && ui_menu_button(tr("Delete"), "delete", ICON_DELETE)) {
2026-03-09 23:02:08 +01:00
tab_materials_delete_material(m);
}
2026-04-15 10:10:17 +02:00
if (g_config->experimental && ui_menu_button(tr("Inspect as Script"), "", ICON_SEARCH)) {
node_shader_dump_to_script = true;
context_select_material(i);
}
2026-06-05 14:48:27 +02:00
ui_handle_t *base_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *opac_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *nor_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *occ_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *rough_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *met_handle = ui_nest(ui_handle(__ID__), m->id);
2026-03-09 23:02:08 +01:00
ui_handle_t *height_handle = ui_nest(ui_handle(__ID__), m->id);
2026-06-05 14:48:27 +02:00
ui_handle_t *emis_handle = ui_nest(ui_handle(__ID__), m->id);
ui_handle_t *subs_handle = ui_nest(ui_handle(__ID__), m->id);
base_handle->b = m->paint_base;
opac_handle->b = m->paint_opac;
nor_handle->b = m->paint_nor;
occ_handle->b = m->paint_occ;
rough_handle->b = m->paint_rough;
met_handle->b = m->paint_met;
height_handle->b = m->paint_height;
emis_handle->b = m->paint_emis;
subs_handle->b = m->paint_subs;
2026-03-09 23:02:08 +01:00
ui_menu_separator();
ui_menu_align();
ui_menu_label(tr("Opacity Mode"), NULL);
ui_menu_align();
ui_handle_t *opac_mode_handle = ui_handle(__ID__);
opac_mode_handle->i = m->paint_opac_mode;
string_array_t *opac_mode_items = any_array_create_from_raw(
2026-04-21 10:52:27 +02:00
(void *[]){
tr("Alpha"),
tr("Translucency"),
},
2);
m->paint_opac_mode = ui_inline_radio(opac_mode_handle, opac_mode_items, UI_ALIGN_LEFT);
2026-03-09 23:02:08 +01:00
ui_menu_separator();
ui_menu_align();
2026-03-15 11:37:45 +01:00
ui_menu_label(tr("Channels"), NULL);
2026-03-09 23:02:08 +01:00
ui_menu_align();
ui_row2();
2026-03-15 11:37:45 +01:00
m->paint_base = ui_check(base_handle, tr("Base Color"), "");
m->paint_opac = ui_check(opac_handle, tr("Opacity"), "");
2026-03-11 14:28:58 +01:00
2026-04-05 16:41:00 +02:00
if (g_config->workflow == WORKFLOW_PBR) {
2026-03-11 14:28:58 +01:00
ui_row2();
2026-03-15 11:37:45 +01:00
m->paint_nor = ui_check(nor_handle, tr("Normal"), "");
m->paint_height = ui_check(height_handle, tr("Height"), "");
2026-03-11 14:28:58 +01:00
ui_row2();
2026-03-15 11:37:45 +01:00
m->paint_rough = ui_check(rough_handle, tr("Roughness"), "");
m->paint_met = ui_check(met_handle, tr("Metallic"), "");
2026-03-11 14:28:58 +01:00
ui_row2();
2026-03-15 11:37:45 +01:00
m->paint_emis = ui_check(emis_handle, tr("Emission"), "");
m->paint_subs = ui_check(subs_handle, tr("Subsurface"), "");
m->paint_occ = ui_check(occ_handle, tr("Occlusion"), "");
2026-03-11 14:28:58 +01:00
}
2026-03-09 23:02:08 +01:00
if (base_handle->changed || opac_handle->changed || nor_handle->changed || occ_handle->changed || rough_handle->changed || met_handle->changed ||
height_handle->changed || emis_handle->changed || subs_handle->changed || opac_mode_handle->changed) {
2026-03-09 23:02:08 +01:00
make_material_parse_paint_material(true);
if (opac_mode_handle->changed) {
sys_notify_on_next_frame(util_render_make_material_preview, NULL);
}
2026-03-09 23:02:08 +01:00
ui_menu_keep_open = true;
}
}
2026-03-06 12:56:38 +01:00
void tab_materials_draw_slots(bool mini) {
2026-04-21 10:52:27 +02:00
i32 slotw = math_floor(51 * UI_SCALE() + g_config->window_scale * 2);
2026-06-08 11:42:44 +02:00
i32 num = math_floor(g_ui->_window_w / (float)slotw);
2026-03-06 12:56:38 +01:00
if (num == 0) {
return;
}
2026-04-21 07:59:19 +02:00
bool drag_pos_set = false;
f32 uix = 0.0;
f32 uiy = 0.0;
i32 imgw_val = math_floor(50 * UI_SCALE());
2026-06-05 20:34:10 +02:00
for (i32 row = 0; row < math_floor(math_ceil(g_project->_->materials->length / (float)num)); ++row) {
2026-04-05 16:41:00 +02:00
i32 mult = g_config->show_asset_names ? 2 : 1;
2026-03-06 12:56:38 +01:00
f32_array_t *ar = f32_array_create_from_raw((f32[]){}, 0);
for (i32 i = 0; i < num * mult; ++i) {
f32_array_push(ar, 1 / (float)num);
}
ui_row(ar);
2026-06-08 11:42:44 +02:00
g_ui->_x += 2;
2026-04-05 16:41:00 +02:00
f32 off = g_config->show_asset_names ? UI_ELEMENT_OFFSET() * 10.0 : 6;
2026-03-06 12:56:38 +01:00
if (row > 0) {
2026-06-08 11:42:44 +02:00
g_ui->_y += off;
2026-03-06 12:56:38 +01:00
}
for (i32 j = 0; j < num; ++j) {
i32 imgw = math_floor(50 * UI_SCALE());
i32 i = j + row * num;
2026-06-05 20:34:10 +02:00
if (i >= g_project->_->materials->length) {
2026-03-06 12:56:38 +01:00
ui_end_element_of_size(imgw);
2026-04-05 16:41:00 +02:00
if (g_config->show_asset_names) {
2026-03-06 12:56:38 +01:00
ui_end_element_of_size(0);
}
continue;
}
2026-06-05 20:34:10 +02:00
gpu_texture_t *img = UI_SCALE() > 1 ? g_project->_->materials->buffer[i]->image : g_project->_->materials->buffer[i]->image_icon;
gpu_texture_t *img_full = g_project->_->materials->buffer[i]->image;
2026-03-06 12:56:38 +01:00
// Highligh selected
2026-06-05 20:34:10 +02:00
if (g_context->material == g_project->_->materials->buffer[i]) {
2026-03-06 12:56:38 +01:00
if (mini) {
2026-06-08 11:42:44 +02:00
f32 w = g_ui->_w / (float)UI_SCALE();
2026-06-08 15:35:04 +02:00
ui_rect(0, -2, w - 2, w - 4, g_theme->HIGHLIGHT_COL, 3);
2026-03-06 12:56:38 +01:00
}
else {
i32 off = row % 2 == 1 ? 1 : 0;
2026-04-05 16:41:00 +02:00
i32 w = 50 + math_floor(g_config->window_scale * 2);
2026-06-08 15:35:04 +02:00
ui_fill(-1, -2, w + 3, 2, g_theme->HIGHLIGHT_COL);
ui_fill(-1, w - off, w + 3, 2 + off, g_theme->HIGHLIGHT_COL);
ui_fill(-1, -2, 2, w + 3, g_theme->HIGHLIGHT_COL);
ui_fill(w + 1, -2, 2, w + 4, g_theme->HIGHLIGHT_COL);
2026-03-06 12:56:38 +01:00
}
}
// Draw material icon
2026-06-08 11:42:44 +02:00
uix = g_ui->_x;
uiy = g_ui->_y;
2026-04-21 10:52:27 +02:00
i32 tile = UI_SCALE() > 1 ? 100 : 50;
f32 imgh = mini ? ui_sidebar_default_w_mini * 0.85 * UI_SCALE() : 50 * UI_SCALE();
2026-04-21 07:59:19 +02:00
if (base_drag_material != NULL && tab_materials_drag_pos == i) {
2026-06-08 15:35:04 +02:00
ui_fill(-1, -2, 2, imgw_val + 4, g_theme->HIGHLIGHT_COL);
2026-04-21 07:59:19 +02:00
}
2026-06-08 11:54:42 +02:00
ui_state_t state = g_project->_->materials->buffer[i]->preview_ready
? ui_image(img, 0xffffffff, imgh)
: ui_sub_image(resource_get("icons.k"), 0xffffffff, -1.0, tile, tile, tile, tile);
2026-03-06 12:56:38 +01:00
2026-04-21 07:59:19 +02:00
if (state == UI_STATE_HOVERED && base_drag_material != NULL) {
2026-06-08 11:42:44 +02:00
tab_materials_drag_pos = (mouse_x > uix + g_ui->_window_x + imgw_val / 2.0) ? i + 1 : i;
2026-04-21 07:59:19 +02:00
drag_pos_set = true;
}
2026-03-06 12:56:38 +01:00
// Draw material numbers when selecting a material via keyboard shortcut
2026-06-08 11:42:44 +02:00
bool is_typing = g_ui->is_typing;
2026-03-06 12:56:38 +01:00
if (!is_typing) {
2026-06-08 11:31:49 +02:00
if (i < 9 && operator_shortcut(any_map_get(g_keymap, "select_material"), SHORTCUT_TYPE_DOWN)) {
2026-03-07 21:12:59 +01:00
char *number = i32_to_string(i + 1);
2026-06-08 15:35:04 +02:00
i32 width = draw_string_width(g_font, g_ui->font_size, number) + 10;
i32 height = draw_font_height(g_font, g_ui->font_size);
draw_set_color(g_theme->TEXT_COL);
2026-03-06 12:56:38 +01:00
draw_filled_rect(uix, uiy, width, height);
2026-06-08 15:35:04 +02:00
draw_set_color(g_theme->BUTTON_COL);
2026-03-06 12:56:38 +01:00
draw_string(number, uix + 5, uiy);
}
}
// Select material
2026-06-08 11:42:44 +02:00
if (state == UI_STATE_STARTED && g_ui->input_y > g_ui->_window_y) {
2026-06-05 20:34:10 +02:00
if (g_context->material != g_project->_->materials->buffer[i]) {
2026-03-06 12:56:38 +01:00
context_select_material(i);
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_MATERIAL) {
2026-03-09 23:02:08 +01:00
sys_notify_on_next_frame(&tab_materials_draw_slots_update_fill_layers, NULL);
2026-03-06 12:56:38 +01:00
}
}
2026-06-08 11:42:44 +02:00
base_drag_off_x = -(mouse_x - uix - g_ui->_window_x - 3);
base_drag_off_y = -(mouse_y - uiy - g_ui->_window_y + 1);
2026-03-06 12:56:38 +01:00
gc_unroot(base_drag_material);
2026-04-05 16:41:00 +02:00
base_drag_material = g_context->material;
2026-03-06 12:56:38 +01:00
gc_root(base_drag_material);
// Double click to show nodes
2026-04-05 16:41:00 +02:00
if (sys_time() - g_context->select_time < 0.2) {
2026-03-06 12:56:38 +01:00
ui_base_show_material_nodes();
gc_unroot(base_drag_material);
2026-03-07 21:12:59 +01:00
base_drag_material = NULL;
2026-03-06 12:56:38 +01:00
base_is_dragging = false;
}
2026-04-05 16:41:00 +02:00
g_context->select_time = sys_time();
2026-03-06 12:56:38 +01:00
}
// Context menu
2026-06-08 11:42:44 +02:00
if (g_ui->is_hovered && g_ui->input_released_r) {
2026-03-06 12:56:38 +01:00
context_select_material(i);
_tab_materials_draw_slots = i;
2026-03-09 23:02:08 +01:00
ui_menu_draw(&tab_materials_draw_slots_menu, -1, -1);
2026-03-06 12:56:38 +01:00
}
2026-06-08 11:42:44 +02:00
if (g_ui->is_hovered) {
2026-03-06 12:56:38 +01:00
ui_tooltip_image(img_full, 0);
if (i < 9) {
i32 i1 = i + 1;
2026-06-08 11:31:49 +02:00
ui_tooltip(string("%s - (%s %d)", g_project->_->materials->buffer[i]->canvas->name, (char *)any_map_get(g_keymap, "select_material"), i1));
2026-03-06 12:56:38 +01:00
}
else {
2026-06-05 20:34:10 +02:00
ui_tooltip(g_project->_->materials->buffer[i]->canvas->name);
2026-03-06 12:56:38 +01:00
}
}
2026-04-05 16:41:00 +02:00
if (g_config->show_asset_names) {
2026-06-08 11:42:44 +02:00
g_ui->_x = uix;
g_ui->_y += slotw * 0.9;
2026-06-05 20:34:10 +02:00
ui_text(g_project->_->materials->buffer[i]->canvas->name, UI_ALIGN_CENTER, 0x00000000);
2026-06-08 11:42:44 +02:00
if (g_ui->is_hovered) {
2026-03-06 12:56:38 +01:00
if (i < 9) {
i32 i1 = i + 1;
2026-03-10 21:00:00 +01:00
ui_tooltip(
2026-06-08 11:31:49 +02:00
string("%s - (%s %d)", g_project->_->materials->buffer[i]->canvas->name, (char *)any_map_get(g_keymap, "select_material"), i1));
2026-03-06 12:56:38 +01:00
}
else {
2026-06-05 20:34:10 +02:00
ui_tooltip(g_project->_->materials->buffer[i]->canvas->name);
2026-03-06 12:56:38 +01:00
}
}
2026-06-08 11:42:44 +02:00
g_ui->_y -= slotw * 0.9;
2026-06-05 20:34:10 +02:00
if (i == g_project->_->materials->length - 1) {
2026-06-08 11:42:44 +02:00
g_ui->_y += j == num - 1 ? imgw : imgw + UI_ELEMENT_H() + UI_ELEMENT_OFFSET();
2026-03-06 12:56:38 +01:00
}
}
}
2026-06-08 11:42:44 +02:00
g_ui->_y += mini ? 0 : 6;
2026-03-06 12:56:38 +01:00
}
2026-06-05 20:34:10 +02:00
if (base_drag_material != NULL && tab_materials_drag_pos == g_project->_->materials->length) {
2026-06-08 11:42:44 +02:00
g_ui->_x = uix;
g_ui->_y = uiy;
2026-06-08 15:35:04 +02:00
ui_fill(imgw_val + 1, -2, 2, imgw_val + 4, g_theme->HIGHLIGHT_COL);
2026-04-21 07:59:19 +02:00
}
if (!drag_pos_set) {
tab_materials_drag_pos = -1;
}
2026-06-08 11:42:44 +02:00
bool in_focus = g_ui->input_x > g_ui->_window_x && g_ui->input_x < g_ui->_window_x + g_ui->_window_w && g_ui->input_y > g_ui->_window_y &&
g_ui->input_y < g_ui->_window_y + g_ui->_window_h;
if (in_focus && g_ui->is_delete_down && g_project->_->materials->length > 1) {
g_ui->is_delete_down = false;
2026-04-05 16:41:00 +02:00
tab_materials_delete_material(g_context->material);
2026-03-06 12:56:38 +01:00
}
2026-06-08 11:42:44 +02:00
if (in_focus && g_ui->is_ctrl_down && g_ui->is_key_pressed && g_ui->key_code == KEY_CODE_D) {
2026-06-05 20:34:10 +02:00
_tab_materials_draw_slots = array_index_of(g_project->_->materials, g_context->material);
2026-04-18 14:14:54 +02:00
sys_notify_on_next_frame(&tab_materials_draw_slots_duplicate, NULL);
}
2026-04-15 22:34:47 +02:00
if (in_focus) {
2026-06-05 20:34:10 +02:00
i32 i = array_index_of(g_project->_->materials, g_context->material);
2026-06-08 11:42:44 +02:00
if (g_ui->is_key_pressed && g_ui->key_code == KEY_CODE_UP) {
2026-04-15 22:34:47 +02:00
if (i > 0) {
context_select_material(i - 1);
}
}
2026-06-08 11:42:44 +02:00
if (g_ui->is_key_pressed && g_ui->key_code == KEY_CODE_DOWN) {
2026-06-05 20:34:10 +02:00
if (i < g_project->_->materials->length - 1) {
2026-04-15 22:34:47 +02:00
context_select_material(i + 1);
}
}
}
2026-03-06 12:56:38 +01:00
}
2026-03-10 21:00:00 +01:00
void tab_materials_button_new_on_next_frame(void *_) {
2026-06-05 20:34:10 +02:00
g_context->material = slot_material_create(g_project->_->materials->buffer[0]->data, NULL);
any_array_push(g_project->_->materials, g_context->material);
2026-03-06 12:56:38 +01:00
tab_materials_update_material();
2026-03-09 23:02:08 +01:00
history_new_material();
2026-03-06 12:56:38 +01:00
}
2026-03-07 21:12:59 +01:00
void tab_materials_button_new(char *text) {
2026-03-06 12:56:38 +01:00
if (ui_icon_button(text, ICON_PLUS, UI_ALIGN_CENTER)) {
2026-03-09 23:02:08 +01:00
sys_notify_on_next_frame(&tab_materials_button_new_on_next_frame, NULL);
2026-03-06 12:56:38 +01:00
}
}
2026-04-04 21:38:20 +02:00
void tab_materials_draw_mini(ui_handle_t *htab) {
ui_set_hovered_tab_name(tr("Materials"));
ui_begin_sticky();
ui_separator(5, true);
tab_materials_button_nodes();
tab_materials_button_new("");
ui_end_sticky();
ui_separator(3, false);
tab_materials_draw_slots(true);
2026-03-06 12:56:38 +01:00
}
2026-04-04 21:38:20 +02:00
void tab_materials_draw_full(ui_handle_t *htab) {
if (ui_tab(htab, tr("Materials"), false, -1, false)) {
ui_begin_sticky();
f32_array_t *row = f32_array_create_from_raw(
(f32[]){
-70,
-70,
-70,
},
3);
ui_row(row);
tab_materials_button_new(tr("New"));
if (ui_icon_button(tr("Import"), ICON_IMPORT, UI_ALIGN_CENTER)) {
project_import_material();
2026-03-06 12:56:38 +01:00
}
2026-04-04 21:38:20 +02:00
tab_materials_button_nodes();
ui_end_sticky();
ui_separator(3, false);
tab_materials_draw_slots(false);
2026-03-06 12:56:38 +01:00
}
}
2026-04-04 21:38:20 +02:00
void tab_materials_draw(ui_handle_t *htab) {
2026-06-08 11:42:44 +02:00
bool mini = g_ui->_window_w <= ui_sidebar_w_mini;
2026-04-04 21:38:20 +02:00
mini ? tab_materials_draw_mini(htab) : tab_materials_draw_full(htab);
}
2026-04-21 07:59:19 +02:00
void tab_materials_accept_material_drop(slot_material_t *material) {
if (tab_materials_drag_pos == -1) {
return;
}
2026-06-05 20:34:10 +02:00
i32 mat_pos = array_index_of(g_project->_->materials, material);
2026-04-21 07:59:19 +02:00
if (mat_pos != -1 && math_abs(mat_pos - tab_materials_drag_pos) > 0) {
2026-06-05 20:34:10 +02:00
array_remove(g_project->_->materials, material);
2026-04-21 07:59:19 +02:00
i32 new_pos = tab_materials_drag_pos - mat_pos > 0 ? tab_materials_drag_pos - 1 : tab_materials_drag_pos;
2026-06-05 20:34:10 +02:00
array_insert(g_project->_->materials, new_pos, material);
2026-04-21 07:59:19 +02:00
}
}
2026-03-06 12:56:38 +01:00
void tab_materials_accept_swatch_drop(swatch_color_t *swatch) {
2026-06-05 20:34:10 +02:00
g_context->material = slot_material_create(g_project->_->materials->buffer[0]->data, NULL);
2026-04-05 16:41:00 +02:00
for (i32 i = 0; i < g_context->material->canvas->nodes->length; ++i) {
ui_node_t *node = g_context->material->canvas->nodes->buffer[i];
2026-03-06 12:56:38 +01:00
if (string_equals(node->type, "RGB")) {
2026-03-15 21:14:44 +01:00
node->outputs->buffer[0]->default_value = f32_array_create_xyzw(color_get_rb(swatch->base) / 255.0, color_get_gb(swatch->base) / 255.0,
color_get_bb(swatch->base) / 255.0, color_get_ab(swatch->base) / 255.0);
2026-03-06 12:56:38 +01:00
}
else if (string_equals(node->type, "OUTPUT_MATERIAL_PBR")) {
node->inputs->buffer[1]->default_value->buffer[0] = swatch->opacity;
node->inputs->buffer[2]->default_value->buffer[0] = swatch->occlusion;
node->inputs->buffer[3]->default_value->buffer[0] = swatch->roughness;
node->inputs->buffer[4]->default_value->buffer[0] = swatch->metallic;
node->inputs->buffer[7]->default_value->buffer[0] = swatch->height;
}
}
2026-06-05 20:34:10 +02:00
any_array_push(g_project->_->materials, g_context->material);
2026-03-06 12:56:38 +01:00
tab_materials_update_material();
history_new_material();
}