diff --git a/config.cpp b/config.cpp index ec6881bc..b5d15a41 100644 --- a/config.cpp +++ b/config.cpp @@ -795,6 +795,9 @@ EX void initConfig() { ld bonus = 0; ld emul = 1; + + param_b(dialog::onscreen_keyboard, "onscreen_keyboard") + ->editable("onscreen keyboard", 'k'); addsaver(sightranges[gBinary3], "sight-binary3", 3.1 + bonus); addsaver(sightranges[gCubeTiling], "sight-cubes", 10); @@ -2573,6 +2576,13 @@ EX void add_to_changed(setting *f) { last_changed.push_back(f); } +EX setting *find_edit(void *val) { + for(auto& fs: params) + if(fs.second->affects(val)) + return &*fs.second; + return nullptr; + } + EX void add_edit_ptr(void *val) { int found = 0; for(auto& fs: params) diff --git a/dialogs.cpp b/dialogs.cpp index 2d1fad73..55218d09 100644 --- a/dialogs.cpp +++ b/dialogs.cpp @@ -816,6 +816,57 @@ EX namespace dialog { addKeyboardItem(lr ? " \t\x1\x2" : " \t"); } + EX bool onscreen_keyboard = ISMOBILE; + + EX void number_dialog_help() { + init("number dialog help"); + dialog::addBreak(100); + dialog::addHelp(XLAT("You can enter formulas in this dialog.")); + dialog::addBreak(100); + dialog::addHelp(XLAT("Functions available:")); + addHelp(available_functions()); + dialog::addBreak(100); + dialog::addHelp(XLAT("Constants and variables available:")); + addHelp(available_constants()); + if(ne.animatable) { + dialog::addBreak(100); + dialog::addHelp(XLAT("Animations:")); + dialog::addHelp(XLAT("a..b -- animate linearly from a to b")); + dialog::addHelp(XLAT("a..b..|c..d -- animate from a to b, then from c to d")); + dialog::addHelp(XLAT("a../x..b../y -- change smoothly, x and y are derivatives")); + } + + /* "Most parameters can be animated simply by using '..' in their editing dialog. " + "For example, the value of a parameter set to 0..1 will grow linearly from 0 to 1. " + "You can also use functions (e.g. cos(0..2*pi)) and refer to other parameters." + )); */ + + #if CAP_ANIMATIONS + dialog::addBreak(50); + auto f = find_edit(ne.intval ? (void*) ne.intval : (void*) ne.editwhat); + if(f) + dialog::addHelp(XLAT("Parameter names, e.g. '%1'", f->parameter_name)); + else + 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); + } + #endif + dialog::addBreak(50); + dialog::addHelp(XLAT("These can be combined, e.g. %1", "projection*sin(0..2*pi)")); + display(); + } + + EX void parser_help() { + ne.editwhat = nullptr; + ne.intval = nullptr; + addItem("help", SDLK_F1); + add_action_push(number_dialog_help); + } + EX void drawNumberDialog() { cmode = sm::NUMBER | dialogflags; if(numberdark < DONT_SHOW) @@ -834,6 +885,9 @@ EX namespace dialog { dialog::addBack(); addSelItem(XLAT("default value"), disp(ne.dft), SDLK_HOME); + add_edit(onscreen_keyboard); + addItem("help", SDLK_F1); + add_action_push(number_dialog_help); addBreak(100); @@ -845,14 +899,16 @@ EX namespace dialog { if(extra_options) extra_options(); - addBreak(100); - formula_keyboard(false); + if(onscreen_keyboard) { + addBreak(100); + formula_keyboard(false); + } display(); keyhandler = [] (int sym, int uni) { handleNavigation(sym, uni); - if((uni >= '0' && uni <= '9') || among(uni, '.', '+', '-', '*', '/', '^', '(', ')', ',', 3) || (uni >= 'a' && uni <= 'z')) { + if((uni >= '0' && uni <= '9') || among(uni, '.', '+', '-', '*', '/', '^', '(', ')', ',', '|', 3) || (uni >= 'a' && uni <= 'z')) { if(uni == 3) ne.s += "pi"; else ne.s += uni; apply_edit(); diff --git a/models.cpp b/models.cpp index 96faaf9b..22d3a602 100644 --- a/models.cpp +++ b/models.cpp @@ -303,10 +303,11 @@ EX namespace models { "This lets you specify the projection as a formula f. " "The formula has access to the value 'z', which is a complex number corresponding to the (x,y) coordinates in the currently selected model; " "the point z is mapped to f(z). You can also use the underlying coordinates ux, uy, uz." - ) + "\n\n" + parser_help() + ) ); #if CAP_QUEUE && CAP_CURVE dialog::extra_options = [] () { + dialog::parser_help(); initquickqueue(); queuereset(mdPixel, PPR::LINE); for(int a=-1; a<=1; a++) { diff --git a/pattern2.cpp b/pattern2.cpp index 351276ec..c4b32397 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -2085,10 +2085,10 @@ EX namespace patterns { ); s += XLAT("see compute_map_function in pattern2.cpp for more\n"); - - s += "\n\n" + parser_help(); - + dialog::edit_string(color_formula, "formula", s); + + dialog::extra_options = dialog::parser_help; dialog::reaction_final = [instant] () { if(instant) stop_game(); whichCanvas = 'f'; diff --git a/screenshot.cpp b/screenshot.cpp index b7a4bd1b..3ae33758 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -1118,14 +1118,16 @@ EX void moved() { playermoved = false; } +#if HDR struct animated_parameter { ld *value; ld last; string formula; reaction_t reaction; }; +#endif -vector aps; +EX vector aps; EX void deanimate(ld &x) { for(int i=0; iaffects(ap.value)) what = p.first; - dialog::addInfo(what + " = " + ap.formula); - } - dialog::addBreak(50); - dialog::addHelp(parser_help()); - } - ld animation_period; EX void rug_angle_options() { @@ -1656,13 +1641,11 @@ EX void show() { dialog::addSelItem(XLAT("animate parameters"), fts(a), 'a'); dialog::add_action([] () { dialog::editNumber(a, -100, 100, 1, 0, XLAT("animate parameters"), ""); - dialog::extra_options = list_animated_parameters; }); dialog::addSelItem(XLAT("animate parameters"), fts(b), 'b'); dialog::add_action([] () { dialog::editNumber(b, -100, 100, 1, 0, XLAT("animate parameters"), ""); - dialog::extra_options = list_animated_parameters; }); dialog::addBoolItem(XLAT("history mode"), (history::on || history::includeHistory), 'h'); diff --git a/util.cpp b/util.cpp index d1f7470c..7aa3c66c 100644 --- a/util.cpp +++ b/util.cpp @@ -445,9 +445,14 @@ EX ld parseld(const string& s) { return real(ep.parse()); } -EX string parser_help() { - return XLAT("Functions available: %1", - "(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], sqrt, to01, random, edge(7,3), regradius(7,3), ifp(a,v,w) [if positive]"); +EX string available_functions() { + return + "(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, sqrt, to01, random, edge(7,3), regradius(7,3), ifp(a,v,w) [if positive]"; + } + +EX string available_constants() { + return + "e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation]"; } #if HDR