Files
armorpaint/paint/sources/nodes_brush/math_node.c
T
2026-08-21 22:40:25 +02:00

215 lines
9.4 KiB
C

#include "../global.h"
typedef struct math_node {
struct logic_node *base;
char *operation;
bool use_clamp;
} math_node_t;
logic_node_value_t *math_node_get(math_node_t *self, i32 from) {
f32 v1 = logic_node_input_get(self->base->inputs->buffer[0])->_f32;
f32 v2 = logic_node_input_get(self->base->inputs->buffer[1])->_f32;
f32 f = 0.0;
char *op = self->operation;
if (string_equals(op, "Add")) {
f = v1 + v2;
}
else if (string_equals(op, "Multiply")) {
f = v1 * v2;
}
else if (string_equals(op, "Sine")) {
f = math_sin(v1);
}
else if (string_equals(op, "Cosine")) {
f = math_cos(v1);
}
else if (string_equals(op, "Max")) {
f = math_max(v1, v2);
}
else if (string_equals(op, "Min")) {
f = math_min(v1, v2);
}
else if (string_equals(op, "Absolute")) {
f = math_abs(v1);
}
else if (string_equals(op, "Subtract")) {
f = v1 - v2;
}
else if (string_equals(op, "Divide")) {
f = v1 / (float)(v2 == 0.0 ? 0.000001 : v2);
}
else if (string_equals(op, "Tangent")) {
f = math_tan(v1);
}
else if (string_equals(op, "Arcsine")) {
f = math_asin(v1);
}
else if (string_equals(op, "Arccosine")) {
f = math_acos(v1);
}
else if (string_equals(op, "Arctangent")) {
f = math_atan(v1);
}
else if (string_equals(op, "Arctan2")) {
f = math_atan2(v2, v1);
}
else if (string_equals(op, "Power")) {
f = math_pow(v1, v2);
}
else if (string_equals(op, "Logarithm")) {
f = math_log(v1);
}
else if (string_equals(op, "Round")) {
f = math_round(v1);
}
else if (string_equals(op, "Floor")) {
f = math_floor(v1);
}
else if (string_equals(op, "Ceil")) {
f = math_ceil(v1);
}
else if (string_equals(op, "Truncate")) {
f = math_floor(v1);
}
else if (string_equals(op, "Fraction")) {
f = v1 - math_floor(v1);
}
else if (string_equals(op, "Less Than")) {
f = v1 < v2 ? 1.0 : 0.0;
}
else if (string_equals(op, "Greater Than")) {
f = v1 > v2 ? 1.0 : 0.0;
}
else if (string_equals(op, "Modulo")) {
f = math_fmod(v1, v2);
}
else if (string_equals(op, "Snap")) {
f = math_floor(v1 / (float)v2) * v2;
}
else if (string_equals(op, "Square Root")) {
f = math_sqrt(v1);
}
else if (string_equals(op, "Inverse Square Root")) {
f = 1.0 / (float)math_sqrt(v1);
}
else if (string_equals(op, "Exponent")) {
f = math_exp(v1);
}
else if (string_equals(op, "Sign")) {
f = v1 > 0 ? 1.0 : (v1 < 0 ? -1.0 : 0);
}
else if (string_equals(op, "Ping-Pong")) {
f = (v2 != 0.0) ? v2 - math_abs(math_fmod(math_abs(v1), (2 * v2)) - v2) : 0.0;
}
else if (string_equals(op, "Hyperbolic Sine")) {
f = (math_exp(v1) - math_exp(-v1)) / 2.0;
}
else if (string_equals(op, "Hyperbolic Cosine")) {
f = (math_exp(v1) + math_exp(-v1)) / 2.0;
}
else if (string_equals(op, "Hyperbolic Tangent")) {
f = 1.0 - (2.0 / (float)(math_exp(2 * v1) + 1));
}
else if (string_equals(op, "To Radians")) {
f = v1 / 180.0 * math_pi();
}
else if (string_equals(op, "To Degrees")) {
f = v1 / (float)math_pi() * 180.0;
}
if (self->use_clamp) {
f = f < 0.0 ? 0.0 : (f > 1.0 ? 1.0 : f);
}
logic_node_value_t *v = TMP_ALLOC_INIT(logic_node_value_t, {._f32 = f});
return v;
}
void *math_node_create(ui_node_t *raw, f32_array_t *args) {
math_node_t *n = ALLOC_INIT(math_node_t, {0});
n->base = logic_node_create(n);
n->base->get = math_node_get;
return n;
}
void math_node_init() {
ui_node_t *math_node_def =
ALLOC_INIT(ui_node_t, {.id = 0,
.name = _tr("Math"),
.type = "math_node",
.x = 0,
.y = 0,
.color = 0xff4982a0,
.inputs = any_array_create_from_raw(
(void *[]){
ALLOC_INIT(ui_node_socket_t, {.id = 0,
.node_id = 0,
.name = _tr("Value"),
.type = "VALUE",
.color = 0xffa1a1a1,
.default_value = f32_array_create_x(0.5),
.min = 0.0,
.max = 1.0,
.precision = 100,
.display = 0}),
ALLOC_INIT(ui_node_socket_t, {.id = 0,
.node_id = 0,
.name = _tr("Value"),
.type = "VALUE",
.color = 0xffa1a1a1,
.default_value = f32_array_create_x(0.5),
.min = 0.0,
.max = 1.0,
.precision = 100,
.display = 0}),
},
2),
.outputs = any_array_create_from_raw(
(void *[]){
ALLOC_INIT(ui_node_socket_t, {.id = 0,
.node_id = 0,
.name = _tr("Value"),
.type = "VALUE",
.color = 0xffa1a1a1,
.default_value = f32_array_create_x(0.0),
.min = 0.0,
.max = 1.0,
.precision = 100,
.display = 0}),
},
1),
.buttons = any_array_create_from_raw(
(void *[]){
ALLOC_INIT(ui_node_button_t, {.name = _tr("operation"),
.type = "ENUM",
.output = 0,
.default_value = f32_array_create_x(0),
.data = u8_array_create_from_string(
"Add\nSubtract\nMultiply\nDivide\nPower\nLogarithm\nSquare Root\nInverse "
"Square Root\nAbsolute\nExponent\nMinimum\nMaximum\nLess Than\nGreater "
"Than\nSign\nRound\nFloor\nCeil\nTruncate\nFraction\nModulo\nSnap\nPing-"
"Pong\nSine\nCosine\nTangent\nArcsine\nArccosine\nArctangent\nArctan2\nHyperb"
"olic Sine\nHyperbolic Cosine\nHyperbolic Tangent\nTo Radians\nTo Degrees"),
.min = 0.0,
.max = 1.0,
.precision = 100,
.height = 0}),
ALLOC_INIT(ui_node_button_t, {.name = _tr("Clamp"),
.type = "BOOL",
.output = 0,
.default_value = f32_array_create_x(0),
.data = NULL,
.min = 0.0,
.max = 1.0,
.precision = 100,
.height = 0}),
},
2),
.width = 0,
.flags = 0});
any_array_push(nodes_brush_category0, math_node_def);
any_map_set(nodes_brush_creates, "math_node", math_node_create);
}