1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-01-13 10:50:35 +00:00

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

View File

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

View File

@ -1082,7 +1082,7 @@ EX namespace dialog {
if(ne.intval) *ne.editwhat = *ne.intval; if(ne.intval) *ne.editwhat = *ne.intval;
ne.s = disp(*ne.editwhat); ne.s = disp(*ne.editwhat);
#if CAP_ANIMATIONS #if CAP_ANIMATIONS
anims::deanimate(*ne.editwhat); anims::deanimate(anims::find_param(ne.editwhat));
#endif #endif
} }
@ -1100,7 +1100,10 @@ EX namespace dialog {
*ne.editwhat = x; *ne.editwhat = x;
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat); if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
#if CAP_ANIMATIONS #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 #endif
if(reaction) reaction(); if(reaction) reaction();
} }
@ -1173,9 +1176,7 @@ EX namespace dialog {
dialog::addHelp(XLAT("Parameter names")); dialog::addHelp(XLAT("Parameter names"));
dialog::addBreak(50); dialog::addBreak(50);
for(auto& ap: anims::aps) { for(auto& ap: anims::aps) {
string what = "?"; dialog::addInfo(ap.par->parameter_name + " = " + ap.formula);
for(auto& p: params) if(p.second->affects(ap.value)) what = p.first;
dialog::addInfo(what + " = " + ap.formula);
} }
#endif #endif
dialog::addBreak(50); dialog::addBreak(50);
@ -1358,7 +1359,7 @@ EX namespace dialog {
extra_options = reaction_t(); extra_options = reaction_t();
ne.animatable = true; ne.animatable = true;
#if CAP_ANIMATIONS #if CAP_ANIMATIONS
anims::get_parameter_animation(x, ne.s); anims::get_parameter_animation(anims::find_param(&x), ne.s);
#endif #endif
} }
@ -1381,7 +1382,7 @@ EX namespace dialog {
reaction = [&] { x = spin(angle * degree); }; reaction = [&] { x = spin(angle * degree); };
reaction_final = reaction; reaction_final = reaction;
extra_options = reaction_t(); 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) { 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() { v2 = Id; v3 = Id; }
trans23(const transmatrix& T) { v2 = T; v3 = T; } trans23(const transmatrix& T) { v2 = T; v3 = T; }
trans23(const transmatrix& T2, const transmatrix& T3) { v2 = T2; v3 = T3; } 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 operator * (trans23 T) {
trans23 t; trans23 t;
auto& dim = cginf.g.homogeneous_dimension; auto& dim = cginf.g.homogeneous_dimension;
@ -254,6 +256,8 @@ constexpr hyperpoint C03 = hyperpoint(0,0,0,1);
#define C0 (MDIM == 3 ? C02 : C03) #define C0 (MDIM == 3 ? C02 : C03)
#endif #endif
bool trans23::operator == (const trans23& b) const { return eqmatrix(v2, b.v2) && eqmatrix(v3, b.v3); }
// basic functions and types // basic functions and types
//=========================== //===========================

View File

@ -835,10 +835,6 @@ EX namespace models {
PHASEFROM(2); PHASEFROM(2);
shift_arg_formula(vpconf.halfplane_scale); shift_arg_formula(vpconf.halfplane_scale);
} }
else if(argis("-mori")) {
PHASEFROM(2);
shift_arg_formula_matrix(vpconf.mori());
}
else if(argis("-mets")) { else if(argis("-mets")) {
PHASEFROM(2); PHASEFROM(2);
shift_arg_formula(vpconf.euclid_to_sphere); 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 #endif
vector<bool> chg; 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([&] { finalizer f([&] {
for(int i=0; i<isize(anims::aps); i++) 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(); if(intra::in) what();
@ -1176,30 +1176,43 @@ EX void moved() {
#if HDR #if HDR
struct animated_parameter { struct animated_parameter {
ld *value; setting *par;
ld last;
string formula; string formula;
reaction_t reaction;
}; };
#endif #endif
EX vector<animated_parameter> aps; 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++) for(int i=0; i<isize(aps); i++)
if(aps[i].value == &x) if(aps[i].par == p)
aps.erase(aps.begin() + (i--)); 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) for(auto &ap: aps)
if(ap.value == &x && ap.last == x) if(ap.par == p && ap.par->anim_unchanged())
s = ap.formula; s = ap.formula;
} }
EX void animate_parameter(ld &x, string f, const reaction_t& r) { EX void animate_parameter(ld &x, string f) {
deanimate(x); auto par = find_param(&x);
aps.emplace_back(animated_parameter{&x, x, f, r}); 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; int ap_changes;
@ -1207,18 +1220,13 @@ int ap_changes;
void apply_animated_parameters() { void apply_animated_parameters() {
ap_changes = 0; ap_changes = 0;
for(auto &ap: aps) { for(auto &ap: aps) {
if(*ap.value != ap.last) continue;
try { try {
*ap.value = parseld(ap.formula); if(ap.par->load_from_animation(ap.formula))
ap_changes++;
} }
catch(hr_parse_exception&) { catch(hr_parse_exception&) {
continue; continue;
} }
if(*ap.value != ap.last) {
if(ap.reaction) ap.reaction();
ap_changes++;
ap.last = *ap.value;
}
} }
} }