mirror of
https://github.com/yshui/picom.git
synced 2024-11-25 14:06:08 -05:00
tools/animgen: support more sophisticated preset parameters
Support multiple choice parameters in additional to plain old numbers. With this we are now able to change the direction of sliding, yippee! Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
dd208ff366
commit
756589d4ce
5 changed files with 1033 additions and 378 deletions
|
@ -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]),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
504
tools/animgen.c
504
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 <libconfig.h>\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);
|
||||
|
|
Loading…
Reference in a new issue