From 2d5dc40c190a1e889eb4d313b812a77a49a8f650 Mon Sep 17 00:00:00 2001 From: Vftdan Date: Mon, 19 Aug 2024 12:00:30 +0200 Subject: [PATCH] Add "scale" node type --- Makefile | 2 +- nodes/scale.c | 111 +++++++++++++++++++++++++++++++++++++++++ quadtap-both-click.cfg | 29 ++++++++++- 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 nodes/scale.c diff --git a/Makefile b/Makefile index ccd6710..a4f7588 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS)) LDLIBS += $(shell pkg-config --libs $(DEPS)) INTERP ?= MAIN = main -OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o nodes/router.o nodes/modifiers.o nodes/modify_predicate.o nodes/uinput.o nodes/assign.o nodes/differentiate.o +OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o nodes/router.o nodes/modifiers.o nodes/modify_predicate.o nodes/uinput.o nodes/assign.o nodes/differentiate.o nodes/scale.o all: $(MAIN) diff --git a/nodes/scale.c b/nodes/scale.c new file mode 100644 index 0000000..46352ee --- /dev/null +++ b/nodes/scale.c @@ -0,0 +1,111 @@ +#include "../graph.h" +#include "../module_registry.h" + +typedef struct { + GraphNode as_GraphNode; + int64_t numerator; + int64_t denominator; + int64_t center; + int64_t defect; + bool amortize_rounding_error; +} ScaleGraphNode; + +static bool +handle_event(EventPositionBase * self, EventNode * event) +{ + ScaleGraphNode *node = DOWNCAST(ScaleGraphNode, GraphNode, DOWNCAST(GraphNode, EventPositionBase, self)); + size_t count = node->as_GraphNode.outputs.length; + if (!count) { + event_destroy(event); + return true; + } + + int64_t value = event->data.payload; + value -= node->center; + value *= node->numerator; + if (node->amortize_rounding_error) { + value += node->defect; + } + if (node->denominator) { + uint64_t undivided = value; + value /= node->denominator; + node->defect = undivided - value * node->denominator; + } + value += node->center; + event->data.payload = value; + + if (count > 1) { + count = event_replicate(event, count - 1) + 1; + } + for (size_t i = 0; i < count; ++i) { + event->position = &node->as_GraphNode.outputs.elements[i]->as_EventPositionBase; + event = event->next; + } + return true; +} + +static GraphNode * +create(GraphNodeSpecification * spec, GraphNodeConfig * config, InitializationEnvironment * env) +{ + (void) config; + (void) env; + ScaleGraphNode * node = T_ALLOC(1, ScaleGraphNode); + if (!node) { + return NULL; + } + + int64_t + numerator = 1, + denominator = 1, + center = 0; + bool amortize_rounding_error = false; + if (config->options) { + numerator = env_resolve_constant_or(env, config_setting_get_member(config->options, "numerator"), numerator); + denominator = env_resolve_constant_or(env, config_setting_get_member(config->options, "denominator"), denominator); + center = env_resolve_constant_or(env, config_setting_get_member(config->options, "center"), center); + amortize_rounding_error = env_resolve_constant(env, config_setting_get_member(config->options, "amortize_rounding_error")) != 0; + } + + *node = (ScaleGraphNode) { + .as_GraphNode = { + .as_EventPositionBase = { + .handle_event = &handle_event, + .waiting_new_event = false, + }, + .specification = spec, + .inputs = EMPTY_GRAPH_CHANNEL_LIST, + .outputs = EMPTY_GRAPH_CHANNEL_LIST, + }, + .numerator = numerator, + .denominator = denominator, + .center = center, + .amortize_rounding_error = amortize_rounding_error, + .defect = 0, + }; + return &node->as_GraphNode; +} + +static void destroy +(GraphNodeSpecification * self, GraphNode * target) +{ + (void) self; + free(target); +} + +GraphNodeSpecification nodespec_scale = (GraphNodeSpecification) { + .create = &create, + .destroy = &destroy, + .register_io = NULL, + .name = "scale", + .documentation = "Multiplies event payload by a constant fraction\nAccepts events on any connector\nSends events on all connectors" + "\nOption 'numerator' (optional): an integer to multiply by" + "\nOption 'denominator' (optional): an integer to divide by" + "\nOption 'center' (optional): an integer to scale around" + "\nOption 'amortize_rounding_error' (optional): whether to adjust the new event value by the rounding error of the previous event value" + , +}; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_scale); +} diff --git a/quadtap-both-click.cfg b/quadtap-both-click.cfg index 2030392..77a265a 100644 --- a/quadtap-both-click.cfg +++ b/quadtap-both-click.cfg @@ -1,3 +1,8 @@ +constants = { + sensitivity_num = 2; + sensitivity_denom = 5; +}; + enums = { namespaces: ["clickpad"]; }; @@ -195,6 +200,22 @@ nodes = { predicates = ["quadtap_held"]; }; }; + sensitivity_x = { + type = "scale"; + options = { + numerator = "sensitivity_num"; + denominator = "sensitivity_denom"; + amortize_rounding_error = "true"; + }; + }; + sensitivity_y = { + type = "scale"; + options = { + numerator = "sensitivity_num"; + denominator = "sensitivity_denom"; + amortize_rounding_error = "true"; + }; + }; }; channels = ({ @@ -226,9 +247,15 @@ channels = ({ to: ("differentiate_y", 0); }, { from: ("differentiate_x", 0); - to: ("while_quadtap_held", 0); + to: ("sensitivity_x", 0); }, { from: ("differentiate_y", 0); + to: ("sensitivity_y", 0); +}, { + from: ("sensitivity_x", 0); + to: ("while_quadtap_held", 0); +}, { + from: ("sensitivity_y", 0); to: ("while_quadtap_held", 1); }, { from: ("while_quadtap_held", 0);