improved parameter animation

This commit is contained in:
Zeno Rogue 2023-08-09 01:01:32 +02:00
parent a13ba9bdbe
commit 5057f10358
6 changed files with 131 additions and 100 deletions

View File

@ -112,18 +112,15 @@ EX namespace arg {
return strtoll(argcs(), NULL, 16);
}
int parameter_id;
EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) {
shift(); ld old = x; x = argf();
#if CAP_ANIMATIONS
anims::animate_parameter(x, args(), r);
#endif
if(old != x && r) r();
shift();
auto par = anims::find_param(&x);
if(!par) par = param_f(x, "tmp_parameter_" + its(parameter_id++))->set_reaction(r);
par->load_as_animation(args());
}
EX void shift_arg_formula_matrix(struct hr::trans23& x) {
shift(); x = parsematrix23(args()); // TODO animate
}
#if HDR
// an useful macro

View File

@ -46,7 +46,6 @@ struct setting {
string help_text;
reaction_t reaction;
char default_key;
cld last_value;
bool is_editable;
supersaver *saver;
virtual bool available() { if(restrict) return restrict(); return true; }
@ -59,16 +58,8 @@ struct setting {
virtual string search_key() {
return parameter_name + "|" + config_name + "|" + menu_item_name + "|" + help_text;
}
virtual cld get_cld() = 0;
virtual void set_cld(cld x) = 0;
explicit setting() { restrict = auto_restrict; is_editable = false; }
virtual void check_change() {
cld val = get_cld();
if(val != last_value) {
last_value = val;
add_to_changed(this);
}
}
virtual void check_change() { }
reaction_t sets;
setting *set_sets(const reaction_t& s) { sets = s; return this; }
setting *set_extra(const reaction_t& r);
@ -79,6 +70,15 @@ struct setting {
println(hlog, "cannot load this parameter");
exit(1);
}
virtual bool load_from_animation(const string& s) {
load_from(s); return false;
}
virtual void load_as_animation(const string& s) {
load_from(s);
}
virtual bool anim_unchanged() { return true; }
virtual void anim_restore() { }
virtual cld get_cld() { throw hr_exception("parameter has no complex value"); }
};
#endif
@ -110,22 +110,54 @@ struct list_setting : setting {
};
template<class T> struct enum_setting : list_setting {
T *value;
T *value, last_value;
T dft;
int get_value() override { return (int) *value; }
void set_value(int i) override { *value = (T) i; }
bool affects(void* v) override { return v == value; }
supersaver *make_saver() override;
cld get_cld() override { return get_value(); }
virtual void set_cld(cld x) { set_value(floor(real(x)+.5)); }
void load_from(const string& s) override {
*value = (T) parseint(s);
}
virtual void check_change() {
if(*value != last_value) {
last_value = *value;
add_to_changed(this);
}
}
};
struct float_setting : public setting {
ld *value;
ld dft;
namespace anims {
extern void animate_setting(setting*, string);
}
template<class T> struct val_setting : public setting {
T *value, last_value, anim_value, dft;
bool affects(void *v) override { return v == value; }
virtual void check_change() {
if(*value != last_value) {
last_value = *value;
add_to_changed(this);
}
}
virtual bool anim_unchanged() { return *value == anim_value; }
virtual void anim_restore() { *value = anim_value; if(reaction) reaction(); }
bool load_from_animation(const string& s) override {
if(anim_value != *value) return false;
load_from(s);
anim_value = *value;
return true;
}
void load_as_animation(const string& s) override {
load_from(s);
anim_value = *value;
anims::animate_setting(this, s);
}
};
struct float_setting : public val_setting<ld> {
ld min_value, max_value, step;
string unit;
float_setting *editable(ld min_value, ld max_value, ld step, string menu_item_name, string help_text, char key) {
@ -141,11 +173,9 @@ struct float_setting : public setting {
function<void(float_setting*)> modify_me;
float_setting *modif(const function<void(float_setting*)>& r) { modify_me = r; return this; }
supersaver *make_saver() override;
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return *value; }
void set_cld(cld x) override { *value = real(x); }
void load_from(const string& s) override;
virtual cld get_cld() override { return *value; }
};
struct float_setting_dft : public float_setting {
@ -154,18 +184,13 @@ struct float_setting_dft : public float_setting {
float_setting_dft* set_hint(const function<ld()>& f) { get_hint = f; return this; }
};
struct int_setting : public setting {
int *value;
int dft;
struct int_setting : public val_setting<int> {
int min_value, max_value;
ld step;
supersaver *make_saver() override;
function<void(int_setting*)> modify_me;
int_setting *modif(const function<void(int_setting*)>& r) { modify_me = r; return this; }
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return *value; }
void set_cld(cld x) override { *value = floor(real(x)+.5); }
int_setting *editable(int min_value, int max_value, ld step, string menu_item_name, string help_text, char key) {
this->is_editable = true;
this->min_value = min_value;
@ -177,20 +202,24 @@ struct int_setting : public setting {
return this;
}
virtual cld get_cld() override { return *value; }
void load_from(const string& s) override {
*value = parseint(s);
}
virtual void check_change() {
if(*value != last_value) {
last_value = *value;
add_to_changed(this);
}
}
};
struct color_setting : public setting {
color_t *value;
color_t dft;
struct color_setting : public val_setting<color_t> {
bool has_alpha;
supersaver *make_saver() override;
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return *value; }
void set_cld(cld x) override { *value = floor(real(x)+.5); }
color_setting *editable(string menu_item_name, string help_text, char key) {
this->is_editable = true;
this->menu_item_name = menu_item_name;
@ -204,15 +233,9 @@ struct color_setting : public setting {
}
};
struct matrix_setting : public setting {
trans23 *value;
trans23 dft;
trans23 last_value_matrix;
struct matrix_setting : public val_setting<trans23> {
supersaver *make_saver() override;
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return 0; }
void set_cld(cld x) override { }
matrix_setting *editable(string menu_item_name, string help_text, char key) {
this->is_editable = true;
this->menu_item_name = menu_item_name;
@ -221,19 +244,12 @@ struct matrix_setting : public setting {
return this;
}
void load_from(const string& s) override {
*value = parsematrix23(s);
}
void load_from(const string& s) override;
};
struct char_setting : public setting {
char *value;
char dft;
struct char_setting : public val_setting<char> {
supersaver *make_saver() override;
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return *value; }
void set_cld(cld x) override { *value = floor(real(x)+.5); }
void load_from(const string& s) override {
if(s == "\\0") value = 0;
@ -241,33 +257,34 @@ struct char_setting : public setting {
}
};
struct bool_setting : public setting {
bool *value;
bool dft;
struct bool_setting : public val_setting<bool> {
supersaver *make_saver() override;
reaction_t switcher;
bool_setting* editable(string cap, char key ) {
is_editable = true;
menu_item_name = cap; default_key = key; return this;
}
bool affects(void *v) override { return v == value; }
void show_edit_option(int key) override;
cld get_cld() override { return *value ? 1 : 0; }
void set_cld(cld x) override { *value = real(x) >= 0.5; }
void load_from(const string& s) override {
*value = parseint(s);
}
virtual cld get_cld() override { return *value; }
};
struct custom_setting : public setting {
cld last_value;
function<void(char)> custom_viewer;
function<cld()> custom_value;
function<bool(void*)> custom_affect;
void show_edit_option(int key) override { custom_viewer(key); }
cld get_cld() override { return custom_value(); }
supersaver *make_saver() { throw hr_exception("make_saver for custom_setting"); }
void set_cld(cld x) override { }
bool affects(void *v) override { return custom_affect(v); }
virtual void check_change() {
if(custom_value() != last_value) {
last_value = custom_value();
add_to_changed(this);
}
}
};
struct local_parameter_set {
@ -474,9 +491,17 @@ supersaver *bool_setting::make_saver() {
}
void float_setting::load_from(const string& s) {
*value = parseld(s);
anims::animate_parameter(*value, s, reaction);
if(reaction) reaction();
auto res = parseld(s);
auto bak = *value;
*value = res;
if(res != bak && reaction) reaction();
}
void matrix_setting::load_from(const string& s) {
auto res = parsematrix23(s);
auto bak = *value;
*value = res;
if(res != bak && reaction) reaction();
}
void non_editable() {
@ -673,7 +698,7 @@ EX matrix_setting *param_matrix(trans23& val, const string s) {
u->config_name = s;
u->menu_item_name = s;
u->value = &val;
u->last_value_matrix = val;
u->last_value = val;
u->dft = val;
u->register_saver();
auto f = &*u;
@ -716,7 +741,7 @@ template<class T> enum_setting<T> *param_enum(T& val, const string p, const stri
u->value = &val;
u->dft = dft;
val = dft;
u->last_value = u->get_cld();
u->last_value = dft;
u->register_saver();
auto f = &*u;
params[p] = std::move(u);
@ -4088,7 +4113,7 @@ EX int read_param_args() {
println(hlog, "parameter unknown: ", name);
exit(1);
}
params[name]->load_from(value);
params[name]->load_as_animation(value);
return 0;
}

View File

@ -1082,7 +1082,7 @@ EX namespace dialog {
if(ne.intval) *ne.editwhat = *ne.intval;
ne.s = disp(*ne.editwhat);
#if CAP_ANIMATIONS
anims::deanimate(*ne.editwhat);
anims::deanimate(anims::find_param(ne.editwhat));
#endif
}
@ -1100,7 +1100,10 @@ EX namespace dialog {
*ne.editwhat = x;
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
#if CAP_ANIMATIONS
if(ne.animatable) anims::animate_parameter(*ne.editwhat, ne.s, reaction ? reaction : reaction_final);
if(ne.animatable) {
auto p = anims::find_param(ne.editwhat);
if(p) p->load_as_animation(ne.s);
}
#endif
if(reaction) reaction();
}
@ -1173,9 +1176,7 @@ EX namespace dialog {
dialog::addHelp(XLAT("Parameter names"));
dialog::addBreak(50);
for(auto& ap: anims::aps) {
string what = "?";
for(auto& p: params) if(p.second->affects(ap.value)) what = p.first;
dialog::addInfo(what + " = " + ap.formula);
dialog::addInfo(ap.par->parameter_name + " = " + ap.formula);
}
#endif
dialog::addBreak(50);
@ -1358,7 +1359,7 @@ EX namespace dialog {
extra_options = reaction_t();
ne.animatable = true;
#if CAP_ANIMATIONS
anims::get_parameter_animation(x, ne.s);
anims::get_parameter_animation(anims::find_param(&x), ne.s);
#endif
}
@ -1381,7 +1382,7 @@ EX namespace dialog {
reaction = [&] { x = spin(angle * degree); };
reaction_final = reaction;
extra_options = reaction_t();
ne.animatable = true;
ne.animatable = false;
}
EX void editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help) {

View File

@ -210,6 +210,8 @@ struct trans23 {
trans23() { v2 = Id; v3 = Id; }
trans23(const transmatrix& T) { v2 = T; v3 = T; }
trans23(const transmatrix& T2, const transmatrix& T3) { v2 = T2; v3 = T3; }
bool operator == (const trans23& b) const;
bool operator != (const trans23& b) const { return !(self == b); }
trans23 operator * (trans23 T) {
trans23 t;
auto& dim = cginf.g.homogeneous_dimension;
@ -254,6 +256,8 @@ constexpr hyperpoint C03 = hyperpoint(0,0,0,1);
#define C0 (MDIM == 3 ? C02 : C03)
#endif
bool trans23::operator == (const trans23& b) const { return eqmatrix(v2, b.v2) && eqmatrix(v3, b.v3); }
// basic functions and types
//===========================

View File

@ -835,10 +835,6 @@ EX namespace models {
PHASEFROM(2);
shift_arg_formula(vpconf.halfplane_scale);
}
else if(argis("-mori")) {
PHASEFROM(2);
shift_arg_formula_matrix(vpconf.mori());
}
else if(argis("-mets")) {
PHASEFROM(2);
shift_arg_formula(vpconf.euclid_to_sphere);

View File

@ -792,10 +792,10 @@ EX void take(string fname, const function<void()>& what IS(default_screenshot_co
#endif
vector<bool> chg;
for(auto ap: anims::aps) chg.push_back(*ap.value == ap.last);
for(auto& ap: anims::aps) chg.push_back(ap.par->anim_unchanged());
finalizer f([&] {
for(int i=0; i<isize(anims::aps); i++)
if(chg[i]) *anims::aps[i].value = anims::aps[i].last;
if(chg[i]) anims::aps[i].par->anim_restore();
});
if(intra::in) what();
@ -1176,30 +1176,43 @@ EX void moved() {
#if HDR
struct animated_parameter {
ld *value;
ld last;
setting *par;
string formula;
reaction_t reaction;
};
#endif
EX vector<animated_parameter> aps;
EX void deanimate(ld &x) {
EX setting *find_param(void *x) {
for(auto& fs: params)
if(fs.second->affects(x))
return &*fs.second;
return nullptr;
}
EX void deanimate(setting *p) {
for(int i=0; i<isize(aps); i++)
if(aps[i].value == &x)
if(aps[i].par == p)
aps.erase(aps.begin() + (i--));
}
EX void get_parameter_animation(ld &x, string &s) {
EX void get_parameter_animation(setting *p, string &s) {
for(auto &ap: aps)
if(ap.value == &x && ap.last == x)
if(ap.par == p && ap.par->anim_unchanged())
s = ap.formula;
}
EX void animate_parameter(ld &x, string f, const reaction_t& r) {
deanimate(x);
aps.emplace_back(animated_parameter{&x, x, f, r});
EX void animate_parameter(ld &x, string f) {
auto par = find_param(&x);
if(!par) { println(hlog, "parameter not animatable"); return; }
deanimate(par);
aps.emplace_back(animated_parameter{par, f});
}
EX void animate_setting(setting *par, string f) {
if(!par) { println(hlog, "parameter not animatable"); return; }
deanimate(par);
aps.emplace_back(animated_parameter{par, f});
}
int ap_changes;
@ -1207,18 +1220,13 @@ int ap_changes;
void apply_animated_parameters() {
ap_changes = 0;
for(auto &ap: aps) {
if(*ap.value != ap.last) continue;
try {
*ap.value = parseld(ap.formula);
if(ap.par->load_from_animation(ap.formula))
ap_changes++;
}
catch(hr_parse_exception&) {
continue;
}
if(*ap.value != ap.last) {
if(ap.reaction) ap.reaction();
ap_changes++;
ap.last = *ap.value;
}
}
}