diff --git a/config.cpp b/config.cpp index 5c1b87b7..1d0f596a 100644 --- a/config.cpp +++ b/config.cpp @@ -22,6 +22,42 @@ EX bool return_false() { return false; } EX bool use_bool_dialog; +/** set to true if a parameter was changed as a consequence of changing linked parameters */ +EX bool linked_consequence; + +EX void adjust_linked() { + indenter ind(2); + geom3::invalid = ""; + dynamicval d(linked_consequence, true); + if(vid.tc_alpha < vid.tc_depth && vid.tc_alpha < vid.tc_camera) { + find_edit(&pconf.alpha)->set_cld(tan_auto(vid.depth) / tan_auto(vid.camera)); + } + else if(vid.tc_depth < vid.tc_alpha && vid.tc_depth < vid.tc_camera) { + ld v = pconf.alpha * tan_auto(vid.camera); + if(hyperbolic && (v<1e-6-12 || v>1-1e-12)) { + geom3::invalid = XLAT("cannot adjust depth"); + v = vid.camera; + } + else v = atan_auto(v); + find_edit(&vid.depth)->set_cld(v); + } + else { + ld v = tan_auto(vid.depth) / pconf.alpha; + if(hyperbolic && (v<1e-12-1 || v>1-1e-12)) { + geom3::invalid = XLAT("cannot adjust camera"); + v = vid.depth; + } + else v = atan_auto(v); + find_edit(&vid.camera)->set_cld(v); + } + } + +EX void update_linked(int& t) { + if(linked_consequence) return; + t = ticks; + adjust_linked(); + } + EX string param_esc(string s); EX void non_editable_pre() { if(game_active) stop_game(); }; @@ -1853,7 +1889,7 @@ EX void saveConfig() { if(vid.tc_depth > vid.tc_camera) pt_depth++; if(vid.tc_depth < vid.tc_camera) pt_camera++; if(vid.tc_depth > vid.tc_alpha ) pt_depth++; - if(vid.tc_depth < vid.tc_alpha ) pt_alpha ++; + if(vid.tc_depth < vid.tc_alpha ) pt_alpha++; if(vid.tc_alpha > vid.tc_camera) pt_alpha++; if(vid.tc_alpha < vid.tc_camera) pt_camera++; vid.tc_alpha = pt_alpha; @@ -2562,7 +2598,6 @@ EX void showJoyConfig() { #endif EX void projectionDialog() { - vid.tc_alpha = ticks; dialog::editNumber(vpconf.alpha, -5, 5, .1, 1, XLAT("projection distance"), XLAT("HyperRogue uses the Minkowski hyperboloid model internally. " @@ -2591,6 +2626,7 @@ EX void projectionDialog() { dialog::addItem(sphere ? "towards orthographic" : "towards Gans model", 'T'); dialog::add_action([] () { double d = 1.1; vpconf.alpha *= d; vpconf.scale *= d; dialog::get_ne().reset_str(); }); }; + dialog::get_di().reaction = [] { update_linked(vid.tc_alpha); }; } EX void menuitem_projection_distance(key_type key) { @@ -3154,7 +3190,6 @@ EX int config3 = addHook(hooks_configfile, 100, [] { ->editable(-5, 5, .1, "eye level", "", 'E') ->set_extra([] { dialog::get_di().dialogflags |= sm::CENTER; - vid.tc_camera = ticks; dialog::addHelp(XLAT("In the FPP mode, the camera will be set at this altitude (before applying shifts).")); @@ -3164,7 +3199,8 @@ EX int config3 = addHook(hooks_configfile, 100, [] { vid.auto_eye = !vid.auto_eye; geom3::do_auto_eye(); }); - }); + }) + ->set_reaction([] { update_linked(vid.tc_camera); }); param_b(vid.auto_eye, "auto-eyelevel", false); @@ -3250,7 +3286,6 @@ EX int config3 = addHook(hooks_configfile, 100, [] { param_f(vid.depth, parameter_names("depth", "3D depth"), 1) ->editable(0, 5, .1, "Ground level below the plane", "", 'd') ->set_extra([] { - vid.tc_depth = ticks; help = XLAT( "Ground level is actually an equidistant surface, " "%1 absolute units below the plane P. " @@ -3282,17 +3317,13 @@ EX int config3 = addHook(hooks_configfile, 100, [] { dialog::addHelp(help); }) ->set_reaction([] { - bool b = vid.tc_alpha < vid.tc_camera; - if(vid.tc_alpha >= vid.tc_depth) vid.tc_alpha = vid.depth - 1; - if(vid.tc_camera >= vid.tc_depth) vid.tc_camera = vid.depth - 1; - if(vid.tc_alpha == vid.tc_camera) (b ? vid.tc_alpha : vid.tc_camera)--; + update_linked(vid.tc_depth); geom3::apply_settings_light(); }); param_f(vid.camera, parameter_names("camera", "3D camera level"), 1) ->editable(0, 5, .1, "", "", 'c') ->modif([] (float_parameter* x) { x->menu_item_name = (GDIM == 2 ? "Camera level above the plane" : "Z shift"); }) ->set_extra([] { - vid.tc_camera = ticks; if(GDIM == 2) dialog::addHelp(XLAT( "Camera is placed %1 absolute units above a plane P in a three-dimensional " @@ -3309,7 +3340,10 @@ EX int config3 = addHook(hooks_configfile, 100, [] { dialog::addHelp(XLAT("Look from behind.")); if(GDIM == 3 && pmodel == mdPerspective) dialog::addBoolItem_action(XLAT("reduce if walls on the way"), vid.use_wall_radar, 'R'); - }); + }) + ->set_reaction([] { + update_linked(vid.tc_camera); + }); param_f(vid.wall_height, parameter_names("wall_height", "3D wall height"), .3) ->editable(0, 1, .1, "Height of walls", "", 'w') ->set_extra([] () { diff --git a/geometry.cpp b/geometry.cpp index b784b677..ab280630 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1011,21 +1011,9 @@ EX namespace geom3 { using namespace geom3; DEBBI(DF_INIT | DF_POLY | DF_GEOM, ("geom3::compute")); // tanh(depth) / tanh(camera) == pconf.alpha - invalid = ""; if(GDIM == 3 || flipped || changing_embedded_settings); - else if(vid.tc_alpha < vid.tc_depth && vid.tc_alpha < vid.tc_camera) - pconf.alpha = tan_auto(vid.depth) / tan_auto(vid.camera); - else if(vid.tc_depth < vid.tc_alpha && vid.tc_depth < vid.tc_camera) { - ld v = pconf.alpha * tan_auto(vid.camera); - if(hyperbolic && (v<1e-6-12 || v>1-1e-12)) invalid = XLAT("cannot adjust depth"), vid.depth = vid.camera; - else vid.depth = atan_auto(v); - } - else { - ld v = tan_auto(vid.depth) / pconf.alpha; - if(hyperbolic && (v<1e-12-1 || v>1-1e-12)) invalid = XLAT("cannot adjust camera"), vid.camera = vid.depth; - else vid.camera = atan_auto(v); - } + else adjust_linked(); if(fabs(pconf.alpha) < 1e-6) invalid = XLAT("does not work with perfect Klein"); diff --git a/models.cpp b/models.cpp index 537e8ce7..29dd0352 100644 --- a/models.cpp +++ b/models.cpp @@ -1078,6 +1078,7 @@ EX namespace models { p.alpha = 1; auto proj = param_custom_ld(p.alpha, sp+"projection", menuitem_projection_distance, 'p'); proj->help_text = "projection distance|Gans Klein Poincare orthographic stereographic"; + proj->reaction = [] { update_linked(vid.tc_alpha); }; } else { param_f(p.alpha, sp+"projection", 1);