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:
parent
a13ba9bdbe
commit
5057f10358
@ -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
|
||||
|
147
config.cpp
147
config.cpp
@ -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;
|
||||
}
|
||||
|
||||
|
15
dialogs.cpp
15
dialogs.cpp
@ -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) {
|
||||
|
@ -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
|
||||
//===========================
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user