From: k9er Date: Sun, 19 Jan 2025 18:54:07 +0000 (+0000) Subject: Implement zoom scrolling X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d500b0a3be7b37e21f5e49f0798c2a934f9596fc;p=xonotic%2Fxonotic-data.pk3dir.git Implement zoom scrolling --- diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 568f0f5a0..54299e524 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -493,6 +493,10 @@ float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary) if (override) return true; + override |= View_InputEvent(bInputType, nPrimary, nSecondary); + if (override) + return true; + override |= HUD_Panel_Chat_InputEvent(bInputType, nPrimary, nSecondary); override |= QuickMenu_InputEvent(bInputType, nPrimary, nSecondary); diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index 583f167dc..4911dc416 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -421,22 +421,9 @@ STATIC_INIT(fpscounter_init) showfps_prevfps_time = currentTime; // we must initialize it to avoid an instant low frame sending } -float avgspeed; -vector GetCurrentFov(float fov) +bool IsZooming() { - float zoomsensitivity, zoomspeed, zoomfactor, zoomdir; - float velocityzoom, curspeed; - vector v; - - zoomsensitivity = autocvar_cl_zoomsensitivity; - zoomfactor = autocvar_cl_zoomfactor; - if(zoomfactor < 1 || zoomfactor > 30) - zoomfactor = 2.5; - zoomspeed = autocvar_cl_zoomspeed; - if (zoomspeed >= 0 && (zoomspeed < 0.5 || zoomspeed > 16)) - zoomspeed = 3.5; - - zoomdir = button_zoom; + bool zoomdir = button_zoom; if(hud == HUD_NORMAL && !spectatee_status) { @@ -453,38 +440,109 @@ vector GetCurrentFov(float fov) } } } - if(spectatee_status > 0 || isdemo()) + + if(spectatorbutton_zoom && (spectatee_status > 0 || isdemo())) + zoomdir = !zoomdir; + + return zoomdir; +} + +const float MAX_ZOOMFACTOR = 30; +float zoomscroll_factor; +float zoomscroll_factor_target; +void ZoomScroll(float nPrimary) +{ + bool zoomin = (nPrimary == K_MWHEELUP); + if (autocvar_cl_zoomscroll_scale < 0) + zoomin = !zoomin; + + // allow negatives so that players can scroll the other way, biggest change allowed is +100% + float zoomscroll_scale = 1 + min(fabs(autocvar_cl_zoomscroll_scale), 1); + + if (zoomin) + zoomscroll_factor_target = min(MAX_ZOOMFACTOR, zoomscroll_factor_target * zoomscroll_scale); + else + zoomscroll_factor_target = max(1, zoomscroll_factor_target / zoomscroll_scale); +} + +bool View_InputEvent(int bInputType, float nPrimary, float nSecondary) +{ + if (bInputType == 2 || bInputType == 3) + return false; + + // at this point bInputType can only be 0 or 1 (key pressed or released) + bool key_pressed = (bInputType == 0); + + if (nPrimary == K_MWHEELUP || nPrimary == K_MWHEELDOWN) { - if(spectatorbutton_zoom) - { - if(zoomdir) - zoomdir = 0; - else - zoomdir = 1; - } - // fteqcc failed twice here already, don't optimize this + if (!autocvar_cl_zoomscroll || autocvar_cl_zoomscroll_scale == 0) + return false; // zoom scroll disabled + if (!IsZooming()) + return false; + if (key_pressed) + ZoomScroll(nPrimary); + return true; } - if(zoomdir) { zoomin_effect = 0; } + return false; +} + +float avgspeed; +vector GetCurrentFov(float fov) +{ + float zoomsensitivity, zoomspeed, zoomfactor, zoomdir; + float velocityzoom, curspeed; + vector v; + + zoomdir = IsZooming(); + + zoomspeed = autocvar_cl_zoomspeed; + if(zoomspeed >= 0 && (zoomspeed < 0.5 || zoomspeed > 16)) + zoomspeed = 3.5; + zoomsensitivity = autocvar_cl_zoomsensitivity; + + zoomfactor = autocvar_cl_zoomfactor; + if(zoomfactor < 1 || zoomfactor > MAX_ZOOMFACTOR) + zoomfactor = 2.5; + + if(zoomdir) + zoomin_effect = 0; if (spectatee_status > 0 && STAT(CAMERA_SPECTATOR) == 2) - { current_viewzoom = 1; - } else if (camera_active) - { current_viewzoom = min(1, current_viewzoom + drawframetime); - } else if(autocvar_cl_spawnzoom && zoomin_effect) { - float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, 30); + float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, MAX_ZOOMFACTOR); current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime); current_viewzoom = bound(1 / spawnzoomfactor, current_viewzoom, 1); - if(current_viewzoom == 1) { zoomin_effect = 0; } + if(current_viewzoom == 1) + zoomin_effect = 0; } else { + // initialize zoom scroll in the first frame / reset zoom scroll when fully zoomed out + if (!zoomscroll_factor || (current_viewzoom == 1 && !zoomdir)) + { + zoomscroll_factor_target = zoomfactor; + zoomscroll_factor = zoomfactor; + } + if (zoomscroll_factor != zoomscroll_factor_target) + { + if (fabs(zoomscroll_factor - zoomscroll_factor_target) < 0.001 || autocvar_cl_zoomscroll_speed < 0) // snap + zoomscroll_factor = zoomscroll_factor_target; + else if (autocvar_cl_zoomscroll_speed != 0) + { + // NOTE: this averaging formula is frametime independent + float avg_time = 1 / autocvar_cl_zoomscroll_speed; + float frac = 1 - exp(-drawframetime / max(0.001, avg_time)); + zoomscroll_factor = frac * zoomscroll_factor_target + (1 - frac) * zoomscroll_factor; + } + } + zoomfactor = zoomscroll_factor; + if(zoomspeed < 0) // instant zoom { if(zoomdir) diff --git a/qcsrc/client/view.qh b/qcsrc/client/view.qh index cd33ebfb6..6e370da73 100644 --- a/qcsrc/client/view.qh +++ b/qcsrc/client/view.qh @@ -32,6 +32,9 @@ float autocvar_cl_velocityzoom_time; float autocvar_cl_zoomfactor; float autocvar_cl_zoomsensitivity; float autocvar_cl_zoomspeed; +bool autocvar_cl_zoomscroll = 1; +float autocvar_cl_zoomscroll_scale = 0.2; +float autocvar_cl_zoomscroll_speed = 16; float autocvar_fov; float autocvar_hud_colorflash_alpha; bool autocvar_hud_contents; @@ -127,3 +130,5 @@ float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power; float intermission_time; float game_stopped_time; + +bool View_InputEvent(int bInputType, float nPrimary, float nSecondary); diff --git a/qcsrc/menu/xonotic/dialog_settings_game_view.qc b/qcsrc/menu/xonotic/dialog_settings_game_view.qc index b4c170280..5e667aa1c 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_view.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_view.qc @@ -95,6 +95,30 @@ void XonoticGameViewSettingsTab_fill(entity me) me.TD(me, 1, 1, e = makeXonoticTextLabel(0, ZCTX(_("ZOOM^Zoom sensitivity:")))); me.TD(me, 1, 2, e = makeXonoticSlider_T(0, 1, 0.1, "cl_zoomsensitivity", _("How zoom changes sensitivity, from 0 (lower sensitivity) to 1 (no sensitivity change)"))); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_zoomscroll", _("Zoom scrolling"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Scale:"))); + setDependent(e, "cl_zoomscroll", 1, 1); + me.TD(me, 1, 2, e = makeXonoticSlider(-1, 1, 0.1, "cl_zoomscroll_scale")); // would be better if this could skip 0 + setDependent(e, "cl_zoomscroll", 1, 1); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Speed:"))); + setDependent(e, "cl_zoomscroll", 1, 1); + me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_zoomscroll_speed")); + e.addValue(e, "2", "2"); // Samual: for() loop doesn't work here, even though it would make sense. + e.addValue(e, "4", "4"); + e.addValue(e, "6", "6"); + e.addValue(e, "8", "8"); + e.addValue(e, "10", "10"); + e.addValue(e, "12", "12"); + e.addValue(e, "14", "14"); + e.addValue(e, "16", "16"); + e.addValue(e, ZCTX(_("ZOOM^Instant")), "-1"); + e.configureXonoticTextSliderValues(e); + setDependent(e, "cl_zoomscroll", 1, 1); me.TR(me); me.TR(me); me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "cl_velocityzoom_enabled", _("Velocity zoom"))); diff --git a/xonotic-client.cfg b/xonotic-client.cfg index 5b620f007..e85cecc61 100644 --- a/xonotic-client.cfg +++ b/xonotic-client.cfg @@ -61,6 +61,9 @@ seta cl_spawnzoom_factor 2 "factor of zoom while spawning" seta cl_zoomfactor 5 "how much +zoom will zoom (1-30)" seta cl_zoomspeed 8 "how fast +zoom will zoom (0.5-16), negative values mean instant zoom" seta cl_zoomsensitivity 0 "how zoom changes sensitivity; \"0\" = weakest, \"1\" = strongest" +seta cl_zoomscroll 1 "allow scrolling to zoom in or out further while holding +zoom" +seta cl_zoomscroll_scale 0.2 "percentage of zoom change on scroll (maximum 1, negative values change the scroll direction)" +seta cl_zoomscroll_speed 16 "zoom scroll speed, negative values mean instant change when scrolling" seta cl_unpress_zoom_on_spawn 1 "automatically unpress zoom when you spawn" seta cl_unpress_zoom_on_death 1 "automatically unpress zoom when you die (and don't allow zoom again while dead)"