Files
armorpaint/paint/sources/brush_nodes/input_node.c
T

201 lines
6.1 KiB
C
Raw Normal View History

2026-03-06 12:56:38 +01:00
2026-03-09 13:17:15 +01:00
#include "../global.h"
2026-04-05 16:09:00 +02:00
f32 input_node_start_x = 0.0;
f32 input_node_start_y = 0.0;
// Brush ruler
2026-04-06 14:52:30 +02:00
bool input_node_lock_begin = false;
bool input_node_lock_x = false;
bool input_node_lock_y = false;
f32 input_node_lock_start_x = 0.0;
f32 input_node_lock_start_y = 0.0;
bool input_node_registered = false;
vec4_t input_node_coords = (vec4_t){0.0, 0.0, 0.0, 1.0};
2026-04-05 16:09:00 +02:00
2026-06-01 16:54:42 +02:00
static void input_node_grid_snap() {
bool snap_shortcut = operator_shortcut(any_map_get(config_keymap, "grid_snap"), SHORTCUT_TYPE_DOWN);
bool in_2d = context_in_2d_view(VIEW_2D_TYPE_LAYER);
bool in_3d = context_in_3d_view();
if (!in_2d && !in_3d) {
2026-05-30 20:56:21 +02:00
return;
}
2026-06-01 16:54:42 +02:00
if (!snap_shortcut && !(g_config->view2d_grid_snap && in_2d)) {
2026-05-30 20:56:21 +02:00
return;
}
slot_layer_t *layer = g_context->layer;
gpu_texture_t *tex = layer->texpaint;
if (tex == NULL) {
return;
}
2026-06-01 16:54:42 +02:00
f32 wx;
f32 wy;
f32 ww;
f32 wh;
f32 pan_x;
f32 pan_y;
f32 pan_scale;
if (in_2d) {
i32 headerh = g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 1 ? ui_header_h * 2 : ui_header_h;
wh = iron_window_height() - g_config->layout->buffer[LAYOUT_SIZE_STATUS_H] + headerh;
if (!base_view3d_show) {
wh = base_h();
}
wx = ui_view2d_wx;
wy = ui_view2d_wy;
ww = ui_view2d_ww;
pan_x = ui_view2d_pan_x;
pan_y = ui_view2d_pan_y;
pan_scale = ui_view2d_pan_scale;
}
else {
wx = base_x();
wy = base_y();
ww = base_w();
wh = base_h();
pan_x = 0.0;
pan_y = 0.0;
pan_scale = 1.0;
}
f32 wm = fmin(ww, wh);
f32 tw = wm * 0.9 * pan_scale;
2026-05-30 20:56:21 +02:00
f32 th = tw * (tex->height / (float)tex->width);
2026-06-01 16:54:42 +02:00
f32 tx = wx + ww / 2.0 - tw / 2.0 + pan_x;
f32 ty = wy + wh / 2.0 - th / 2.0 + pan_y;
2026-05-30 20:56:21 +02:00
f32 sx = input_node_coords.x * base_w() + base_x();
f32 sy = input_node_coords.y * base_h() + base_y();
// Snap to nearest cell center
f32 u = (sx - tx) / tw;
f32 v = (sy - ty) / th;
i32 cell = g_config->view2d_grid_cell;
f32 px = (math_floor(u * tex->width / cell) + 0.5) * cell;
f32 py = (math_floor(v * tex->height / cell) + 0.5) * cell;
sx = tx + (px / tex->width) * tw;
sy = ty + (py / tex->height) * th;
input_node_coords.x = (sx - base_x()) / base_w();
input_node_coords.y = (sy - base_y()) / base_h();
}
2026-03-06 12:56:38 +01:00
void input_node_update(float_node_t *self) {
2026-04-05 16:41:00 +02:00
if (g_context->split_view) {
g_context->view_index = mouse_view_x() > base_w() / 2.0 ? 1 : 0;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:09:00 +02:00
bool decal_mask = context_is_decal_mask_paint();
2026-03-10 11:49:57 +01:00
char *ruler_paint = string("%s+%s", any_map_get(config_keymap, "brush_ruler"), any_map_get(config_keymap, "action_paint"));
2026-04-05 16:41:00 +02:00
bool lazy_paint = g_context->brush_lazy_radius > 0 && (operator_shortcut(any_map_get(config_keymap, "action_paint"), SHORTCUT_TYPE_DOWN) ||
2026-04-06 14:52:30 +02:00
operator_shortcut(ruler_paint, SHORTCUT_TYPE_DOWN) || decal_mask);
2026-03-06 12:56:38 +01:00
f32 paint_x = mouse_view_x() / (float)sys_w();
f32 paint_y = mouse_view_y() / (float)sys_h();
if (mouse_started("left")) {
input_node_start_x = mouse_view_x() / (float)sys_w();
input_node_start_y = mouse_view_y() / (float)sys_h();
}
if (pen_down("tip")) {
paint_x = pen_view_x() / (float)sys_w();
paint_y = pen_view_y() / (float)sys_h();
}
if (pen_started("tip")) {
input_node_start_x = pen_view_x() / (float)sys_w();
input_node_start_y = pen_view_y() / (float)sys_h();
}
2026-03-10 11:49:57 +01:00
if (operator_shortcut(ruler_paint, SHORTCUT_TYPE_DOWN)) {
2026-03-06 12:56:38 +01:00
if (input_node_lock_x) {
paint_x = input_node_start_x;
}
if (input_node_lock_y) {
paint_y = input_node_start_y;
}
}
2026-04-05 16:41:00 +02:00
if (g_context->brush_lazy_radius > 0) {
g_context->brush_lazy_x = paint_x;
g_context->brush_lazy_y = paint_y;
2026-03-06 12:56:38 +01:00
}
2026-05-14 10:14:11 +02:00
if (!lazy_paint || slot_layer_is_path(g_context->layer)) {
2026-03-06 12:56:38 +01:00
input_node_coords.x = paint_x;
input_node_coords.y = paint_y;
}
2026-04-05 16:41:00 +02:00
if (g_context->split_view) {
g_context->view_index = -1;
2026-03-06 12:56:38 +01:00
}
if (input_node_lock_begin) {
f32 dx = math_abs(input_node_lock_start_x - mouse_view_x());
f32 dy = math_abs(input_node_lock_start_y - mouse_view_y());
if (dx > 1 || dy > 1) {
input_node_lock_begin = false;
if (dx > dy) {
input_node_lock_y = true;
}
else {
input_node_lock_x = true;
}
}
}
if (keyboard_started(any_map_get(config_keymap, "brush_ruler"))) {
input_node_lock_start_x = mouse_view_x();
input_node_lock_start_y = mouse_view_y();
input_node_lock_begin = true;
}
else if (keyboard_released(any_map_get(config_keymap, "brush_ruler"))) {
input_node_lock_x = input_node_lock_y = input_node_lock_begin = false;
}
2026-05-14 10:14:11 +02:00
if (g_context->brush_lazy_radius > 0 && !slot_layer_is_path(g_context->layer)) {
2026-04-05 23:00:47 +02:00
vec4_t v1 = (vec4_t){g_context->brush_lazy_x * sys_w(), g_context->brush_lazy_y * sys_h(), 0.0, 1.0};
vec4_t v2 = (vec4_t){input_node_coords.x * sys_w(), input_node_coords.y * sys_h(), 0.0, 1.0};
2026-03-06 12:56:38 +01:00
f32 d = vec4_dist(v1, v2);
2026-04-05 16:41:00 +02:00
f32 r = g_context->brush_lazy_radius * 85;
2026-03-06 12:56:38 +01:00
if (d > r) {
2026-04-05 23:00:47 +02:00
vec4_t v3 = (vec4_t){0.0, 0.0, 0.0, 1.0};
2026-03-06 12:56:38 +01:00
v3 = vec4_sub(v2, v1);
v3 = vec4_norm(v3);
2026-04-05 16:41:00 +02:00
v3 = vec4_mult(v3, 1.0 - g_context->brush_lazy_step);
2026-03-06 12:56:38 +01:00
v3 = vec4_mult(v3, r);
v2 = vec4_add(v1, v3);
input_node_coords.x = v2.x / (float)sys_w();
input_node_coords.y = v2.y / (float)sys_h();
// Parse brush inputs once on next draw
2026-04-05 16:41:00 +02:00
g_context->painted = -1;
2026-03-06 12:56:38 +01:00
}
2026-04-05 16:41:00 +02:00
g_context->last_paint_x = -1;
g_context->last_paint_y = -1;
2026-03-06 12:56:38 +01:00
}
2026-06-01 16:54:42 +02:00
input_node_grid_snap();
2026-05-30 20:56:21 +02:00
2026-05-18 11:30:34 +02:00
brush_output_node_parse_inputs();
2026-03-06 12:56:38 +01:00
}
logic_node_value_t *input_node_get(input_node_t *self, i32 from) {
2026-04-05 16:41:00 +02:00
g_context->brush_lazy_radius = logic_node_input_get(self->base->inputs->buffer[0])->_f32;
g_context->brush_lazy_step = logic_node_input_get(self->base->inputs->buffer[1])->_f32;
2026-04-06 14:52:30 +02:00
logic_node_value_t *v = GC_ALLOC_INIT(logic_node_value_t, {._vec4 = input_node_coords});
2026-03-06 12:56:38 +01:00
return v;
}
2026-04-04 21:38:20 +02:00
input_node_t *input_node_create(ui_node_t *raw, f32_array_t *args) {
float_node_t *n = GC_ALLOC_INIT(float_node_t, {0});
n->base = logic_node_create(n);
n->base->get = input_node_get;
if (!input_node_registered) {
input_node_registered = true;
sys_notify_on_update(input_node_update, n);
}
return n;
}