mirror of
https://github.com/yshui/picom.git
synced 2024-11-25 14:06:08 -05:00
transition: add support for animation presets
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
23f44d7295
commit
5a69a26602
9 changed files with 645 additions and 66 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -54,6 +54,7 @@ target
|
|||
.vscode
|
||||
*.conf
|
||||
!/tests/configs/*.conf
|
||||
!/data/*.conf
|
||||
perf.data
|
||||
perf.data.old
|
||||
core.*
|
||||
|
|
61
data/animation_presets.conf
Normal file
61
data/animation_presets.conf
Normal file
|
@ -0,0 +1,61 @@
|
|||
disappear = {
|
||||
opacity = {
|
||||
duration = "placeholder0";
|
||||
start = "window-raw-opacity-before";
|
||||
end = "window-raw-opacity";
|
||||
};
|
||||
blur-opacity = "opacity";
|
||||
shadow-opacity = "opacity";
|
||||
offset-x = "(1 - scale-x) / 2 * window-width";
|
||||
offset-y = "(1 - scale-y) / 2 * window-height";
|
||||
scale-x = {
|
||||
curve = "cubic-bezier(0.21, 0.02, 0.76, 0.36)";
|
||||
duration = "placeholder0";
|
||||
start = 1;
|
||||
end = "placeholder1";
|
||||
};
|
||||
scale-y = "scale-x";
|
||||
shadow-scale-x = "scale-x";
|
||||
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);
|
||||
};
|
||||
};
|
||||
|
||||
appear = {
|
||||
opacity = {
|
||||
duration = "placeholder0";
|
||||
start = "window-raw-opacity-before";
|
||||
end = "window-raw-opacity";
|
||||
};
|
||||
blur-opacity = "opacity";
|
||||
shadow-opacity = "opacity";
|
||||
offset-x = "(1 - scale-x) / 2 * window-width";
|
||||
offset-y = "(1 - scale-y) / 2 * window-height";
|
||||
scale-x = {
|
||||
curve = "cubic-bezier(0.24, 0.64, 0.79, 0.98)";
|
||||
duration = "placeholder0";
|
||||
start = "placeholder1";
|
||||
end = 1;
|
||||
};
|
||||
scale-y = "scale-x";
|
||||
shadow-scale-x = "scale-x";
|
||||
shadow-scale-y = "scale-y";
|
||||
shadow-offset-x = "offset-x";
|
||||
shadow-offset-y = "offset-y";
|
||||
placeholders = {
|
||||
scale = (1, 0.95);
|
||||
duration = (0, 0.2);
|
||||
};
|
||||
};
|
|
@ -16,6 +16,7 @@
|
|||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "transition/preset.h"
|
||||
#include "transition/script.h"
|
||||
#include "utils/dynarr.h"
|
||||
#include "utils/misc.h"
|
||||
|
@ -233,8 +234,14 @@ static enum animation_trigger parse_animation_trigger(const char *trigger) {
|
|||
return ANIMATION_TRIGGER_INVALID;
|
||||
}
|
||||
|
||||
static struct script *
|
||||
compile_win_script(config_setting_t *setting, int *output_indices, char **err) {
|
||||
/// Compile a script from `setting` into `result`, return false on failure.
|
||||
/// Only the `script` and `output_indices` fields of `result` will be modified.
|
||||
static bool
|
||||
compile_win_script(struct win_script *result, config_setting_t *setting, char **err) {
|
||||
if (config_setting_lookup(setting, "preset")) {
|
||||
return win_script_parse_preset(result, setting);
|
||||
}
|
||||
|
||||
struct script_output_info outputs[ARR_SIZE(win_script_outputs)];
|
||||
memcpy(outputs, win_script_outputs, sizeof(win_script_outputs));
|
||||
|
||||
|
@ -242,20 +249,19 @@ compile_win_script(config_setting_t *setting, int *output_indices, char **err) {
|
|||
.context_info = win_script_context_info,
|
||||
.output_info = outputs,
|
||||
};
|
||||
auto script = script_compile(setting, parse_config, err);
|
||||
if (script == NULL) {
|
||||
return script;
|
||||
result->script = script_compile(setting, parse_config, err);
|
||||
if (result->script == NULL) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < NUM_OF_WIN_SCRIPT_OUTPUTS; i++) {
|
||||
output_indices[i] = outputs[i].slot;
|
||||
result->output_indices[i] = outputs[i].slot;
|
||||
}
|
||||
return script;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_animation(struct win_script *animations, const enum animation_trigger *triggers,
|
||||
int number_of_triggers, struct script *script, const int *output_indices,
|
||||
uint64_t suppressions, unsigned line, bool is_generated) {
|
||||
int number_of_triggers, struct win_script animation, unsigned line) {
|
||||
bool needed = false;
|
||||
for (int i = 0; i < number_of_triggers; i++) {
|
||||
if (triggers[i] == ANIMATION_TRIGGER_INVALID) {
|
||||
|
@ -268,42 +274,39 @@ set_animation(struct win_script *animations, const enum animation_trigger *trigg
|
|||
animation_trigger_names[triggers[i]], line);
|
||||
continue;
|
||||
}
|
||||
memcpy(animations[triggers[i]].output_indices, output_indices,
|
||||
sizeof(int[NUM_OF_WIN_SCRIPT_OUTPUTS]));
|
||||
animations[triggers[i]].script = script;
|
||||
animations[triggers[i]].suppressions = suppressions;
|
||||
animations[triggers[i]].is_generated = is_generated;
|
||||
animations[triggers[i]] = animation;
|
||||
needed = true;
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
|
||||
static struct script *
|
||||
parse_animation_one(struct win_script *animations, config_setting_t *setting) {
|
||||
static bool parse_animation_one(struct win_script *animations,
|
||||
struct script ***all_scripts, config_setting_t *setting) {
|
||||
struct win_script result = {};
|
||||
auto triggers = config_setting_lookup(setting, "triggers");
|
||||
if (!triggers) {
|
||||
log_error("Missing triggers in animation script, at line %d",
|
||||
config_setting_source_line(setting));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (!config_setting_is_list(triggers) && !config_setting_is_array(triggers) &&
|
||||
config_setting_get_string(triggers) == NULL) {
|
||||
log_error("The \"triggers\" option must either be a string, a list, or "
|
||||
"an array, but is none of those at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
auto number_of_triggers =
|
||||
config_setting_get_string(triggers) == NULL ? config_setting_length(triggers) : 1;
|
||||
if (number_of_triggers > ANIMATION_TRIGGER_LAST) {
|
||||
log_error("Too many triggers in animation defined at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (number_of_triggers == 0) {
|
||||
log_error("Trigger list is empty in animation defined at line %d",
|
||||
config_setting_source_line(triggers));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
enum animation_trigger *trigger_types =
|
||||
alloca(sizeof(enum animation_trigger[number_of_triggers]));
|
||||
|
@ -322,7 +325,6 @@ parse_animation_one(struct win_script *animations, config_setting_t *setting) {
|
|||
// script parser shouldn't see this.
|
||||
config_setting_remove(setting, "triggers");
|
||||
|
||||
uint64_t suppressions = 0;
|
||||
auto suppressions_setting = config_setting_lookup(setting, "suppressions");
|
||||
if (suppressions_setting != NULL) {
|
||||
auto single_suppression = config_setting_get_string(suppressions_setting);
|
||||
|
@ -332,16 +334,16 @@ parse_animation_one(struct win_script *animations, config_setting_t *setting) {
|
|||
log_error("The \"suppressions\" option must either be a string, "
|
||||
"a list, or an array, but is none of those at line %d",
|
||||
config_setting_source_line(suppressions_setting));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (single_suppression != NULL) {
|
||||
auto suppression = parse_animation_trigger(single_suppression);
|
||||
if (suppression == ANIMATION_TRIGGER_INVALID) {
|
||||
log_error("Invalid suppression defined at line %d",
|
||||
config_setting_source_line(suppressions_setting));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
suppressions = 1 << suppression;
|
||||
result.suppressions = 1 << suppression;
|
||||
} else {
|
||||
auto len = config_setting_length(suppressions_setting);
|
||||
for (int i = 0; i < len; i++) {
|
||||
|
@ -353,39 +355,37 @@ parse_animation_one(struct win_script *animations, config_setting_t *setting) {
|
|||
"contain strings, but one of them is not at "
|
||||
"line %d",
|
||||
config_setting_source_line(suppressions_setting));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
auto suppression = parse_animation_trigger(suppression_str);
|
||||
if (suppression == ANIMATION_TRIGGER_INVALID) {
|
||||
log_error(
|
||||
"Invalid suppression defined at line %d",
|
||||
config_setting_source_line(suppressions_setting));
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
suppressions |= 1U << suppression;
|
||||
result.suppressions |= 1U << suppression;
|
||||
}
|
||||
}
|
||||
config_setting_remove(setting, "suppressions");
|
||||
}
|
||||
|
||||
int output_indices[NUM_OF_WIN_SCRIPT_OUTPUTS];
|
||||
char *err;
|
||||
auto script = compile_win_script(setting, output_indices, &err);
|
||||
if (!script) {
|
||||
if (!compile_win_script(&result, setting, &err)) {
|
||||
log_error("Failed to parse animation script at line %d: %s",
|
||||
config_setting_source_line(setting), err);
|
||||
free(err);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool needed = set_animation(animations, trigger_types, number_of_triggers, script,
|
||||
output_indices, suppressions,
|
||||
config_setting_source_line(setting), false);
|
||||
bool needed = set_animation(animations, trigger_types, number_of_triggers, result,
|
||||
config_setting_source_line(setting));
|
||||
if (!needed) {
|
||||
script_free(script);
|
||||
script = NULL;
|
||||
script_free(result.script);
|
||||
} else {
|
||||
dynarr_push(*all_scripts, result.script);
|
||||
}
|
||||
return script;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// `out_scripts`: all the script objects created, this is a dynarr.
|
||||
|
@ -394,10 +394,7 @@ static void parse_animations(struct win_script *animations, config_setting_t *se
|
|||
auto number_of_animations = (unsigned)config_setting_length(setting);
|
||||
for (unsigned i = 0; i < number_of_animations; i++) {
|
||||
auto sub = config_setting_get_elem(setting, (unsigned)i);
|
||||
auto script = parse_animation_one(animations, sub);
|
||||
if (script != NULL) {
|
||||
dynarr_push(*out_scripts, script);
|
||||
}
|
||||
parse_animation_one(animations, out_scripts, sub);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,7 +411,7 @@ static void parse_animations(struct win_script *animations, config_setting_t *se
|
|||
" start = %d; end = %d; " \
|
||||
"};"
|
||||
|
||||
static struct script *compile_win_script_from_string(const char *input, int *output_indices) {
|
||||
static bool compile_win_script_from_string(struct win_script *result, const char *input) {
|
||||
config_t tmp_config;
|
||||
config_setting_t *setting;
|
||||
config_init(&tmp_config);
|
||||
|
@ -424,11 +421,11 @@ static struct script *compile_win_script_from_string(const char *input, int *out
|
|||
|
||||
// Since we are compiling scripts we generated, it can't fail.
|
||||
char *err = NULL;
|
||||
auto script = compile_win_script(setting, output_indices, &err);
|
||||
bool succeeded = compile_win_script(result, setting, &err);
|
||||
config_destroy(&tmp_config);
|
||||
BUG_ON(err != NULL);
|
||||
|
||||
return script;
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void generate_fading_config(struct options *opt) {
|
||||
|
@ -441,7 +438,6 @@ void generate_fading_config(struct options *opt) {
|
|||
unsigned number_of_scripts = 0;
|
||||
int number_of_triggers = 0;
|
||||
|
||||
int output_indices[NUM_OF_WIN_SCRIPT_OUTPUTS];
|
||||
double duration = 1.0 / opt->fade_in_step * opt->fade_delta / 1000.0;
|
||||
if (!safe_isinf(duration) && !safe_isnan(duration) && duration > 0) {
|
||||
scoped_charp duration_str = NULL;
|
||||
|
@ -451,7 +447,8 @@ void generate_fading_config(struct options *opt) {
|
|||
asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration_str,
|
||||
duration_str, 0, 1);
|
||||
|
||||
auto fade_in1 = compile_win_script_from_string(str, output_indices);
|
||||
struct win_script fade_in1 = {.is_generated = true};
|
||||
BUG_ON(!compile_win_script_from_string(&fade_in1, str));
|
||||
if (opt->animations[ANIMATION_TRIGGER_OPEN].script == NULL &&
|
||||
!opt->no_fading_openclose) {
|
||||
trigger[number_of_triggers++] = ANIMATION_TRIGGER_OPEN;
|
||||
|
@ -459,25 +456,24 @@ void generate_fading_config(struct options *opt) {
|
|||
if (opt->animations[ANIMATION_TRIGGER_SHOW].script == NULL) {
|
||||
trigger[number_of_triggers++] = ANIMATION_TRIGGER_SHOW;
|
||||
}
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_in1,
|
||||
output_indices, 0, 0, true)) {
|
||||
scripts[number_of_scripts++] = fade_in1;
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_in1, 0)) {
|
||||
scripts[number_of_scripts++] = fade_in1.script;
|
||||
} else {
|
||||
script_free(fade_in1);
|
||||
script_free(fade_in1.script);
|
||||
}
|
||||
|
||||
// Fading for opacity change, for these, the blur opacity doesn't change.
|
||||
asnprintf(&str, &len, FADING_TEMPLATE_1, duration_str);
|
||||
auto fade_in2 = compile_win_script_from_string(str, output_indices);
|
||||
struct win_script fade_in2 = {.is_generated = true};
|
||||
BUG_ON(!compile_win_script_from_string(&fade_in2, str));
|
||||
number_of_triggers = 0;
|
||||
if (opt->animations[ANIMATION_TRIGGER_INCREASE_OPACITY].script == NULL) {
|
||||
trigger[number_of_triggers++] = ANIMATION_TRIGGER_INCREASE_OPACITY;
|
||||
}
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_in2,
|
||||
output_indices, 0, 0, true)) {
|
||||
scripts[number_of_scripts++] = fade_in2;
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_in2, 0)) {
|
||||
scripts[number_of_scripts++] = fade_in2.script;
|
||||
} else {
|
||||
script_free(fade_in2);
|
||||
script_free(fade_in2.script);
|
||||
}
|
||||
} else {
|
||||
log_error("Invalid fade-in setting (step: %f, delta: %d), ignoring.",
|
||||
|
@ -492,7 +488,8 @@ void generate_fading_config(struct options *opt) {
|
|||
// Fading out to nothing, i.e. `hide` and `close`
|
||||
asnprintf(&str, &len, FADING_TEMPLATE_1 FADING_TEMPLATE_2, duration_str,
|
||||
duration_str, 1, 0);
|
||||
auto fade_out1 = compile_win_script_from_string(str, output_indices);
|
||||
struct win_script fade_out1 = {.is_generated = true};
|
||||
BUG_ON(!compile_win_script_from_string(&fade_out1, str));
|
||||
number_of_triggers = 0;
|
||||
if (opt->animations[ANIMATION_TRIGGER_CLOSE].script == NULL &&
|
||||
!opt->no_fading_openclose) {
|
||||
|
@ -501,25 +498,24 @@ void generate_fading_config(struct options *opt) {
|
|||
if (opt->animations[ANIMATION_TRIGGER_HIDE].script == NULL) {
|
||||
trigger[number_of_triggers++] = ANIMATION_TRIGGER_HIDE;
|
||||
}
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_out1,
|
||||
output_indices, 0, 0, true)) {
|
||||
scripts[number_of_scripts++] = fade_out1;
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_out1, 0)) {
|
||||
scripts[number_of_scripts++] = fade_out1.script;
|
||||
} else {
|
||||
script_free(fade_out1);
|
||||
script_free(fade_out1.script);
|
||||
}
|
||||
|
||||
// Fading for opacity change
|
||||
asnprintf(&str, &len, FADING_TEMPLATE_1, duration_str);
|
||||
auto fade_out2 = compile_win_script_from_string(str, output_indices);
|
||||
struct win_script fade_out2 = {.is_generated = true};
|
||||
BUG_ON(!compile_win_script_from_string(&fade_out2, str));
|
||||
number_of_triggers = 0;
|
||||
if (opt->animations[ANIMATION_TRIGGER_DECREASE_OPACITY].script == NULL) {
|
||||
trigger[number_of_triggers++] = ANIMATION_TRIGGER_DECREASE_OPACITY;
|
||||
}
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_out2,
|
||||
output_indices, 0, 0, true)) {
|
||||
scripts[number_of_scripts++] = fade_out2;
|
||||
if (set_animation(opt->animations, trigger, number_of_triggers, fade_out2, 0)) {
|
||||
scripts[number_of_scripts++] = fade_out2.script;
|
||||
} else {
|
||||
script_free(fade_out2);
|
||||
script_free(fade_out2.script);
|
||||
}
|
||||
} else {
|
||||
log_error("Invalid fade-out setting (step: %f, delta: %d), ignoring.",
|
||||
|
|
451
src/transition/generated/script_templates.c
Normal file
451
src/transition/generated/script_templates.c
Normal file
|
@ -0,0 +1,451 @@
|
|||
// This file is generated by tools/animgen.c from data/animation_presets.conf
|
||||
// This file is included in git repository for convenience only.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
|
||||
#include <libconfig.h>
|
||||
#include "../curve.h"
|
||||
#include "../script.h"
|
||||
#include "../script_internal.h"
|
||||
#include "config.h"
|
||||
#include "utils/misc.h"
|
||||
static struct script *script_template__disappear(int *output_slots) {
|
||||
static const struct instruction instrs[] = {
|
||||
{.type = INST_BRANCH_ONCE, .rel = 59},
|
||||
{.type = INST_LOAD, .slot = 14},
|
||||
{.type = INST_LOAD, .slot = 13},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 11},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 15},
|
||||
{.type = INST_OP, .op = OP_DIV},
|
||||
{
|
||||
.type = INST_CURVE,
|
||||
.curve = {.type = CURVE_LINEAR},
|
||||
},
|
||||
{.type = INST_OP, .op = OP_MUL},
|
||||
{.type = INST_LOAD, .slot = 13},
|
||||
{.type = INST_OP, .op = OP_ADD},
|
||||
{.type = INST_STORE, .slot = 0},
|
||||
{.type = INST_LOAD, .slot = 0},
|
||||
{.type = INST_STORE, .slot = 1},
|
||||
{.type = INST_LOAD, .slot = 0},
|
||||
{.type = INST_STORE, .slot = 2},
|
||||
{.type = INST_LOAD, .slot = 17},
|
||||
{.type = INST_LOAD, .slot = 16},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 11},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.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}},
|
||||
},
|
||||
{.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_LOAD, .slot = 5},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_IMM, .imm = 2.000000},
|
||||
{.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_LOAD, .slot = 6},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_IMM, .imm = 2.000000},
|
||||
{.type = INST_OP, .op = OP_DIV},
|
||||
{.type = INST_LOAD_CTX, .ctx = 24},
|
||||
{.type = INST_OP, .op = OP_MUL},
|
||||
{.type = INST_STORE, .slot = 4},
|
||||
{.type = INST_LOAD, .slot = 5},
|
||||
{.type = INST_STORE, .slot = 7},
|
||||
{.type = INST_LOAD, .slot = 6},
|
||||
{.type = INST_STORE, .slot = 8},
|
||||
{.type = INST_LOAD, .slot = 3},
|
||||
{.type = INST_STORE, .slot = 9},
|
||||
{.type = INST_LOAD, .slot = 4},
|
||||
{.type = INST_STORE, .slot = 10},
|
||||
{.type = INST_BRANCH_ONCE, .rel = 15},
|
||||
{.type = INST_HALT},
|
||||
{.type = INST_LOAD_CTX, .ctx = 32},
|
||||
{.type = INST_STORE_OVER_NAN, .slot = 13},
|
||||
{.type = INST_LOAD_CTX, .ctx = 1073741824},
|
||||
{.type = INST_STORE, .slot = 15},
|
||||
{.type = INST_LOAD_CTX, .ctx = 40},
|
||||
{.type = INST_STORE, .slot = 14},
|
||||
{.type = INST_IMM, .imm = 1.000000},
|
||||
{.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_STORE, .slot = 12},
|
||||
{.type = INST_LOAD, .slot = 15},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.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_OP, .op = OP_ADD},
|
||||
{.type = INST_LOAD, .slot = 12},
|
||||
{.type = INST_OP, .op = OP_MAX},
|
||||
{.type = INST_STORE, .slot = 12},
|
||||
{.type = INST_HALT},
|
||||
};
|
||||
struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs));
|
||||
ret->len = ARR_SIZE(instrs);
|
||||
ret->elapsed_slot = 11;
|
||||
ret->n_slots = 19;
|
||||
ret->stack_size = 3;
|
||||
ret->vars = NULL;
|
||||
ret->overrides = NULL;
|
||||
memcpy(ret->instrs, instrs, sizeof(instrs));
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("opacity"), .slot = 0, .index = 0};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("blur-opacity"), .slot = 1, .index = 1};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-opacity"), .slot = 2, .index = 2};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("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("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("scale-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("scale-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("shadow-scale-x"), .slot = 7, .index = 7};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-scale-y"), .slot = 8, .index = 8};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-offset-x"), .slot = 9, .index = 9};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-offset-y"), .slot = 10, .index = 10};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct overridable_slot *override = malloc(sizeof(*override));
|
||||
*override = (struct overridable_slot){.name = strdup("opacity"), .slot = 13};
|
||||
HASH_ADD_STR(ret->overrides, name, override);
|
||||
}
|
||||
{
|
||||
struct overridable_slot *override = malloc(sizeof(*override));
|
||||
*override = (struct overridable_slot){.name = strdup("scale-x"), .slot = 16};
|
||||
HASH_ADD_STR(ret->overrides, name, override);
|
||||
}
|
||||
output_slots[0] = 3;
|
||||
output_slots[1] = 4;
|
||||
output_slots[2] = 9;
|
||||
output_slots[3] = 10;
|
||||
output_slots[4] = 0;
|
||||
output_slots[5] = 1;
|
||||
output_slots[6] = 2;
|
||||
output_slots[7] = 5;
|
||||
output_slots[8] = 6;
|
||||
output_slots[9] = 7;
|
||||
output_slots[10] = 8;
|
||||
output_slots[11] = -1;
|
||||
output_slots[12] = -1;
|
||||
output_slots[13] = -1;
|
||||
output_slots[14] = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
struct script_specialization_context spec[] = {
|
||||
{.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration},
|
||||
{.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder_scale},
|
||||
};
|
||||
script_specialize(output->script, spec, ARR_SIZE(spec));
|
||||
return true;
|
||||
}
|
||||
static struct script *script_template__appear(int *output_slots) {
|
||||
static const struct instruction instrs[] = {
|
||||
{.type = INST_BRANCH_ONCE, .rel = 59},
|
||||
{.type = INST_LOAD, .slot = 14},
|
||||
{.type = INST_LOAD, .slot = 13},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 11},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 15},
|
||||
{.type = INST_OP, .op = OP_DIV},
|
||||
{
|
||||
.type = INST_CURVE,
|
||||
.curve = {.type = CURVE_LINEAR},
|
||||
},
|
||||
{.type = INST_OP, .op = OP_MUL},
|
||||
{.type = INST_LOAD, .slot = 13},
|
||||
{.type = INST_OP, .op = OP_ADD},
|
||||
{.type = INST_STORE, .slot = 0},
|
||||
{.type = INST_LOAD, .slot = 0},
|
||||
{.type = INST_STORE, .slot = 1},
|
||||
{.type = INST_LOAD, .slot = 0},
|
||||
{.type = INST_STORE, .slot = 2},
|
||||
{.type = INST_IMM, .imm = 1.000000},
|
||||
{.type = INST_LOAD, .slot = 16},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_LOAD, .slot = 11},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.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}},
|
||||
},
|
||||
{.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_LOAD, .slot = 5},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_IMM, .imm = 2.000000},
|
||||
{.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_LOAD, .slot = 6},
|
||||
{.type = INST_OP, .op = OP_SUB},
|
||||
{.type = INST_IMM, .imm = 2.000000},
|
||||
{.type = INST_OP, .op = OP_DIV},
|
||||
{.type = INST_LOAD_CTX, .ctx = 24},
|
||||
{.type = INST_OP, .op = OP_MUL},
|
||||
{.type = INST_STORE, .slot = 4},
|
||||
{.type = INST_LOAD, .slot = 5},
|
||||
{.type = INST_STORE, .slot = 7},
|
||||
{.type = INST_LOAD, .slot = 6},
|
||||
{.type = INST_STORE, .slot = 8},
|
||||
{.type = INST_LOAD, .slot = 3},
|
||||
{.type = INST_STORE, .slot = 9},
|
||||
{.type = INST_LOAD, .slot = 4},
|
||||
{.type = INST_STORE, .slot = 10},
|
||||
{.type = INST_BRANCH_ONCE, .rel = 13},
|
||||
{.type = INST_HALT},
|
||||
{.type = INST_LOAD_CTX, .ctx = 32},
|
||||
{.type = INST_STORE_OVER_NAN, .slot = 13},
|
||||
{.type = INST_LOAD_CTX, .ctx = 1073741824},
|
||||
{.type = INST_STORE, .slot = 15},
|
||||
{.type = INST_LOAD_CTX, .ctx = 40},
|
||||
{.type = INST_STORE, .slot = 14},
|
||||
{.type = INST_LOAD_CTX, .ctx = 1073741828},
|
||||
{.type = INST_STORE_OVER_NAN, .slot = 16},
|
||||
{.type = INST_LOAD_CTX, .ctx = 1073741824},
|
||||
{.type = INST_STORE, .slot = 17},
|
||||
{.type = INST_BRANCH, .rel = -68},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.type = INST_STORE, .slot = 12},
|
||||
{.type = INST_LOAD, .slot = 15},
|
||||
{.type = INST_IMM, .imm = 0.000000},
|
||||
{.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_OP, .op = OP_ADD},
|
||||
{.type = INST_LOAD, .slot = 12},
|
||||
{.type = INST_OP, .op = OP_MAX},
|
||||
{.type = INST_STORE, .slot = 12},
|
||||
{.type = INST_HALT},
|
||||
};
|
||||
struct script *ret = malloc(offsetof(struct script, instrs) + sizeof(instrs));
|
||||
ret->len = ARR_SIZE(instrs);
|
||||
ret->elapsed_slot = 11;
|
||||
ret->n_slots = 18;
|
||||
ret->stack_size = 3;
|
||||
ret->vars = NULL;
|
||||
ret->overrides = NULL;
|
||||
memcpy(ret->instrs, instrs, sizeof(instrs));
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("opacity"), .slot = 0, .index = 0};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("blur-opacity"), .slot = 1, .index = 1};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-opacity"), .slot = 2, .index = 2};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("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("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("scale-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("scale-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("shadow-scale-x"), .slot = 7, .index = 7};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-scale-y"), .slot = 8, .index = 8};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-offset-x"), .slot = 9, .index = 9};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct variable_allocation *var = malloc(sizeof(*var));
|
||||
*var = (struct variable_allocation){
|
||||
.name = strdup("shadow-offset-y"), .slot = 10, .index = 10};
|
||||
HASH_ADD_STR(ret->vars, name, var);
|
||||
}
|
||||
{
|
||||
struct overridable_slot *override = malloc(sizeof(*override));
|
||||
*override = (struct overridable_slot){.name = strdup("opacity"), .slot = 13};
|
||||
HASH_ADD_STR(ret->overrides, name, override);
|
||||
}
|
||||
{
|
||||
struct overridable_slot *override = malloc(sizeof(*override));
|
||||
*override = (struct overridable_slot){.name = strdup("scale-x"), .slot = 16};
|
||||
HASH_ADD_STR(ret->overrides, name, override);
|
||||
}
|
||||
output_slots[0] = 3;
|
||||
output_slots[1] = 4;
|
||||
output_slots[2] = 9;
|
||||
output_slots[3] = 10;
|
||||
output_slots[4] = 0;
|
||||
output_slots[5] = 1;
|
||||
output_slots[6] = 2;
|
||||
output_slots[7] = 5;
|
||||
output_slots[8] = 6;
|
||||
output_slots[9] = 7;
|
||||
output_slots[10] = 8;
|
||||
output_slots[11] = -1;
|
||||
output_slots[12] = -1;
|
||||
output_slots[13] = -1;
|
||||
output_slots[14] = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
struct script_specialization_context spec[] = {
|
||||
{.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 0, .value = placeholder_duration},
|
||||
{.offset = SCRIPT_CTX_PLACEHOLDER_BASE + 4, .value = placeholder_scale},
|
||||
};
|
||||
script_specialize(output->script, spec, ARR_SIZE(spec));
|
||||
return true;
|
||||
}
|
||||
struct {
|
||||
const char *name;
|
||||
bool (*func)(struct win_script *output, config_setting_t *setting);
|
||||
} win_script_presets[] = {
|
||||
{"disappear", win_script_preset__disappear},
|
||||
{"appear", win_script_preset__appear},
|
||||
{NULL, NULL},
|
||||
};
|
|
@ -1 +1 @@
|
|||
srcs += [ files('curve.c', 'script.c') ]
|
||||
srcs += [files('generated/script_templates.c', 'curve.c', 'preset.c', 'script.c')]
|
||||
|
|
30
src/transition/preset.c
Normal file
30
src/transition/preset.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||
|
||||
#include <libconfig.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "preset.h"
|
||||
#include "script.h"
|
||||
|
||||
extern struct {
|
||||
const char *name;
|
||||
bool (*func)(struct win_script *output, config_setting_t *setting);
|
||||
} win_script_presets[];
|
||||
|
||||
bool win_script_parse_preset(struct win_script *output, config_setting_t *setting) {
|
||||
const char *preset = NULL;
|
||||
if (!config_setting_lookup_string(setting, "preset", &preset)) {
|
||||
log_error("Missing preset name in script");
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; win_script_presets[i].name; i++) {
|
||||
if (strcmp(preset, win_script_presets[i].name) == 0) {
|
||||
log_debug("Using animation preset: %s", preset);
|
||||
return win_script_presets[i].func(output, setting);
|
||||
}
|
||||
}
|
||||
log_error("Unknown preset: %s", preset);
|
||||
return false;
|
||||
}
|
12
src/transition/preset.h
Normal file
12
src/transition/preset.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct config_setting_t config_setting_t;
|
||||
struct win_script;
|
||||
|
||||
/// Parse a animation preset definition into a win_script.
|
||||
bool win_script_parse_preset(struct win_script *output, config_setting_t *setting);
|
|
@ -1127,6 +1127,22 @@ char *script_to_c(const struct script *script, const struct script_output_info *
|
|||
return dynarr_join(buf, "");
|
||||
}
|
||||
|
||||
void script_specialize(struct script *script,
|
||||
const struct script_specialization_context *spec, unsigned n_context) {
|
||||
for (unsigned i = 0; i < script->len; i++) {
|
||||
if (script->instrs[i].type != INST_LOAD_CTX) {
|
||||
continue;
|
||||
}
|
||||
for (unsigned j = 0; j < n_context; j++) {
|
||||
if (script->instrs[i].ctx == spec[j].offset) {
|
||||
script->instrs[i].type = INST_IMM;
|
||||
script->instrs[i].imm = spec[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct script_instance *script_instance_new(const struct script *script) {
|
||||
// allocate no space for the variable length array is UB.
|
||||
unsigned memory_size = max2(1, script->n_slots + script->stack_size);
|
||||
|
|
|
@ -14,6 +14,11 @@ struct script_context_info {
|
|||
ptrdiff_t offset;
|
||||
};
|
||||
|
||||
struct script_specialization_context {
|
||||
ptrdiff_t offset;
|
||||
double value;
|
||||
};
|
||||
|
||||
struct script_output_info {
|
||||
const char *name;
|
||||
/// Slot for this variable, -1 if this variable doesn't exist.
|
||||
|
@ -66,6 +71,13 @@ struct script_instance *script_instance_new(const struct script *script);
|
|||
unsigned script_total_duration_slot(const struct script *script);
|
||||
unsigned script_elapsed_slot(const struct script *script);
|
||||
|
||||
/// Specialize a script instance with a context. During evaluation of the resulting
|
||||
/// script, what would have been read from the context will be replaced with the hardcoded
|
||||
/// value in the specialization context.
|
||||
void script_specialize(struct script *instance,
|
||||
const struct script_specialization_context *context,
|
||||
unsigned n_context);
|
||||
|
||||
/// Check if a script instance has finished. The script instance must have been evaluated
|
||||
/// at least once.
|
||||
static inline bool script_instance_is_finished(const struct script_instance *instance) {
|
||||
|
|
Loading…
Reference in a new issue