diff --git a/data/animation_presets.conf b/data/animation_presets.conf index 4d8e17ad..f1ff06c8 100644 --- a/data/animation_presets.conf +++ b/data/animation_presets.conf @@ -19,18 +19,13 @@ disappear = { shadow-scale-y = "scale-y"; shadow-offset-x = "offset-x"; shadow-offset-y = "offset-y"; - # This section defines placeholders used in this script - # Each entry is a tuple of two numbers. The first one is - # the id of the placeholder (e.g. 0 for placeholder0), the - # second number is the default value, if it is not specified - # by the user. - # - # Currently up to 10 placeholders are supported, if more is - # needed, tools/animgen.c needs to be updated to include more. - placeholders = { - scale = (1, 0.95); - duration = (0, 0.2); + + # See comments in tools/animgen.c for syntax + *knobs = { + scale = 0.95; + duration = 0.2; }; + *placeholders = ((0, "duration"),(1, "scale")); }; appear = { @@ -54,70 +49,117 @@ appear = { shadow-scale-y = "scale-y"; shadow-offset-x = "offset-x"; shadow-offset-y = "offset-y"; - placeholders = { - scale = (1, 0.95); - duration = (0, 0.2); + *knobs = { + scale = 0.95; + duration = 0.2; }; + *placeholders = ((0, "duration"),(1, "scale")); }; slide-out = { - offset-x = { + v-timing = { curve = "cubic-bezier(0.21, 0.02, 0.76, 0.36)"; start = 0; duration = "placeholder0"; - end = "-window-width"; + end = "window-width * placeholder1 + window-height * placeholder2"; }; + offset-x = "v-timing * placeholder3"; + offset-y = "v-timing * (1 - placeholder3)"; shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; crop-x = "window-x"; + crop-y = "window-y"; + crop-width = "window-width"; + crop-height = "window-height"; opacity = 1; blur-opacity = "opacity"; shadow-opacity = "opacity"; - placeholders = { - duration = (0, 0.2); + *knobs = { + duration = 0.2; + direction = (2, ["up", "down", "left", "right"]); }; + *placeholders = ( + (0, "duration"), + (1, "direction", [0, 0, -1, 1]), + (2, "direction", [-1, 1, 0, 0]), + (3, "direction", [0, 0, 1, 1]), + ); }; slide-in = { - offset-x = { + v-timing = { curve = "cubic-bezier(0.24, 0.64, 0.79, 0.98)"; - start = "-window-width"; + start = "window-width * placeholder1 + window-height * placeholder2"; duration = "placeholder0"; end = 0; }; + offset-x = "v-timing * placeholder3"; + offset-y = "v-timing * (1 - placeholder3)"; shadow-offset-x = "offset-x"; + shadow-offset-y = "offset-y"; crop-x = "window-x"; - placeholders = { - duration = (0, 0.2); + crop-y = "window-y"; + crop-width = "window-width"; + crop-height = "window-height"; + *knobs = { + duration = 0.2; + direction = (2, ["up", "down", "left", "right"]); }; + *placeholders = ( + (0, "duration"), + (1, "direction", [0, 0, -1, 1]), + (2, "direction", [-1, 1, 0, 0]), + (3, "direction", [0, 0, 1, 1]), + ); }; fly-out = { - offset-y = { + v-timing = { curve = "cubic-bezier(0.05, 0, 0.69, -0.05)"; duration = "placeholder0"; start = 0; - end = "- window-height - window-y"; + end = "(window-height + window-y) * placeholder2 + (window-width + window-x) * placeholder1"; }; + offset-x = "v-timing * placeholder3"; + offset-y = "v-timing * (1 - placeholder3)"; + shadow-offset-x = "offset-x"; shadow-offset-y = "offset-y"; opacity = 1; shadow-opacity = 1; blur-opacity = 1; - placeholders = { - duration = (0, 0.25); + *knobs = { + duration = 0.2; + direction = (0, ["up", "down", "left", "right"]); }; + *placeholders = ( + (0, "duration"), + (1, "direction", [0, 0, -1, 1]), + (2, "direction", [-1, 1, 0, 0]), + (3, "direction", [0, 0, 1, 1]), + ); }; fly-in = { - offset-y = { + v-timing = { curve = "cubic-bezier(0.17, 0.67, 0.68, 1.03)"; end = 0; duration = "placeholder0"; start = "- window-height - window-y"; }; + offset-x = "v-timing * placeholder3"; + offset-y = "v-timing * (1 - placeholder3)"; + shadow-offset-x = "offset-x"; shadow-offset-y = "offset-y"; opacity = 1; shadow-opacity = 1; blur-opacity = 1; - placeholders = { - duration = (0, 0.25); + *knobs = { + duration = 0.2; + direction = (0, ["up", "down", "left", "right"]); }; + *placeholders = ( + (0, "duration"), + (1, "direction", [0, 0, -1, 1]), + (2, "direction", [-1, 1, 0, 0]), + (3, "direction", [0, 0, 1, 1]), + ); } diff --git a/src/transition/curve.c b/src/transition/curve.c index 4b5dc2aa..28f12e6e 100644 --- a/src/transition/curve.c +++ b/src/transition/curve.c @@ -85,8 +85,8 @@ curve_sample_cubic_bezier(const struct curve_cubic_bezier *curve, double progres static char *curve_cubic_bezier_to_c(const struct curve_cubic_bezier *curve) { char *buf = NULL; casprintf(&buf, - "{.type = CURVE_CUBIC_BEZIER, .bezier = { .ax = %f, .bx = %f, " - ".cx = %f, .ay = %f, .by = %f, .cy = %f }},", + "{.type = CURVE_CUBIC_BEZIER, .bezier = { .ax = %a, .bx = %a, " + ".cx = %a, .ay = %a, .by = %a, .cy = %a }},", curve->ax, curve->bx, curve->cx, curve->ay, curve->by, curve->cy); return buf; } diff --git a/src/transition/generated/script_templates.c b/src/transition/generated/script_templates.c index 42a60446..25aff2c1 100644 --- a/src/transition/generated/script_templates.c +++ b/src/transition/generated/script_templates.c @@ -15,7 +15,7 @@ static struct script *script_template__disappear(int *output_slots) { {.type = INST_LOAD, .slot = 13}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 11}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 15}, {.type = INST_OP, .op = OP_DIV}, @@ -35,38 +35,38 @@ static struct script *script_template__disappear(int *output_slots) { {.type = INST_LOAD, .slot = 16}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 11}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 18}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.650000, - .bx = 1.020000, - .cx = 0.630000, - .ay = -0.020000, - .by = 0.960000, - .cy = 0.060000}}, + .bezier = {.ax = -0x1.4cccccccccccep-1, + .bx = 0x1.051eb851eb852p+0, + .cx = 0x1.428f5c28f5c2ap-1, + .ay = -0x1.47ae147ae148p-6, + .by = 0x1.eb851eb851eb8p-1, + .cy = 0x1.eb851eb851ebap-5}}, }, {.type = INST_OP, .op = OP_MUL}, {.type = INST_LOAD, .slot = 16}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 5}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_LOAD, .slot = 5}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_IMM, .imm = 2.000000}, + {.type = INST_IMM, .imm = 0x1p+1}, {.type = INST_OP, .op = OP_DIV}, {.type = INST_LOAD_CTX, .ctx = 16}, {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 3}, {.type = INST_LOAD, .slot = 5}, {.type = INST_STORE, .slot = 6}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_LOAD, .slot = 6}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_IMM, .imm = 2.000000}, + {.type = INST_IMM, .imm = 0x1p+1}, {.type = INST_OP, .op = OP_DIV}, {.type = INST_LOAD_CTX, .ctx = 24}, {.type = INST_OP, .op = OP_MUL}, @@ -87,23 +87,23 @@ static struct script *script_template__disappear(int *output_slots) { {.type = INST_STORE, .slot = 15}, {.type = INST_LOAD_CTX, .ctx = 40}, {.type = INST_STORE, .slot = 14}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_STORE_OVER_NAN, .slot = 16}, {.type = INST_LOAD_CTX, .ctx = 1073741824}, {.type = INST_STORE, .slot = 18}, {.type = INST_LOAD_CTX, .ctx = 1073741828}, {.type = INST_STORE, .slot = 17}, {.type = INST_BRANCH, .rel = -70}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_STORE, .slot = 12}, {.type = INST_LOAD, .slot = 15}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_MAX}, {.type = INST_STORE, .slot = 12}, {.type = INST_LOAD, .slot = 18}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_MAX}, @@ -215,13 +215,13 @@ static struct script *script_template__disappear(int *output_slots) { static bool win_script_preset__disappear(struct win_script *output, config_setting_t *setting) { output->script = script_template__disappear(output->output_indices); - double placeholder_duration = 0.200000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); - double placeholder_scale = 0.950000; - config_setting_lookup_float(setting, "scale", &placeholder_scale); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + double knob_scale = 0x1.e666666666666p-1; + config_setting_lookup_float(setting, "scale", &knob_scale); struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder_scale}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = knob_scale}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; @@ -233,7 +233,7 @@ static struct script *script_template__appear(int *output_slots) { {.type = INST_LOAD, .slot = 13}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 11}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 15}, {.type = INST_OP, .op = OP_DIV}, @@ -249,42 +249,42 @@ static struct script *script_template__appear(int *output_slots) { {.type = INST_STORE, .slot = 1}, {.type = INST_LOAD, .slot = 0}, {.type = INST_STORE, .slot = 2}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_LOAD, .slot = 16}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 11}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 17}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.650000, - .bx = 0.930000, - .cx = 0.720000, - .ay = -0.020000, - .by = -0.900000, - .cy = 1.920000}}, + .bezier = {.ax = -0x1.4cccccccccccep-1, + .bx = 0x1.dc28f5c28f5c3p-1, + .cx = 0x1.70a3d70a3d70bp-1, + .ay = -0x1.47ae147ae14p-6, + .by = -0x1.cccccccccccd4p-1, + .cy = 0x1.eb851eb851ebap+0}}, }, {.type = INST_OP, .op = OP_MUL}, {.type = INST_LOAD, .slot = 16}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 5}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_LOAD, .slot = 5}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_IMM, .imm = 2.000000}, + {.type = INST_IMM, .imm = 0x1p+1}, {.type = INST_OP, .op = OP_DIV}, {.type = INST_LOAD_CTX, .ctx = 16}, {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 3}, {.type = INST_LOAD, .slot = 5}, {.type = INST_STORE, .slot = 6}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_LOAD, .slot = 6}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_IMM, .imm = 2.000000}, + {.type = INST_IMM, .imm = 0x1p+1}, {.type = INST_OP, .op = OP_DIV}, {.type = INST_LOAD_CTX, .ctx = 24}, {.type = INST_OP, .op = OP_MUL}, @@ -310,16 +310,16 @@ static struct script *script_template__appear(int *output_slots) { {.type = INST_LOAD_CTX, .ctx = 1073741824}, {.type = INST_STORE, .slot = 17}, {.type = INST_BRANCH, .rel = -68}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_STORE, .slot = 12}, {.type = INST_LOAD, .slot = 15}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_MAX}, {.type = INST_STORE, .slot = 12}, {.type = INST_LOAD, .slot = 17}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_MAX}, @@ -430,76 +430,99 @@ static struct script *script_template__appear(int *output_slots) { static bool win_script_preset__appear(struct win_script *output, config_setting_t *setting) { output->script = script_template__appear(output->output_indices); - double placeholder_duration = 0.200000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); - double placeholder_scale = 0.950000; - config_setting_lookup_float(setting, "scale", &placeholder_scale); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + double knob_scale = 0x1.e666666666666p-1; + config_setting_lookup_float(setting, "scale", &knob_scale); struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder_scale}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = knob_scale}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; } static struct script *script_template__slide_out(int *output_slots) { static const struct instruction instrs[] = { - {.type = INST_BRANCH_ONCE, .rel = 24}, - {.type = INST_LOAD, .slot = 9}, - {.type = INST_LOAD, .slot = 8}, + {.type = INST_BRANCH_ONCE, .rel = 42}, + {.type = INST_LOAD, .slot = 15}, + {.type = INST_LOAD, .slot = 14}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 6}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_LOAD, .slot = 12}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 10}, + {.type = INST_LOAD, .slot = 16}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.650000, - .bx = 1.020000, - .cx = 0.630000, - .ay = -0.020000, - .by = 0.960000, - .cy = 0.060000}}, + .bezier = {.ax = -0x1.4cccccccccccep-1, + .bx = 0x1.051eb851eb852p+0, + .cx = 0x1.428f5c28f5c2ap-1, + .ay = -0x1.47ae147ae148p-6, + .by = 0x1.eb851eb851eb8p-1, + .cy = 0x1.eb851eb851ebap-5}}, }, {.type = INST_OP, .op = OP_MUL}, - {.type = INST_LOAD, .slot = 8}, + {.type = INST_LOAD, .slot = 14}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 0}, {.type = INST_LOAD, .slot = 0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 1}, - {.type = INST_LOAD_CTX, .ctx = 0}, + {.type = INST_LOAD, .slot = 0}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_SUB}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 2}, - {.type = INST_LOAD, .slot = 3}, - {.type = INST_STORE, .slot = 4}, - {.type = INST_LOAD, .slot = 3}, - {.type = INST_STORE, .slot = 5}, - {.type = INST_BRANCH_ONCE, .rel = 12}, - {.type = INST_HALT}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_STORE_OVER_NAN, .slot = 8}, - {.type = INST_LOAD_CTX, .ctx = 1073741824}, - {.type = INST_STORE, .slot = 10}, - {.type = INST_LOAD_CTX, .ctx = 16}, - {.type = INST_OP, .op = OP_NEG}, - {.type = INST_STORE, .slot = 9}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_LOAD, .slot = 1}, {.type = INST_STORE, .slot = 3}, - {.type = INST_BRANCH, .rel = -32}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_LOAD, .slot = 2}, + {.type = INST_STORE, .slot = 4}, + {.type = INST_LOAD_CTX, .ctx = 0}, + {.type = INST_STORE, .slot = 5}, + {.type = INST_LOAD_CTX, .ctx = 8}, + {.type = INST_STORE, .slot = 6}, + {.type = INST_LOAD_CTX, .ctx = 16}, {.type = INST_STORE, .slot = 7}, - {.type = INST_LOAD, .slot = 10}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_LOAD_CTX, .ctx = 24}, + {.type = INST_STORE, .slot = 8}, + {.type = INST_LOAD, .slot = 9}, + {.type = INST_STORE, .slot = 10}, + {.type = INST_LOAD, .slot = 9}, + {.type = INST_STORE, .slot = 11}, + {.type = INST_BRANCH_ONCE, .rel = 17}, + {.type = INST_HALT}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE_OVER_NAN, .slot = 14}, + {.type = INST_LOAD_CTX, .ctx = 1073741824}, + {.type = INST_STORE, .slot = 16}, + {.type = INST_LOAD_CTX, .ctx = 16}, + {.type = INST_LOAD_CTX, .ctx = 1073741828}, + {.type = INST_OP, .op = OP_MUL}, + {.type = INST_LOAD_CTX, .ctx = 24}, + {.type = INST_LOAD_CTX, .ctx = 1073741832}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_OP, .op = OP_ADD}, - {.type = INST_LOAD, .slot = 7}, + {.type = INST_STORE, .slot = 15}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_STORE, .slot = 9}, + {.type = INST_BRANCH, .rel = -55}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE, .slot = 13}, + {.type = INST_LOAD, .slot = 16}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_OP, .op = OP_ADD}, + {.type = INST_LOAD, .slot = 13}, {.type = INST_OP, .op = OP_MAX}, - {.type = INST_STORE, .slot = 7}, + {.type = INST_STORE, .slot = 13}, {.type = INST_HALT}, }; struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs)); ret->len = ARR_SIZE(instrs); - ret->elapsed_slot = 6; - ret->n_slots = 11; + ret->elapsed_slot = 12; + ret->n_slots = 17; ret->stack_size = 3; ret->vars = NULL; ret->overrides = NULL; @@ -507,124 +530,217 @@ static struct script *script_template__slide_out(int *output_slots) { { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("offset-x"), .slot = 0, .index = 0}; + .name = strdup("v-timing"), .slot = 0, .index = 0}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-offset-x"), .slot = 1, .index = 1}; + .name = strdup("offset-x"), .slot = 1, .index = 1}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("crop-x"), .slot = 2, .index = 2}; + .name = strdup("offset-y"), .slot = 2, .index = 2}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("opacity"), .slot = 3, .index = 3}; + .name = strdup("shadow-offset-x"), .slot = 3, .index = 3}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("blur-opacity"), .slot = 4, .index = 4}; + .name = strdup("shadow-offset-y"), .slot = 4, .index = 4}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-opacity"), .slot = 5, .index = 5}; + .name = strdup("crop-x"), .slot = 5, .index = 5}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-y"), .slot = 6, .index = 6}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-width"), .slot = 7, .index = 7}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-height"), .slot = 8, .index = 8}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("opacity"), .slot = 9, .index = 9}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("blur-opacity"), .slot = 10, .index = 10}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("shadow-opacity"), .slot = 11, .index = 11}; HASH_ADD_STR(ret->vars, name, var); } { struct overridable_slot *override = malloc(sizeof(*override)); - *override = (struct overridable_slot){.name = strdup("offset-x"), .slot = 8}; + *override = (struct overridable_slot){.name = strdup("v-timing"), .slot = 14}; HASH_ADD_STR(ret->overrides, name, override); } - output_slots[0] = 0; - output_slots[1] = -1; - output_slots[2] = 1; - output_slots[3] = -1; - output_slots[4] = 3; - output_slots[5] = 4; - output_slots[6] = 5; + output_slots[0] = 1; + output_slots[1] = 2; + output_slots[2] = 3; + output_slots[3] = 4; + output_slots[4] = 9; + output_slots[5] = 10; + output_slots[6] = 11; output_slots[7] = -1; output_slots[8] = -1; output_slots[9] = -1; output_slots[10] = -1; - output_slots[11] = 2; - output_slots[12] = -1; - output_slots[13] = -1; - output_slots[14] = -1; + output_slots[11] = 5; + output_slots[12] = 6; + output_slots[13] = 7; + output_slots[14] = 8; return ret; } static bool win_script_preset__slide_out(struct win_script *output, config_setting_t *setting) { output->script = script_template__slide_out(output->output_indices); - double placeholder_duration = 0.200000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + const char *knob_direction = "left"; + config_setting_lookup_string(setting, "direction", &knob_direction); + double placeholder1_direction; + double placeholder2_direction; + double placeholder3_direction; + if (strcmp(knob_direction, "up") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = -0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "down") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = 0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "left") == 0) { + placeholder1_direction = -0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else if (strcmp(knob_direction, "right") == 0) { + placeholder1_direction = 0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else { + log_error("Invalid choice \"%s\" for option \"direction\". Line %d.", + knob_direction, + config_setting_source_line( + config_setting_get_member(setting, "direction"))); + log_error(" Valid ones are: \"up\", \"down\", \"left\", \"right\""); + script_free(output->script); + output->script = NULL; + return false; + } struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder1_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 8, .value = placeholder2_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 12, .value = placeholder3_direction}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; } static struct script *script_template__slide_in(int *output_slots) { static const struct instruction instrs[] = { - {.type = INST_BRANCH_ONCE, .rel = 20}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_LOAD, .slot = 5}, + {.type = INST_BRANCH_ONCE, .rel = 38}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_LOAD, .slot = 11}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 3}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_LOAD, .slot = 9}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 6}, + {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.650000, - .bx = 0.930000, - .cx = 0.720000, - .ay = -0.020000, - .by = -0.900000, - .cy = 1.920000}}, + .bezier = {.ax = -0x1.4cccccccccccep-1, + .bx = 0x1.dc28f5c28f5c3p-1, + .cx = 0x1.70a3d70a3d70bp-1, + .ay = -0x1.47ae147ae14p-6, + .by = -0x1.cccccccccccd4p-1, + .cy = 0x1.eb851eb851ebap+0}}, }, {.type = INST_OP, .op = OP_MUL}, - {.type = INST_LOAD, .slot = 5}, + {.type = INST_LOAD, .slot = 11}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 0}, {.type = INST_LOAD, .slot = 0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 1}, - {.type = INST_LOAD_CTX, .ctx = 0}, + {.type = INST_LOAD, .slot = 0}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_SUB}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 2}, - {.type = INST_BRANCH_ONCE, .rel = 8}, + {.type = INST_LOAD, .slot = 1}, + {.type = INST_STORE, .slot = 3}, + {.type = INST_LOAD, .slot = 2}, + {.type = INST_STORE, .slot = 4}, + {.type = INST_LOAD_CTX, .ctx = 0}, + {.type = INST_STORE, .slot = 5}, + {.type = INST_LOAD_CTX, .ctx = 8}, + {.type = INST_STORE, .slot = 6}, + {.type = INST_LOAD_CTX, .ctx = 16}, + {.type = INST_STORE, .slot = 7}, + {.type = INST_LOAD_CTX, .ctx = 24}, + {.type = INST_STORE, .slot = 8}, + {.type = INST_BRANCH_ONCE, .rel = 13}, {.type = INST_HALT}, {.type = INST_LOAD_CTX, .ctx = 16}, - {.type = INST_OP, .op = OP_NEG}, - {.type = INST_STORE_OVER_NAN, .slot = 5}, - {.type = INST_LOAD_CTX, .ctx = 1073741824}, - {.type = INST_STORE, .slot = 6}, - {.type = INST_BRANCH, .rel = -24}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_STORE, .slot = 4}, - {.type = INST_LOAD, .slot = 6}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_LOAD_CTX, .ctx = 1073741828}, + {.type = INST_OP, .op = OP_MUL}, + {.type = INST_LOAD_CTX, .ctx = 24}, + {.type = INST_LOAD_CTX, .ctx = 1073741832}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_OP, .op = OP_ADD}, - {.type = INST_LOAD, .slot = 4}, + {.type = INST_STORE_OVER_NAN, .slot = 11}, + {.type = INST_LOAD_CTX, .ctx = 1073741824}, + {.type = INST_STORE, .slot = 12}, + {.type = INST_BRANCH, .rel = -47}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE, .slot = 10}, + {.type = INST_LOAD, .slot = 12}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_OP, .op = OP_ADD}, + {.type = INST_LOAD, .slot = 10}, {.type = INST_OP, .op = OP_MAX}, - {.type = INST_STORE, .slot = 4}, + {.type = INST_STORE, .slot = 10}, {.type = INST_HALT}, }; struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs)); ret->len = ARR_SIZE(instrs); - ret->elapsed_slot = 3; - ret->n_slots = 7; + ret->elapsed_slot = 9; + ret->n_slots = 13; ret->stack_size = 3; ret->vars = NULL; ret->overrides = NULL; @@ -632,30 +748,66 @@ static struct script *script_template__slide_in(int *output_slots) { { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("offset-x"), .slot = 0, .index = 0}; + .name = strdup("v-timing"), .slot = 0, .index = 0}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-offset-x"), .slot = 1, .index = 1}; + .name = strdup("offset-x"), .slot = 1, .index = 1}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("crop-x"), .slot = 2, .index = 2}; + .name = strdup("offset-y"), .slot = 2, .index = 2}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("shadow-offset-x"), .slot = 3, .index = 3}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("shadow-offset-y"), .slot = 4, .index = 4}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-x"), .slot = 5, .index = 5}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-y"), .slot = 6, .index = 6}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-width"), .slot = 7, .index = 7}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("crop-height"), .slot = 8, .index = 8}; HASH_ADD_STR(ret->vars, name, var); } { struct overridable_slot *override = malloc(sizeof(*override)); - *override = (struct overridable_slot){.name = strdup("offset-x"), .slot = 5}; + *override = (struct overridable_slot){.name = strdup("v-timing"), .slot = 11}; HASH_ADD_STR(ret->overrides, name, override); } - output_slots[0] = 0; - output_slots[1] = -1; - output_slots[2] = 1; - output_slots[3] = -1; + output_slots[0] = 1; + output_slots[1] = 2; + output_slots[2] = 3; + output_slots[3] = 4; output_slots[4] = -1; output_slots[5] = -1; output_slots[6] = -1; @@ -663,82 +815,135 @@ static struct script *script_template__slide_in(int *output_slots) { output_slots[8] = -1; output_slots[9] = -1; output_slots[10] = -1; - output_slots[11] = 2; - output_slots[12] = -1; - output_slots[13] = -1; - output_slots[14] = -1; + output_slots[11] = 5; + output_slots[12] = 6; + output_slots[13] = 7; + output_slots[14] = 8; return ret; } static bool win_script_preset__slide_in(struct win_script *output, config_setting_t *setting) { output->script = script_template__slide_in(output->output_indices); - double placeholder_duration = 0.200000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + const char *knob_direction = "left"; + config_setting_lookup_string(setting, "direction", &knob_direction); + double placeholder1_direction; + double placeholder2_direction; + double placeholder3_direction; + if (strcmp(knob_direction, "up") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = -0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "down") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = 0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "left") == 0) { + placeholder1_direction = -0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else if (strcmp(knob_direction, "right") == 0) { + placeholder1_direction = 0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else { + log_error("Invalid choice \"%s\" for option \"direction\". Line %d.", + knob_direction, + config_setting_source_line( + config_setting_get_member(setting, "direction"))); + log_error(" Valid ones are: \"up\", \"down\", \"left\", \"right\""); + script_free(output->script); + output->script = NULL; + return false; + } struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder1_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 8, .value = placeholder2_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 12, .value = placeholder3_direction}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; } static struct script *script_template__fly_out(int *output_slots) { static const struct instruction instrs[] = { - {.type = INST_BRANCH_ONCE, .rel = 18}, + {.type = INST_BRANCH_ONCE, .rel = 30}, + {.type = INST_LOAD, .slot = 11}, + {.type = INST_LOAD, .slot = 10}, + {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 8}, - {.type = INST_LOAD, .slot = 7}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 5}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 9}, + {.type = INST_LOAD, .slot = 12}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.920000, - .bx = 1.770000, - .cx = 0.150000, - .ay = 1.150000, - .by = -0.150000, - .cy = 0.000000}}, + .bezier = {.ax = -0x1.d70a3d70a3d75p-1, + .bx = 0x1.c51eb851eb854p+0, + .cx = 0x1.3333333333334p-3, + .ay = 0x1.2666666666666p+0, + .by = -0x1.3333333333334p-3, + .cy = 0x0p+0}}, }, {.type = INST_OP, .op = OP_MUL}, - {.type = INST_LOAD, .slot = 7}, + {.type = INST_LOAD, .slot = 10}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 0}, {.type = INST_LOAD, .slot = 0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 1}, - {.type = INST_BRANCH_ONCE, .rel = 18}, - {.type = INST_HALT}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_STORE_OVER_NAN, .slot = 7}, - {.type = INST_LOAD_CTX, .ctx = 1073741824}, - {.type = INST_STORE, .slot = 9}, - {.type = INST_LOAD_CTX, .ctx = 24}, - {.type = INST_OP, .op = OP_NEG}, - {.type = INST_LOAD_CTX, .ctx = 8}, + {.type = INST_LOAD, .slot = 0}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_STORE, .slot = 8}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 2}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_LOAD, .slot = 1}, {.type = INST_STORE, .slot = 3}, - {.type = INST_IMM, .imm = 1.000000}, + {.type = INST_LOAD, .slot = 2}, {.type = INST_STORE, .slot = 4}, - {.type = INST_BRANCH, .rel = -32}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_STORE, .slot = 6}, - {.type = INST_LOAD, .slot = 9}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_BRANCH_ONCE, .rel = 25}, + {.type = INST_HALT}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE_OVER_NAN, .slot = 10}, + {.type = INST_LOAD_CTX, .ctx = 1073741824}, + {.type = INST_STORE, .slot = 12}, + {.type = INST_LOAD_CTX, .ctx = 24}, + {.type = INST_LOAD_CTX, .ctx = 8}, {.type = INST_OP, .op = OP_ADD}, - {.type = INST_LOAD, .slot = 6}, - {.type = INST_OP, .op = OP_MAX}, + {.type = INST_LOAD_CTX, .ctx = 1073741832}, + {.type = INST_OP, .op = OP_MUL}, + {.type = INST_LOAD_CTX, .ctx = 16}, + {.type = INST_LOAD_CTX, .ctx = 0}, + {.type = INST_OP, .op = OP_ADD}, + {.type = INST_LOAD_CTX, .ctx = 1073741828}, + {.type = INST_OP, .op = OP_MUL}, + {.type = INST_OP, .op = OP_ADD}, + {.type = INST_STORE, .slot = 11}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_STORE, .slot = 5}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_STORE, .slot = 6}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_STORE, .slot = 7}, + {.type = INST_BRANCH, .rel = -51}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE, .slot = 9}, + {.type = INST_LOAD, .slot = 12}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_OP, .op = OP_ADD}, + {.type = INST_LOAD, .slot = 9}, + {.type = INST_OP, .op = OP_MAX}, + {.type = INST_STORE, .slot = 9}, {.type = INST_HALT}, }; struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs)); ret->len = ARR_SIZE(instrs); - ret->elapsed_slot = 5; - ret->n_slots = 10; + ret->elapsed_slot = 8; + ret->n_slots = 13; ret->stack_size = 3; ret->vars = NULL; ret->overrides = NULL; @@ -746,45 +951,63 @@ static struct script *script_template__fly_out(int *output_slots) { { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("offset-y"), .slot = 0, .index = 0}; + .name = strdup("v-timing"), .slot = 0, .index = 0}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-offset-y"), .slot = 1, .index = 1}; + .name = strdup("offset-x"), .slot = 1, .index = 1}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("opacity"), .slot = 2, .index = 2}; + .name = strdup("offset-y"), .slot = 2, .index = 2}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-opacity"), .slot = 3, .index = 3}; + .name = strdup("shadow-offset-x"), .slot = 3, .index = 3}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("blur-opacity"), .slot = 4, .index = 4}; + .name = strdup("shadow-offset-y"), .slot = 4, .index = 4}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("opacity"), .slot = 5, .index = 5}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("shadow-opacity"), .slot = 6, .index = 6}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("blur-opacity"), .slot = 7, .index = 7}; HASH_ADD_STR(ret->vars, name, var); } { struct overridable_slot *override = malloc(sizeof(*override)); - *override = (struct overridable_slot){.name = strdup("offset-y"), .slot = 7}; + *override = (struct overridable_slot){.name = strdup("v-timing"), .slot = 10}; HASH_ADD_STR(ret->overrides, name, override); } - output_slots[0] = -1; - output_slots[1] = 0; - output_slots[2] = -1; - output_slots[3] = 1; - output_slots[4] = 2; - output_slots[5] = 4; - output_slots[6] = 3; + output_slots[0] = 1; + output_slots[1] = 2; + output_slots[2] = 3; + output_slots[3] = 4; + output_slots[4] = 5; + output_slots[5] = 7; + output_slots[6] = 6; output_slots[7] = -1; output_slots[8] = -1; output_slots[9] = -1; @@ -798,71 +1021,117 @@ static struct script *script_template__fly_out(int *output_slots) { static bool win_script_preset__fly_out(struct win_script *output, config_setting_t *setting) { output->script = script_template__fly_out(output->output_indices); - double placeholder_duration = 0.250000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + const char *knob_direction = "up"; + config_setting_lookup_string(setting, "direction", &knob_direction); + double placeholder1_direction; + double placeholder2_direction; + double placeholder3_direction; + if (strcmp(knob_direction, "up") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = -0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "down") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = 0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "left") == 0) { + placeholder1_direction = -0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else if (strcmp(knob_direction, "right") == 0) { + placeholder1_direction = 0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else { + log_error("Invalid choice \"%s\" for option \"direction\". Line %d.", + knob_direction, + config_setting_source_line( + config_setting_get_member(setting, "direction"))); + log_error(" Valid ones are: \"up\", \"down\", \"left\", \"right\""); + script_free(output->script); + output->script = NULL; + return false; + } struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder1_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 8, .value = placeholder2_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 12, .value = placeholder3_direction}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; } static struct script *script_template__fly_in(int *output_slots) { static const struct instruction instrs[] = { - {.type = INST_BRANCH_ONCE, .rel = 18}, - {.type = INST_IMM, .imm = 0.000000}, - {.type = INST_LOAD, .slot = 7}, - {.type = INST_OP, .op = OP_SUB}, - {.type = INST_LOAD, .slot = 5}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_BRANCH_ONCE, .rel = 30}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_LOAD, .slot = 10}, {.type = INST_OP, .op = OP_SUB}, {.type = INST_LOAD, .slot = 8}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_OP, .op = OP_SUB}, + {.type = INST_LOAD, .slot = 11}, {.type = INST_OP, .op = OP_DIV}, { .type = INST_CURVE, .curve = {.type = CURVE_CUBIC_BEZIER, - .bezier = {.ax = -0.530000, - .bx = 1.020000, - .cx = 0.510000, - .ay = -0.080000, - .by = -0.930000, - .cy = 2.010000}}, + .bezier = {.ax = -0x1.0f5c28f5c28f8p-1, + .bx = 0x1.051eb851eb853p+0, + .cx = 0x1.051eb851eb852p-1, + .ay = -0x1.47ae147ae146p-4, + .by = -0x1.dc28f5c28f5ccp-1, + .cy = 0x1.0147ae147ae16p+1}}, }, {.type = INST_OP, .op = OP_MUL}, - {.type = INST_LOAD, .slot = 7}, + {.type = INST_LOAD, .slot = 10}, {.type = INST_OP, .op = OP_ADD}, {.type = INST_STORE, .slot = 0}, {.type = INST_LOAD, .slot = 0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_MUL}, {.type = INST_STORE, .slot = 1}, + {.type = INST_LOAD, .slot = 0}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_LOAD_CTX, .ctx = 1073741836}, + {.type = INST_OP, .op = OP_SUB}, + {.type = INST_OP, .op = OP_MUL}, + {.type = INST_STORE, .slot = 2}, + {.type = INST_LOAD, .slot = 1}, + {.type = INST_STORE, .slot = 3}, + {.type = INST_LOAD, .slot = 2}, + {.type = INST_STORE, .slot = 4}, {.type = INST_BRANCH_ONCE, .rel = 16}, {.type = INST_HALT}, {.type = INST_LOAD_CTX, .ctx = 24}, {.type = INST_OP, .op = OP_NEG}, {.type = INST_LOAD_CTX, .ctx = 8}, {.type = INST_OP, .op = OP_SUB}, - {.type = INST_STORE_OVER_NAN, .slot = 7}, + {.type = INST_STORE_OVER_NAN, .slot = 10}, {.type = INST_LOAD_CTX, .ctx = 1073741824}, - {.type = INST_STORE, .slot = 8}, - {.type = INST_IMM, .imm = 1.000000}, - {.type = INST_STORE, .slot = 2}, - {.type = INST_IMM, .imm = 1.000000}, - {.type = INST_STORE, .slot = 3}, - {.type = INST_IMM, .imm = 1.000000}, - {.type = INST_STORE, .slot = 4}, - {.type = INST_BRANCH, .rel = -30}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_STORE, .slot = 11}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_STORE, .slot = 5}, + {.type = INST_IMM, .imm = 0x1p+0}, {.type = INST_STORE, .slot = 6}, - {.type = INST_LOAD, .slot = 8}, - {.type = INST_IMM, .imm = 0.000000}, + {.type = INST_IMM, .imm = 0x1p+0}, + {.type = INST_STORE, .slot = 7}, + {.type = INST_BRANCH, .rel = -42}, + {.type = INST_IMM, .imm = 0x0p+0}, + {.type = INST_STORE, .slot = 9}, + {.type = INST_LOAD, .slot = 11}, + {.type = INST_IMM, .imm = 0x0p+0}, {.type = INST_OP, .op = OP_ADD}, - {.type = INST_LOAD, .slot = 6}, + {.type = INST_LOAD, .slot = 9}, {.type = INST_OP, .op = OP_MAX}, - {.type = INST_STORE, .slot = 6}, + {.type = INST_STORE, .slot = 9}, {.type = INST_HALT}, }; struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs)); ret->len = ARR_SIZE(instrs); - ret->elapsed_slot = 5; - ret->n_slots = 9; + ret->elapsed_slot = 8; + ret->n_slots = 12; ret->stack_size = 3; ret->vars = NULL; ret->overrides = NULL; @@ -870,45 +1139,63 @@ static struct script *script_template__fly_in(int *output_slots) { { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("offset-y"), .slot = 0, .index = 0}; + .name = strdup("v-timing"), .slot = 0, .index = 0}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-offset-y"), .slot = 1, .index = 1}; + .name = strdup("offset-x"), .slot = 1, .index = 1}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("opacity"), .slot = 2, .index = 2}; + .name = strdup("offset-y"), .slot = 2, .index = 2}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("shadow-opacity"), .slot = 3, .index = 3}; + .name = strdup("shadow-offset-x"), .slot = 3, .index = 3}; HASH_ADD_STR(ret->vars, name, var); } { struct variable_allocation *var = malloc(sizeof(*var)); *var = (struct variable_allocation){ - .name = strdup("blur-opacity"), .slot = 4, .index = 4}; + .name = strdup("shadow-offset-y"), .slot = 4, .index = 4}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("opacity"), .slot = 5, .index = 5}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("shadow-opacity"), .slot = 6, .index = 6}; + HASH_ADD_STR(ret->vars, name, var); + } + { + struct variable_allocation *var = malloc(sizeof(*var)); + *var = (struct variable_allocation){ + .name = strdup("blur-opacity"), .slot = 7, .index = 7}; HASH_ADD_STR(ret->vars, name, var); } { struct overridable_slot *override = malloc(sizeof(*override)); - *override = (struct overridable_slot){.name = strdup("offset-y"), .slot = 7}; + *override = (struct overridable_slot){.name = strdup("v-timing"), .slot = 10}; HASH_ADD_STR(ret->overrides, name, override); } - output_slots[0] = -1; - output_slots[1] = 0; - output_slots[2] = -1; - output_slots[3] = 1; - output_slots[4] = 2; - output_slots[5] = 4; - output_slots[6] = 3; + output_slots[0] = 1; + output_slots[1] = 2; + output_slots[2] = 3; + output_slots[3] = 4; + output_slots[4] = 5; + output_slots[5] = 7; + output_slots[6] = 6; output_slots[7] = -1; output_slots[8] = -1; output_slots[9] = -1; @@ -922,10 +1209,44 @@ static struct script *script_template__fly_in(int *output_slots) { static bool win_script_preset__fly_in(struct win_script *output, config_setting_t *setting) { output->script = script_template__fly_in(output->output_indices); - double placeholder_duration = 0.250000; - config_setting_lookup_float(setting, "duration", &placeholder_duration); + double knob_duration = 0x1.999999999999ap-3; + config_setting_lookup_float(setting, "duration", &knob_duration); + const char *knob_direction = "up"; + config_setting_lookup_string(setting, "direction", &knob_direction); + double placeholder1_direction; + double placeholder2_direction; + double placeholder3_direction; + if (strcmp(knob_direction, "up") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = -0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "down") == 0) { + placeholder1_direction = 0x0p+0; + placeholder2_direction = 0x1p+0; + placeholder3_direction = 0x0p+0; + } else if (strcmp(knob_direction, "left") == 0) { + placeholder1_direction = -0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else if (strcmp(knob_direction, "right") == 0) { + placeholder1_direction = 0x1p+0; + placeholder2_direction = 0x0p+0; + placeholder3_direction = 0x1p+0; + } else { + log_error("Invalid choice \"%s\" for option \"direction\". Line %d.", + knob_direction, + config_setting_source_line( + config_setting_get_member(setting, "direction"))); + log_error(" Valid ones are: \"up\", \"down\", \"left\", \"right\""); + script_free(output->script); + output->script = NULL; + return false; + } struct script_specialization_context spec[] = { - {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = knob_duration}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder1_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 8, .value = placeholder2_direction}, + {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 12, .value = placeholder3_direction}, }; script_specialize(output->script, spec, ARR_SIZE(spec)); return true; diff --git a/src/transition/script.c b/src/transition/script.c index 29cd9f9a..3cf107ea 100644 --- a/src/transition/script.c +++ b/src/transition/script.c @@ -103,7 +103,7 @@ static void log_instruction_(enum log_level level, const char *func, unsigned in char *instruction_to_c(struct instruction i) { char *buf = NULL; switch (i.type) { - case INST_IMM: casprintf(&buf, "{.type = INST_IMM, .imm = %f},", i.imm); break; + case INST_IMM: casprintf(&buf, "{.type = INST_IMM, .imm = %a},", i.imm); break; case INST_BRANCH: casprintf(&buf, "{.type = INST_BRANCH, .rel = %d},", i.rel); break; diff --git a/tools/animgen.c b/tools/animgen.c index 911e2bde..59342d00 100644 --- a/tools/animgen.c +++ b/tools/animgen.c @@ -6,38 +6,50 @@ #include "utils/dynarr.h" #include "wm/win.h" -struct placeholder { - UT_hash_handle hh; - const char *name; - unsigned index; - double default_value; +enum knob_type { + KNOB_NUMBER, + KNOB_CHOICE, }; -// `config_setting_lookup_*` surprisingly doesn't support paths like -// `config_setting_lookup` does. e.g. indexing like `[0]` is not supported. So we define -// our own helper functions here. +struct knob { + UT_hash_handle hh; + const char *name; + enum knob_type type; -bool config_extra_lookup_int(config_setting_t *setting, const char *path, int *value) { - auto sub = config_setting_lookup(setting, path); - if (!sub) { + union { + struct { + double default_value; + } number; + struct { + char **choices; + unsigned n_choices; + unsigned default_choice; + }; + }; + bool emitted; +}; + +struct placeholder { + struct knob *source; + double *value_for_choices; +}; + +bool config_extra_get_float(config_setting_t *setting, double *value) { + if (config_setting_type(setting) != CONFIG_TYPE_FLOAT && + config_setting_type(setting) != CONFIG_TYPE_INT && + config_setting_type(setting) != CONFIG_TYPE_INT64) { return false; } - if (config_setting_type(sub) != CONFIG_TYPE_INT) { - return false; - } - *value = config_setting_get_int(sub); + *value = config_setting_get_float(setting); return true; } -bool config_extra_lookup_float(config_setting_t *setting, const char *path, double *value) { - auto sub = config_setting_lookup(setting, path); - if (!sub) { +bool config_extra_get_int(config_setting_t *setting, int *value) { + if (config_setting_type(setting) != CONFIG_TYPE_INT && + config_setting_type(setting) != CONFIG_TYPE_INT64) { return false; } - if (config_setting_type(sub) != CONFIG_TYPE_FLOAT) { - return false; - } - *value = config_setting_get_float(sub); + *value = config_setting_get_int(setting); return true; } @@ -51,6 +63,14 @@ char *sanitized_name(const char *name) { return ret; } +void free_charp(void *p) { + free(*(char **)p); +} + +#define scopedp(type) cleanup(free_##type##p) type * + +#define MAX_PLACEHOLDERS 10 + void codegen(const char *name, const char *body, const struct placeholder *placeholders) { auto ident = sanitized_name(name); printf("static struct script *script_template__%s(int *output_slots)\n%s\n", @@ -59,26 +79,77 @@ void codegen(const char *name, const char *body, const struct placeholder *place "config_setting_t *setting) {\n", ident); printf(" output->script = script_template__%s(output->output_indices);\n", ident); - for (size_t i = 0; i < 10; i++) { - if (placeholders[i].name) { - auto placeholder_ident = sanitized_name(placeholders[i].name); - printf(" double placeholder_%s = %f;\n", placeholder_ident, - placeholders[i].default_value); - printf(" config_setting_lookup_float(setting, \"%s\", " - "&placeholder_%s);\n", - placeholders[i].name, placeholder_ident); - free(placeholder_ident); + for (size_t i = 0; i < MAX_PLACEHOLDERS; i++) { + if (placeholders[i].source == NULL || placeholders[i].source->emitted) { + continue; } + + auto knob = placeholders[i].source; + scopedp(char) knob_ident = sanitized_name(knob->name); + knob->emitted = true; + if (knob->type == KNOB_NUMBER) { + printf(" double knob_%s = %a;\n", knob_ident, + knob->number.default_value); + printf(" config_setting_lookup_float(setting, \"%s\", " + "&knob_%s);\n", + knob->name, knob_ident); + continue; + } + printf(" const char *knob_%s = \"%s\";\n", knob_ident, + knob->choices[knob->default_choice]); + printf(" config_setting_lookup_string(setting, \"%s\", &knob_%s);\n", + knob->name, knob_ident); + for (unsigned j = 0; j < MAX_PLACEHOLDERS; j++) { + if (placeholders[j].source != knob) { + continue; + } + printf(" double placeholder%u_%s;\n", j, knob_ident); + } + for (unsigned j = 0; j < knob->n_choices; j++) { + printf(" if (strcmp(knob_%s, \"%s\") == 0) {\n", knob_ident, + knob->choices[j]); + for (unsigned k = 0; k < MAX_PLACEHOLDERS; k++) { + if (placeholders[k].source != knob) { + continue; + } + printf(" placeholder%u_%s = %a;\n", k, knob_ident, + placeholders[k].value_for_choices[j]); + } + printf(" } else "); + } + printf("{\n"); + printf(" log_error(\"Invalid choice \\\"%%s\\\" for " + "option \\\"%s\\\". Line %%d.\", knob_%s, " + "config_setting_source_line(config_setting_get_member(setting, " + "\"%s\")));\n", + knob->name, knob_ident, knob->name); + printf(" log_error(\" Valid ones are: "); + for (unsigned j = 0; j < knob->n_choices; j++) { + printf("%s\\\"%s\\\"", j ? ", " : "", knob->choices[j]); + } + printf("\");\n"); + printf(" script_free(output->script);\n"); + printf(" output->script = NULL;\n"); + printf(" return false;\n"); + printf(" }\n"); } printf(" struct script_specialization_context spec[] = {\n"); for (size_t i = 0; i < 10; i++) { - if (placeholders[i].name) { - auto placeholder_ident = sanitized_name(placeholders[i].name); - printf(" {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + %zu, " - ".value = placeholder_%s},\n", - i * 4, placeholder_ident); - free(placeholder_ident); + if (placeholders[i].source == NULL) { + continue; } + auto knob = placeholders[i].source; + auto knob_ident = sanitized_name(knob->name); + if (knob->type == KNOB_NUMBER) { + printf(" {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + %zu, " + ".value = knob_%s},\n", + i * 4, knob_ident); + } else { + printf(" {.offset = SCRIPT_CTX_PLACEHOLDER_BASE + %zu, " + ".value = placeholder%zu_%s},\n", + i * 4, i, knob_ident); + } + free(knob_ident); } printf(" };\n"); printf(" script_specialize(output->script, spec, ARR_SIZE(spec));\n"); @@ -87,6 +158,250 @@ void codegen(const char *name, const char *body, const struct placeholder *place free(ident); } +/// Syntax for defining knobs and placeholders: +/// +/// { +/// # other settings... +/// # .... +/// +/// __knobs = { +/// knob1 = 0.5; # knob1 is a number, default value 0.5 +/// +/// # knob2 is a choice, default choice is "default_choice" (index 2) +/// # ┌----- index of the default choice +/// # v +/// knob2 = (2, ["choice1", "choice2", "default_choice"]); +/// }; +/// __placeholders = ( +/// #┌----- index of the placeholder +/// #v +/// (1, "knob1"), # placeholder1 takes value from knob1 +/// +/// # placeholder2 takes value from knob2. Because knob2 is a choice, +/// # we need to provide a mapping from choice to value. +/// (2, "knob2", [1, 2, 0]); +/// ); +/// } + +static bool parse_knobs(const char *preset_name, config_setting_t *knob_settings, + config_setting_t *placeholder_settings, struct knob *knobs, + struct placeholder *placeholders) { + struct knob *knobs_by_name = NULL; + if (config_setting_length(knob_settings) > MAX_PLACEHOLDERS) { + fprintf(stderr, "Too many knobs in %s, max %d allowed\n", preset_name, + MAX_PLACEHOLDERS); + return false; + } + if (config_setting_length(placeholder_settings) > MAX_PLACEHOLDERS) { + fprintf(stderr, "Too many placeholders in %s, max %d allowed\n", + preset_name, MAX_PLACEHOLDERS); + return false; + } + unsigned n_knobs = 0; + for (unsigned i = 0; i < (unsigned)config_setting_length(knob_settings); i++) { + auto config = config_setting_get_elem(knob_settings, i); + const char *name = config_setting_name(config); + double default_value; + auto knob = &knobs[n_knobs++]; + knob->name = strdup(name); + if (config_extra_get_float(config, &default_value)) { + knob->type = KNOB_NUMBER; + knob->number.default_value = default_value; + HASH_ADD_STR(knobs_by_name, name, knob); + n_knobs++; + continue; + } + if (!config_setting_is_list(config) || config_setting_length(config) != 2) { + fprintf(stderr, + "Invalid placeholder %s in %s, line %d. It must be a " + "list of length 2.\n", + name, preset_name, config_setting_source_line(config)); + continue; + } + + int default_choice; + config_setting_t *choices = config_setting_get_elem(config, 1); + if (!config_extra_get_int(config_setting_get_elem(config, 0), &default_choice) || + choices == NULL || !config_setting_is_array(choices)) { + fprintf(stderr, + "Invalid placeholder %s in %s, line %d. Failed to get " + "elements.\n", + name, preset_name, config_setting_source_line(config)); + continue; + } + + auto n_choices = (unsigned)config_setting_length(choices); + if (default_choice < 0 || (unsigned)default_choice >= n_choices) { + fprintf(stderr, + "Invalid knob choice in %s, knob %s line %d. Default " + "choice out of range.\n", + preset_name, name, config_setting_source_line(config)); + continue; + } + knob->type = KNOB_CHOICE; + knob->n_choices = 0; + knob->choices = malloc(n_choices * sizeof(char *)); + knob->default_choice = (unsigned)default_choice; + + bool has_error = false; + for (unsigned j = 0; j < n_choices; j++) { + auto choice = + config_setting_get_string(config_setting_get_elem(choices, j)); + if (choice == NULL) { + fprintf(stderr, + "Invalid knob choice in %s, knob %s line %d. " + "Failed to get choice.\n", + preset_name, name, + config_setting_source_line(config)); + has_error = true; + break; + } + for (unsigned k = 0; k < j; k++) { + if (strcmp(knob->choices[k], choice) == 0) { + fprintf(stderr, + "Invalid knob choice in %s, knob %s line " + "%d. Duplicate choice %s.\n", + preset_name, name, + config_setting_source_line(config), choice); + has_error = true; + break; + } + } + if (has_error) { + break; + } + knob->choices[knob->n_choices++] = strdup(choice); + } + if (has_error) { + for (unsigned j = 0; j < knob->n_choices; j++) { + free(knob->choices[j]); + } + free(knob->choices); + free((void *)knob->name); + knob->choices = NULL; + knob->name = NULL; + continue; + } + HASH_ADD_STR(knobs_by_name, name, knob); + n_knobs++; + } + + for (unsigned i = 0; i < (unsigned)config_setting_length(placeholder_settings); i++) { + auto config = config_setting_get_elem(placeholder_settings, i); + if (!config_setting_is_list(config) || config_setting_length(config) < 2) { + fprintf(stderr, + "Invalid placeholder in preset %s, line %d. Must be a " + "non-empty list.\n", + preset_name, config_setting_source_line(config)); + continue; + } + + int index; + if (!config_extra_get_int(config_setting_get_elem(config, 0), &index)) { + fprintf(stderr, + "Invalid placeholder in preset %s, line %d. Index must " + "be an integer.\n", + preset_name, config_setting_source_line(config)); + continue; + } + + auto placeholder = &placeholders[index]; + if (placeholder->source) { + fprintf(stderr, + "Invalid placeholder in preset %s, line %d. Placeholder " + "with index %d already defined.\n", + preset_name, config_setting_source_line(config), index); + continue; + } + BUG_ON(placeholder->value_for_choices != NULL); + const char *source = + config_setting_get_string(config_setting_get_elem(config, 1)); + struct knob *knob; + HASH_FIND_STR(knobs_by_name, source, knob); + if (!knob) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line " + "%d. Source knob %s not found.\n", + index, preset_name, config_setting_source_line(config), + source); + continue; + } + + if (config_setting_length(config) == 2) { + if (knob->type != KNOB_NUMBER) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line " + "%d. Source knob %s is not a number.\n", + index, preset_name, + config_setting_source_line(config), source); + continue; + } + placeholder->source = knob; + } else if (config_setting_length(config) == 3) { + config_setting_t *value_for_choices = + config_setting_get_elem(config, 2); + if (value_for_choices == NULL || + !config_setting_is_array(value_for_choices)) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line " + "%d. Failed to get elements.\n", + index, preset_name, + config_setting_source_line(config)); + continue; + } + if (knob->type != KNOB_CHOICE) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line " + "%d. Source knob %s is not a choice.\n", + index, preset_name, + config_setting_source_line(config), source); + continue; + } + if (knob->n_choices != + (unsigned)config_setting_length(value_for_choices)) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line " + "%d. Number of choices doesn't match.\n", + index, preset_name, + config_setting_source_line(config)); + continue; + } + placeholder->value_for_choices = + malloc(sizeof(double) * knob->n_choices); + for (unsigned j = 0; j < knob->n_choices; j++) { + double value; + if (!config_extra_get_float( + config_setting_get_elem(value_for_choices, j), &value)) { + fprintf(stderr, + "Invalid placeholder%d definition in %s, " + "line %d. Failed to get value.\n", + index, preset_name, + config_setting_source_line(config)); + free(placeholder->value_for_choices); + placeholder->value_for_choices = NULL; + break; + } + placeholder->value_for_choices[j] = value; + } + if (placeholder->value_for_choices == NULL) { + continue; + } + placeholder->source = knob; + } else { + fprintf(stderr, + "Invalid placeholder%d definition in %s, line %d. " + "Excessive elements.\n", + index, preset_name, config_setting_source_line(config)); + continue; + } + } + struct knob *k, *nk; + HASH_ITER(hh, knobs_by_name, k, nk) { + HASH_DEL(knobs_by_name, k); + } + return true; +} + int main(int argc, const char **argv) { if (argc != 2) { return 1; @@ -100,14 +415,19 @@ int main(int argc, const char **argv) { config_init(&cfg); config_set_auto_convert(&cfg, 1); - config_read_file(&cfg, argv[1]); + if (!config_read_file(&cfg, argv[1])) { + fprintf(stderr, "Failed to read config file %s: %s\n", argv[1], + config_error_text(&cfg)); + config_destroy(&cfg); + return 1; + } auto settings = config_root_setting(&cfg); // win_script_context_info and 10 extra placeholder contexts, for // script_specialize() static const ptrdiff_t base = SCRIPT_CTX_PLACEHOLDER_BASE; - struct script_context_info context_info[ARR_SIZE(win_script_context_info) + 10] = { + struct script_context_info context_info[ARR_SIZE(win_script_context_info) + MAX_PLACEHOLDERS] = { {"placeholder0", base}, {"placeholder1", base + 4}, {"placeholder2", base + 8}, {"placeholder3", base + 12}, {"placeholder4", base + 16}, {"placeholder5", base + 20}, @@ -124,7 +444,8 @@ int main(int argc, const char **argv) { .output_info = NULL, }; printf("// This file is generated by tools/animgen.c from %s\n", argv[1]); - printf("// This file is included in git repository for convenience only.\n"); + printf("// This file is included in git repository for " + "convenience only.\n"); printf("// DO NOT EDIT THIS FILE!\n\n"); printf("#include \n"); @@ -136,57 +457,19 @@ int main(int argc, const char **argv) { for (unsigned i = 0; i < (unsigned)config_setting_length(settings); i++) { auto sub = config_setting_get_elem(settings, i); auto name = config_setting_name(sub); - struct placeholder *placeholders_by_name = NULL; - struct placeholder placeholders[10] = {}; + struct knob knobs[MAX_PLACEHOLDERS] = {}; + struct placeholder placeholders[MAX_PLACEHOLDERS] = {}; - auto placeholders_config = config_setting_get_member(sub, "placeholders"); - if (placeholders_config) { - for (unsigned j = 0; - j < (unsigned)config_setting_length(placeholders_config); j++) { - auto placeholder_config = - config_setting_get_elem(placeholders_config, j); - const char *placeholder_name = - config_setting_name(placeholder_config); - if (!config_setting_is_list(placeholder_config) || - config_setting_length(placeholder_config) != 2) { - fprintf(stderr, - "Invalid placeholder %s in %s, line %d. " - "It must be a list of 2 numbers.\n", - placeholder_name, name, - config_setting_source_line(placeholder_config)); - continue; - } - - int index; - double default_value; - if (!config_extra_lookup_int(placeholder_config, "[0]", &index) || - !config_extra_lookup_float(placeholder_config, "[1]", - &default_value)) { - fprintf(stderr, - "Invalid placeholder %s in %s, line %d. " - "Failed to get elements.\n", - placeholder_name, name, - config_setting_source_line(placeholder_config)); - continue; - } - if (index < 0 || (size_t)index >= ARR_SIZE(placeholders)) { - fprintf( - stderr, "Invalid placeholder index %d in %s, line %d\n", - index, name, - config_setting_source_line(placeholder_config)); - continue; - } - struct placeholder *placeholder = - malloc(sizeof(*placeholder)); - placeholder->name = strdup(placeholder_name); - placeholder->index = (unsigned)index; - placeholder->default_value = default_value; - HASH_ADD_STR(placeholders_by_name, name, placeholder); - - placeholders[index] = *placeholder; - } - config_setting_remove(sub, "placeholders"); - placeholders_config = NULL; + auto knob_settings = config_setting_get_member(sub, "*knobs"); + if (knob_settings) { + auto placeholder_settings = + config_setting_get_member(sub, "*placeholders"); + BUG_ON(!placeholder_settings); + parse_knobs(name, knob_settings, placeholder_settings, knobs, + placeholders); + config_setting_remove(sub, "*knobs"); + config_setting_remove(sub, "*placeholders"); + knob_settings = NULL; } char *err = NULL; @@ -201,16 +484,16 @@ int main(int argc, const char **argv) { if (script->instrs[j].type != INST_LOAD_CTX) { continue; } - if (script->instrs[j].ctx >= base) { - size_t index = ((size_t)script->instrs[j].ctx - base) / 4; - BUG_ON(index >= ARR_SIZE(placeholders)); - if (!placeholders[index].name) { - fprintf(stderr, - "Placeholder %zu used, but not defined\n", - index); - has_err = true; - break; - } + if (script->instrs[j].ctx < base) { + continue; + } + size_t index = (size_t)(script->instrs[j].ctx - base) / 4; + BUG_ON(index >= ARR_SIZE(knobs)); + if (placeholders[index].source == NULL) { + fprintf(stderr, "Placeholder %zu used, but not defined\n", + index); + has_err = true; + break; } } @@ -221,11 +504,19 @@ int main(int argc, const char **argv) { dynarr_push(presets, strdup(name)); } - struct placeholder *p, *np; - HASH_ITER(hh, placeholders_by_name, p, np) { - free((void *)p->name); - HASH_DEL(placeholders_by_name, p); - free(p); + for (size_t j = 0; j < MAX_PLACEHOLDERS; j++) { + if (placeholders[j].value_for_choices) { + free(placeholders[j].value_for_choices); + } + } + for (size_t j = 0; j < MAX_PLACEHOLDERS; j++) { + if (knobs[j].type == KNOB_CHOICE) { + for (unsigned k = 0; k < knobs[j].n_choices; k++) { + free(knobs[j].choices[k]); + } + free(knobs[j].choices); + } + free((void *)knobs[j].name); } script_free(script); } @@ -234,7 +525,8 @@ int main(int argc, const char **argv) { printf("struct {\n" " const char *name;\n" - " bool (*func)(struct win_script *output, config_setting_t *setting);\n" + " bool (*func)(struct win_script *output, " + "config_setting_t *setting);\n" "} win_script_presets[] = {\n"); dynarr_foreach(presets, p) { auto ident = sanitized_name(*p);