Files
armorpaint/paint/sources/ui_header.c
T

590 lines
22 KiB
C
Raw Normal View History

2026-03-09 13:17:15 +01:00
#include "global.h"
2026-04-05 16:09:00 +02:00
ui_handle_t *_ui_header_draw_tool_properties_h;
2026-03-06 12:56:38 +01:00
void ui_header_init() {
ui_header_handle->layout = UI_LAYOUT_HORIZONTAL;
}
void ui_header_render_ui() {
2026-04-05 16:41:00 +02:00
if (g_config->touch_ui) {
2026-03-06 12:56:38 +01:00
ui_header_h = ui_header_default_h + 4;
}
else {
ui_header_h = ui_header_default_h;
}
ui_header_h = math_floor(ui_header_h * UI_SCALE());
2026-04-05 16:41:00 +02:00
if (g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 0) {
2026-03-06 12:56:38 +01:00
return;
}
if (!base_view3d_show) {
return;
}
2026-04-05 16:41:00 +02:00
i32 nodesw = (ui_nodes_show || ui_view2d_show) ? g_config->layout->buffer[LAYOUT_SIZE_NODES_W] : 0;
i32 ww = iron_window_width() - ui_toolbar_w(true) - g_config->layout->buffer[LAYOUT_SIZE_SIDEBAR_W] - nodesw;
2026-03-06 12:56:38 +01:00
2026-03-31 12:39:41 +02:00
if (ui->is_typing) {
ui_header_handle->redraws = 2;
}
2026-03-06 12:56:38 +01:00
if (ui_window(ui_header_handle, base_x(), ui_header_h, ww, ui_header_h, false)) {
ui->_y += 2;
ui_header_draw_tool_properties();
}
}
2026-05-12 13:58:45 +02:00
void ui_header_particle_menu_draw() {
ui_handle_t *hlifetime = ui_handle(__ID__);
if (hlifetime->init) {
hlifetime->f = g_context->particle_lifetime;
}
g_context->particle_lifetime = ui_slider(hlifetime, tr("Lifetime"), 0.0, 10.0, true, 1.0, true, UI_ALIGN_RIGHT, true);
ui_handle_t *hspawn_distance = ui_handle(__ID__);
if (hspawn_distance->init) {
hspawn_distance->f = g_context->particle_spawn_distance;
}
g_context->particle_spawn_distance = ui_slider(hspawn_distance, tr("Distance"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
ui_handle_t *hmass = ui_handle(__ID__);
if (hmass->init) {
hmass->f = g_context->particle_mass;
}
g_context->particle_mass = ui_slider(hmass, tr("Mass"), 0.0, 3.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
ui_handle_t *hrandom = ui_handle(__ID__);
if (hrandom->init) {
hrandom->f = g_context->particle_random;
}
g_context->particle_random = ui_slider(hrandom, tr("Random"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
ui_handle_t *hfriction = ui_handle(__ID__);
if (hfriction->init) {
hfriction->f = g_context->particle_friction;
}
g_context->particle_friction = ui_slider(hfriction, tr("Friction"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
if (hfriction->changed) {
asim_set_friction(g_context->particle_friction);
}
ui_handle_t *hbounciness = ui_handle(__ID__);
if (hbounciness->init) {
hbounciness->f = g_context->particle_bounciness;
}
g_context->particle_bounciness = ui_slider(hbounciness, tr("Bounce"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
if (hbounciness->changed) {
asim_set_bounciness(g_context->particle_bounciness);
}
ui_handle_t *hgravx = ui_handle(__ID__);
if (hgravx->init) {
hgravx->f = g_context->particle_gravity_x;
}
g_context->particle_gravity_x = ui_slider(hgravx, tr("Gravity X"), -10.0, 10.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
if (hgravx->changed) {
asim_set_gravity(g_context->particle_gravity_x, g_context->particle_gravity_y, g_context->particle_gravity_z);
}
ui_handle_t *hgravy = ui_handle(__ID__);
if (hgravy->init) {
hgravy->f = g_context->particle_gravity_y;
}
g_context->particle_gravity_y = ui_slider(hgravy, tr("Gravity Y"), -10.0, 10.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
if (hgravy->changed) {
asim_set_gravity(g_context->particle_gravity_x, g_context->particle_gravity_y, g_context->particle_gravity_z);
}
ui_handle_t *hgravz = ui_handle(__ID__);
if (hgravz->init) {
hgravz->f = g_context->particle_gravity_z;
}
g_context->particle_gravity_z = ui_slider(hgravz, tr("Gravity Z"), -10.0, 10.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
if (hgravz->changed) {
asim_set_gravity(g_context->particle_gravity_x, g_context->particle_gravity_y, g_context->particle_gravity_z);
}
if (ui->changed || ui->is_typing) {
ui_menu_keep_open = true;
}
}
2026-03-10 21:00:00 +01:00
void ui_header_draw_tool_properties_layer_preview_dirty(void *_) {
2026-04-05 16:41:00 +02:00
g_context->layer_preview_dirty = true;
2026-03-09 23:02:08 +01:00
}
void ui_header_draw_tool_properties_color_picker_normal() {
ui_fill(0, 0, ui->_w / (float)UI_SCALE(), ui->ops->theme->ELEMENT_H * 9, ui->ops->theme->SEPARATOR_COL);
ui->changed = false;
ui_color_wheel(_ui_header_draw_tool_properties_h, false, -1, 10 * ui->ops->theme->ELEMENT_H * UI_SCALE(), false, NULL, NULL);
if (ui->changed) {
2026-04-05 16:41:00 +02:00
g_context->picked_color->normal = _ui_header_draw_tool_properties_h->color;
2026-04-21 10:52:27 +02:00
ui_header_handle->redraws = 2;
ui_menu_keep_open = true;
2026-03-09 23:02:08 +01:00
}
}
void ui_header_draw_tool_properties_color_picker_base() {
ui_fill(0, 0, ui->_w / (float)UI_SCALE(), ui->ops->theme->ELEMENT_H * 9, ui->ops->theme->SEPARATOR_COL);
ui->changed = false;
ui_color_wheel(_ui_header_draw_tool_properties_h, false, -1, 10 * ui->ops->theme->ELEMENT_H * UI_SCALE(), false, NULL, NULL);
if (ui->changed) {
2026-04-05 16:41:00 +02:00
g_context->picked_color->base = _ui_header_draw_tool_properties_h->color;
2026-04-21 10:52:27 +02:00
ui_header_handle->redraws = 2;
ui_menu_keep_open = true;
2026-03-09 23:02:08 +01:00
}
}
void ui_header_draw_tool_properties_to_mask(slot_layer_t *m) {
_gpu_begin(m->texpaint, NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
gpu_set_pipeline(pipes_colorid_to_mask);
render_target_t *rt = any_map_get(render_path_render_targets, "texpaint_colorid");
gpu_set_texture(pipes_texpaint_colorid, rt->_image);
2026-04-05 16:41:00 +02:00
gpu_set_texture(pipes_tex_colorid, project_get_image(project_assets->buffer[g_context->colorid_handle->i]));
2026-03-09 23:02:08 +01:00
gpu_set_vertex_buffer(const_data_screen_aligned_vb);
gpu_set_index_buffer(const_data_screen_aligned_ib);
gpu_draw();
gpu_end();
2026-04-05 16:41:00 +02:00
g_context->colorid_picked = false;
2026-04-21 10:52:27 +02:00
ui_toolbar_handle->redraws = 1;
ui_header_handle->redraws = 1;
2026-04-05 16:41:00 +02:00
g_context->layer_preview_dirty = true;
2026-03-09 23:02:08 +01:00
layers_update_fill_layers();
}
void ui_header_draw_tool_properties_import(char *path) {
import_asset_run(path, -1.0, -1.0, true, false, NULL);
2026-04-05 16:41:00 +02:00
g_context->colorid_handle->i = project_asset_names->length - 1;
2026-03-09 23:02:08 +01:00
for (i32 i = 0; i < project_assets->length; ++i) {
asset_t *a = project_assets->buffer[i];
// Already imported
if (string_equals(a->file, path)) {
2026-04-05 16:41:00 +02:00
g_context->colorid_handle->i = array_index_of(project_assets, a);
2026-03-09 23:02:08 +01:00
}
}
2026-04-21 10:52:27 +02:00
g_context->ddirty = 2;
g_context->colorid_picked = false;
2026-03-09 23:02:08 +01:00
ui_toolbar_handle->redraws = 1;
ui_base_hwnds->buffer[2]->redraws = 2;
}
2026-03-06 12:56:38 +01:00
void ui_header_draw_tool_properties() {
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_COLORID) {
2026-03-15 11:37:45 +01:00
ui_text(tr("Picked Color"), UI_ALIGN_LEFT, 0x00000000);
2026-04-05 16:41:00 +02:00
if (g_context->colorid_picked) {
2026-03-06 12:56:38 +01:00
render_target_t *rt = any_map_get(render_path_render_targets, "texpaint_colorid");
ui_image(rt->_image, 0xffffffff, 64);
}
2026-04-05 16:41:00 +02:00
ui->enabled = g_context->colorid_picked;
2026-04-18 14:44:33 +02:00
if (ui_icon_button(tr("Clear"), ICON_ERASE, UI_ALIGN_CENTER)) {
2026-04-21 10:52:27 +02:00
g_context->colorid_picked = false;
ui_toolbar_handle->redraws = 1;
2026-03-06 12:56:38 +01:00
}
ui->enabled = true;
2026-03-15 11:37:45 +01:00
ui_text(tr("Color ID Map"), UI_ALIGN_LEFT, 0x00000000);
2026-03-06 12:56:38 +01:00
if (project_asset_names->length > 0) {
2026-04-05 16:41:00 +02:00
i32 cid = ui_combo(g_context->colorid_handle, base_combo_enum_texts("TEX_IMAGE"), tr("Color ID"), false, UI_ALIGN_LEFT, true);
if (g_context->colorid_handle == ui->combo_selected_handle) {
2026-03-31 18:16:37 +02:00
ui->combo_selected_images = base_combo_enum_images("TEX_IMAGE");
}
2026-04-05 16:41:00 +02:00
if (g_context->colorid_handle->changed) {
2026-04-21 10:52:27 +02:00
g_context->ddirty = 2;
g_context->colorid_picked = false;
ui_toolbar_handle->redraws = 1;
2026-03-06 12:56:38 +01:00
}
ui_image(project_get_image(project_assets->buffer[cid]), 0xffffffff, -1.0);
if (ui->is_hovered) {
ui_tooltip_image(project_get_image(project_assets->buffer[cid]), 256);
}
}
2026-04-18 14:44:33 +02:00
if (ui_icon_button(tr("Import"), ICON_FOLDER_OPEN, UI_ALIGN_CENTER)) {
2026-03-09 23:02:08 +01:00
ui_files_show(string_array_join(path_texture_formats(), ","), false, true, &ui_header_draw_tool_properties_import);
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
ui->enabled = g_context->colorid_picked;
2026-04-18 14:44:33 +02:00
if (ui_icon_button(tr("To Mask"), ICON_MASK, UI_ALIGN_CENTER)) {
2026-04-05 16:41:00 +02:00
if (slot_layer_is_mask(g_context->layer)) {
context_set_layer(g_context->layer->parent);
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
slot_layer_t *m = layers_new_mask(false, g_context->layer, -1);
2026-03-09 23:02:08 +01:00
sys_notify_on_next_frame(&ui_header_draw_tool_properties_to_mask, m);
2026-03-06 12:56:38 +01:00
history_new_white_mask();
}
ui->enabled = true;
2026-04-18 15:24:33 +02:00
2026-04-21 10:52:27 +02:00
ui_handle_t *h_viewport_mask = ui_handle(__ID__);
2026-04-18 15:24:33 +02:00
g_context->colorid_viewport_mask = ui_check(h_viewport_mask, tr("Viewport Mask"), "");
if (h_viewport_mask->changed) {
make_material_parse_mesh_material();
}
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
else if (g_context->tool == TOOL_TYPE_PICKER || g_context->tool == TOOL_TYPE_MATERIAL) {
2026-03-06 12:56:38 +01:00
ui_handle_t *h_color = ui_handle(__ID__);
2026-04-05 16:41:00 +02:00
h_color->color = g_context->picked_color->base;
2026-03-06 12:56:38 +01:00
h_color->color = color_set_ab(h_color->color, 255);
ui_state_t state = ui_text("", 0, h_color->color);
if (state == UI_STATE_STARTED) {
base_drag_off_x = -(mouse_x - ui->_x - ui->_window_x - 3);
base_drag_off_y = -(mouse_y - ui->_y - ui->_window_y + 1);
gc_unroot(base_drag_swatch);
2026-04-05 16:41:00 +02:00
base_drag_swatch = project_clone_swatch(g_context->picked_color);
2026-03-06 12:56:38 +01:00
gc_root(base_drag_swatch);
}
if (ui->is_hovered) {
2026-03-15 11:37:45 +01:00
ui_tooltip(tr("Drag and drop picked color to swatches, materials, layers or to the node editor"));
2026-03-06 12:56:38 +01:00
}
if (ui->is_hovered && ui->input_released) {
gc_unroot(_ui_header_draw_tool_properties_h);
_ui_header_draw_tool_properties_h = h_color;
gc_root(_ui_header_draw_tool_properties_h);
2026-03-09 23:02:08 +01:00
ui_menu_draw(&ui_header_draw_tool_properties_color_picker_base, -1, -1);
2026-03-06 12:56:38 +01:00
}
2026-04-18 14:44:33 +02:00
if (ui_icon_button(tr("Add Swatch"), ICON_PLUS, UI_ALIGN_CENTER)) {
2026-04-05 16:41:00 +02:00
swatch_color_t *new_swatch = project_clone_swatch(g_context->picked_color);
2026-03-06 12:56:38 +01:00
context_set_swatch(new_swatch);
2026-04-05 16:41:00 +02:00
any_array_push(g_project->swatches, new_swatch);
2026-03-06 12:56:38 +01:00
ui_base_hwnds->buffer[2]->redraws = 1;
}
if (ui->is_hovered) {
2026-03-15 11:37:45 +01:00
ui_tooltip(tr("Add picked color to swatches"));
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
if (g_config->workflow == WORKFLOW_PBR) {
2026-03-11 14:28:58 +01:00
i32 _w = ui->_w;
ui->_w /= 2;
ui_handle_t *h_normal = ui_handle(__ID__);
2026-04-05 16:41:00 +02:00
h_normal->color = g_context->picked_color->normal;
2026-03-11 14:28:58 +01:00
ui_text("", 0, h_normal->color);
if (ui->is_hovered && ui->input_released) {
gc_unroot(_ui_header_draw_tool_properties_h);
_ui_header_draw_tool_properties_h = h_normal;
gc_root(_ui_header_draw_tool_properties_h);
ui_menu_draw(&ui_header_draw_tool_properties_color_picker_normal, -1, -1);
}
2026-03-15 11:37:45 +01:00
ui_text(tr("Normal"), UI_ALIGN_LEFT, 0x00000000);
2026-03-11 14:28:58 +01:00
ui->_w = _w;
2026-03-06 12:56:38 +01:00
2026-04-21 10:52:27 +02:00
ui_handle_t *hocc = ui_handle(__ID__);
hocc->f = g_context->picked_color->occlusion;
2026-04-05 16:41:00 +02:00
g_context->picked_color->occlusion = ui_slider(hocc, tr("Occlusion"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
2026-04-21 10:52:27 +02:00
ui_handle_t *hrough = ui_handle(__ID__);
hrough->f = g_context->picked_color->roughness;
2026-04-05 16:41:00 +02:00
g_context->picked_color->roughness = ui_slider(hrough, tr("Roughness"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
2026-04-21 10:52:27 +02:00
ui_handle_t *hmet = ui_handle(__ID__);
hmet->f = g_context->picked_color->metallic;
2026-04-05 16:41:00 +02:00
g_context->picked_color->metallic = ui_slider(hmet, tr("Metallic"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
2026-04-21 10:52:27 +02:00
ui_handle_t *hheight = ui_handle(__ID__);
hheight->f = g_context->picked_color->height;
2026-04-05 16:41:00 +02:00
g_context->picked_color->height = ui_slider(hheight, tr("Height"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-11 14:28:58 +01:00
}
2026-03-06 12:56:38 +01:00
2026-04-21 10:52:27 +02:00
ui_handle_t *hopac = ui_handle(__ID__);
hopac->f = g_context->picked_color->opacity;
2026-04-05 16:41:00 +02:00
g_context->picked_color->opacity = ui_slider(hopac, tr("Opacity"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
2026-03-10 21:00:00 +01:00
ui_handle_t *h_select_mat = ui_handle(__ID__);
2026-03-06 12:56:38 +01:00
if (h_select_mat->init) {
2026-04-05 16:41:00 +02:00
h_select_mat->b = g_context->picker_select_material;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
g_context->picker_select_material = ui_check(h_select_mat, tr("Select Material"), "");
2026-03-06 12:56:38 +01:00
2026-03-31 18:47:10 +02:00
string_array_t *picker_mask_combo = any_array_create_from_raw(
2026-03-08 08:39:29 +01:00
(void *[]){
2026-03-15 11:37:45 +01:00
tr("None"),
tr("Material"),
2026-03-06 12:56:38 +01:00
},
2);
2026-04-05 16:41:00 +02:00
ui_combo(g_context->picker_mask_handle, picker_mask_combo, tr("Mask"), true, UI_ALIGN_LEFT, true);
if (g_context->picker_mask_handle->changed) {
2026-03-06 12:56:38 +01:00
make_material_parse_paint_material(true);
}
}
2026-04-05 16:41:00 +02:00
else if (g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_ERASER || g_context->tool == TOOL_TYPE_FILL ||
g_context->tool == TOOL_TYPE_DECAL || g_context->tool == TOOL_TYPE_TEXT || g_context->tool == TOOL_TYPE_CLONE ||
2026-05-14 11:24:04 +02:00
g_context->tool == TOOL_TYPE_BLUR || g_context->tool == TOOL_TYPE_PARTICLE) {
2026-03-06 12:56:38 +01:00
bool decal_mask = context_is_decal_mask();
2026-04-05 16:41:00 +02:00
if (g_context->tool != TOOL_TYPE_FILL) {
2026-03-06 12:56:38 +01:00
if (decal_mask) {
2026-04-05 16:41:00 +02:00
g_context->brush_decal_mask_radius =
ui_slider(g_context->brush_decal_mask_radius_handle, tr("Radius"), 0.01, 2.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
if (ui->is_hovered) {
any_map_t *vars = any_map_create();
any_map_set(vars, "brush_radius", any_map_get(config_keymap, "brush_radius"));
any_map_set(vars, "brush_radius_decrease", any_map_get(config_keymap, "brush_radius_decrease"));
any_map_set(vars, "brush_radius_increase", any_map_get(config_keymap, "brush_radius_increase"));
2026-04-05 16:09:00 +02:00
ui_tooltip(
vtr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} "
"and move mouse to the right or press {brush_radius_increase} to increase the radius",
vars));
2026-03-06 12:56:38 +01:00
}
}
else {
2026-05-07 13:24:49 +02:00
ui_handle_t *brush_radius_handle = ui_handle(__ID__);
2026-05-11 21:57:42 +02:00
brush_radius_handle->f = g_context->brush_radius;
g_context->brush_radius = ui_slider(brush_radius_handle, tr("Radius"), 0.01, 2.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
if (ui->is_hovered) {
any_map_t *vars = any_map_create();
any_map_set(vars, "brush_radius", any_map_get(config_keymap, "brush_radius"));
any_map_set(vars, "brush_radius_decrease", any_map_get(config_keymap, "brush_radius_decrease"));
any_map_set(vars, "brush_radius_increase", any_map_get(config_keymap, "brush_radius_increase"));
2026-04-05 16:09:00 +02:00
ui_tooltip(
vtr("Hold {brush_radius} and move mouse to the left or press {brush_radius_decrease} to decrease the radius\nHold {brush_radius} "
"and move mouse to the right or press {brush_radius_increase} to increase the radius",
vars));
2026-03-06 12:56:38 +01:00
}
}
}
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_DECAL || g_context->tool == TOOL_TYPE_TEXT) {
g_context->brush_scale_x = ui_slider(g_context->brush_scale_x_handle, tr("Scale X"), 0.01, 2.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_FILL || g_context->tool == TOOL_TYPE_DECAL ||
g_context->tool == TOOL_TYPE_TEXT) {
2026-03-06 12:56:38 +01:00
ui_handle_t *brush_scale_handle = ui_handle(__ID__);
if (brush_scale_handle->init) {
2026-04-05 16:41:00 +02:00
brush_scale_handle->f = g_context->brush_scale;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
g_context->brush_scale = ui_slider(brush_scale_handle, tr("UV Scale"), 0.01, 5.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
if (brush_scale_handle->changed) {
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_DECAL || g_context->tool == TOOL_TYPE_TEXT) {
2026-03-06 12:56:38 +01:00
gpu_texture_t *current = _draw_current;
draw_end();
util_render_make_decal_preview();
draw_begin(current, false, 0);
}
}
2026-04-05 16:41:00 +02:00
g_context->brush_angle = ui_slider(g_context->brush_angle_handle, tr("Angle"), 0.0, 360.0, true, 1, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
if (ui->is_hovered) {
any_map_t *vars = any_map_create();
any_map_set(vars, "brush_angle", any_map_get(config_keymap, "brush_angle"));
2026-03-15 11:37:45 +01:00
ui_tooltip(vtr(
2026-03-06 12:56:38 +01:00
"Hold {brush_angle} and move mouse to the left to decrease the angle\nHold {brush_angle} and move mouse to the right to increase the angle",
vars));
}
2026-04-05 16:41:00 +02:00
if (g_context->brush_angle_handle->changed) {
2026-03-06 12:56:38 +01:00
make_material_parse_paint_material(true);
}
}
2026-04-05 16:41:00 +02:00
g_context->brush_opacity = ui_slider(g_context->brush_opacity_handle, tr("Opacity"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
if (ui->is_hovered) {
any_map_t *vars = any_map_create();
any_map_set(vars, "brush_opacity", any_map_get(config_keymap, "brush_opacity"));
2026-03-15 11:37:45 +01:00
ui_tooltip(vtr("Hold {brush_opacity} and move mouse to the left to decrease the opacity\nHold {brush_opacity} and move mouse to the right to "
2026-04-05 16:09:00 +02:00
"increase the opacity",
vars));
2026-03-06 12:56:38 +01:00
}
2026-05-11 21:57:42 +02:00
if (g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_ERASER || g_context->tool == TOOL_TYPE_CLONE || decal_mask ||
g_context->tool == TOOL_TYPE_PARTICLE) {
2026-03-06 12:56:38 +01:00
ui_handle_t *h = ui_handle(__ID__);
if (h->init) {
2026-04-05 16:41:00 +02:00
h->f = g_context->brush_hardness;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
g_context->brush_hardness = ui_slider(h, tr("Hardness"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
if (g_context->tool != TOOL_TYPE_ERASER) {
2026-03-06 12:56:38 +01:00
ui_handle_t *brush_blending_handle = ui_handle(__ID__);
if (brush_blending_handle->init) {
2026-04-05 16:41:00 +02:00
brush_blending_handle->f = g_context->brush_blending;
2026-03-06 12:56:38 +01:00
}
2026-03-31 18:47:10 +02:00
string_array_t *brush_blending_combo = any_array_create_from_raw(
2026-03-08 08:39:29 +01:00
(void *[]){
2026-03-15 11:37:45 +01:00
tr("Mix"),
tr("Darken"),
tr("Multiply"),
tr("Burn"),
tr("Lighten"),
tr("Screen"),
tr("Dodge"),
tr("Add"),
tr("Overlay"),
tr("Soft Light"),
tr("Linear Light"),
tr("Difference"),
tr("Subtract"),
tr("Divide"),
tr("Hue"),
tr("Saturation"),
tr("Color"),
tr("Value"),
2026-03-06 12:56:38 +01:00
},
18);
2026-04-05 16:41:00 +02:00
g_context->brush_blending = ui_combo(brush_blending_handle, brush_blending_combo, tr("Blending"), false, UI_ALIGN_LEFT, true);
2026-03-06 12:56:38 +01:00
if (brush_blending_handle->changed) {
make_material_parse_paint_material(true);
}
}
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_BRUSH || g_context->tool == TOOL_TYPE_FILL) {
2026-04-05 16:09:00 +02:00
ui_handle_t *paint_handle = ui_handle(__ID__);
2026-03-31 18:47:10 +02:00
string_array_t *texcoord_combo = any_array_create_from_raw(
2026-03-08 08:39:29 +01:00
(void *[]){
2026-03-15 11:37:45 +01:00
tr("UV Map"),
tr("Triplanar"),
tr("Project"),
2026-03-06 12:56:38 +01:00
},
3);
2026-04-05 16:41:00 +02:00
g_context->brush_paint = ui_combo(paint_handle, texcoord_combo, tr("TexCoord"), false, UI_ALIGN_LEFT, true);
2026-03-06 12:56:38 +01:00
if (paint_handle->changed) {
make_material_parse_paint_material(true);
}
}
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_TEXT) {
2026-03-06 12:56:38 +01:00
ui_handle_t *h = ui_handle(__ID__);
2026-04-05 16:41:00 +02:00
h->text = string_copy(g_context->text_tool_text);
2026-03-06 12:56:38 +01:00
i32 w = ui->_w;
if (ui->text_selected_handle == h || ui->submit_text_handle == h) {
ui->_w *= 3;
}
2026-04-05 16:41:00 +02:00
g_context->text_tool_text = string_copy(ui_text_input(h, "", UI_ALIGN_LEFT, true, true));
2026-04-21 10:52:27 +02:00
ui->_w = w;
2026-03-06 12:56:38 +01:00
if (h->changed) {
gpu_texture_t *current = _draw_current;
draw_end();
util_render_make_text_preview();
util_render_make_decal_preview();
draw_begin(current, false, 0);
}
}
2026-05-11 20:26:08 +02:00
if (g_context->tool == TOOL_TYPE_PARTICLE) {
2026-05-12 13:58:45 +02:00
if (ui_button(tr("Particle"), UI_ALIGN_CENTER, "")) {
ui_menu_draw(&ui_header_particle_menu_draw, -1, -1);
2026-05-11 20:26:08 +02:00
}
}
2026-05-14 11:24:04 +02:00
if (g_context->tool == TOOL_TYPE_BLUR) {
string_array_t *blur_type_combo = any_array_create_from_raw(
(void *[]){
tr("Blur"),
tr("Smudge"),
},
2);
g_context->blur_type = ui_combo(g_context->blur_type_handle, blur_type_combo, tr("Blur Type"), false, UI_ALIGN_LEFT, true);
if (g_context->blur_type_handle->changed) {
make_material_parse_paint_material(true);
}
}
2026-04-05 16:41:00 +02:00
if (g_context->tool == TOOL_TYPE_FILL) {
2026-03-31 18:47:10 +02:00
string_array_t *fill_mode_combo = any_array_create_from_raw(
2026-03-08 08:39:29 +01:00
(void *[]){
2026-03-15 11:37:45 +01:00
tr("Object"),
tr("Face"),
tr("Angle"),
tr("UV Island"),
2026-03-06 12:56:38 +01:00
},
4);
2026-04-05 16:41:00 +02:00
ui_combo(g_context->fill_type_handle, fill_mode_combo, tr("Fill Mode"), false, UI_ALIGN_LEFT, true);
if (g_context->fill_type_handle->changed) {
if (g_context->fill_type_handle->i == FILL_TYPE_FACE) {
2026-03-06 12:56:38 +01:00
gpu_texture_t *current = _draw_current;
draw_end();
// cache_uv_map();
util_uv_cache_triangle_map();
draw_begin(current, false, 0);
// wireframe_handle.b = draw_wireframe = true;
}
make_material_parse_paint_material(true);
make_material_parse_mesh_material();
}
}
else {
i32 _w = ui->_w;
f32 sc = UI_SCALE();
2026-04-05 16:41:00 +02:00
bool touch_header = (g_config->touch_ui && g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 1);
2026-03-06 12:56:38 +01:00
if (touch_header) {
ui->_x -= 4 * sc;
}
2026-03-10 21:00:00 +01:00
ui->_w = math_floor((touch_header ? 54 : 60) * sc);
2026-03-06 12:56:38 +01:00
ui_handle_t *xray_handle = ui_handle(__ID__);
if (xray_handle->init) {
2026-04-05 16:41:00 +02:00
xray_handle->b = g_context->xray;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
g_context->xray = ui_check(xray_handle, tr("X-Ray"), "");
2026-03-06 12:56:38 +01:00
if (xray_handle->changed) {
make_material_parse_paint_material(true);
}
ui_handle_t *sym_x_handle = ui_handle(__ID__);
if (sym_x_handle->init) {
sym_x_handle->b = false;
}
ui_handle_t *sym_y_handle = ui_handle(__ID__);
if (sym_y_handle->init) {
sym_y_handle->b = false;
}
ui_handle_t *sym_z_handle = ui_handle(__ID__);
if (sym_z_handle->init) {
sym_z_handle->b = false;
}
2026-04-05 16:41:00 +02:00
if (g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 1) {
if (g_config->touch_ui) {
2026-04-21 10:52:27 +02:00
ui->_w = math_floor(19 * sc);
2026-04-05 16:41:00 +02:00
g_context->sym_x = ui_check(sym_x_handle, "", "");
2026-03-06 12:56:38 +01:00
ui->_x -= 4 * sc;
2026-04-05 16:41:00 +02:00
g_context->sym_y = ui_check(sym_y_handle, "", "");
2026-03-06 12:56:38 +01:00
ui->_x -= 4 * sc;
2026-04-05 16:41:00 +02:00
g_context->sym_z = ui_check(sym_z_handle, "", "");
2026-03-06 12:56:38 +01:00
ui->_x -= 4 * sc;
2026-03-10 21:00:00 +01:00
ui->_w = math_floor(40 * sc);
2026-03-15 11:37:45 +01:00
char *x = tr("X");
char *y = tr("Y");
char *z = tr("Z");
2026-03-10 21:00:00 +01:00
ui_text(string("%s%s%s", x, y, z), UI_ALIGN_LEFT, 0x00000000);
2026-03-06 12:56:38 +01:00
}
else {
ui->_w = math_floor(56 * sc);
2026-03-15 11:37:45 +01:00
ui_text(tr("Symmetry"), UI_ALIGN_LEFT, 0x00000000);
2026-04-21 10:52:27 +02:00
ui->_w = math_floor(25 * sc);
2026-04-05 16:41:00 +02:00
g_context->sym_x = ui_check(sym_x_handle, tr("X"), "");
g_context->sym_y = ui_check(sym_y_handle, tr("Y"), "");
g_context->sym_z = ui_check(sym_z_handle, tr("Z"), "");
2026-03-06 12:56:38 +01:00
}
ui->_w = _w;
}
else {
// Popup
2026-04-21 10:52:27 +02:00
ui->_w = _w;
2026-04-05 16:41:00 +02:00
g_context->sym_x = ui_check(sym_x_handle, string("%s %s", tr("Symmetry"), tr("X")), "");
g_context->sym_y = ui_check(sym_y_handle, string("%s %s", tr("Symmetry"), tr("Y")), "");
g_context->sym_z = ui_check(sym_z_handle, string("%s %s", tr("Symmetry"), tr("Z")), "");
2026-03-06 12:56:38 +01:00
}
if (sym_x_handle->changed || sym_y_handle->changed || sym_z_handle->changed) {
make_material_parse_paint_material(true);
}
}
}
2026-05-11 20:26:08 +02:00
2026-04-18 12:54:50 +02:00
if (g_context->tool == TOOL_TYPE_CURSOR) {
2026-03-06 12:56:38 +01:00
// if (!sim_running && ui_button("Play")) {
// sim_play();
2026-04-05 16:41:00 +02:00
// g_context.selected_object = scene_camera.base;
2026-03-06 12:56:38 +01:00
// }
// if (sim_running && ui_button("Stop")) {
// sim_stop();
// }
// let h_record: ui_handle_t = ui_handle(__ID__);
// sim_record = ui_check(h_record, tr("Record"));
}
}