From 1616fb2dcc58755f76dd41c48fdccdb248d3512c Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sat, 5 Mar 2022 20:06:29 -0800 Subject: [PATCH] Fit Viewport cleanup (#65225) * Fit Viewport cleanup Changes how Fit Viewport works slightly. From what I understand, the verb was created with the goal of eliminating the pixel hunting required to get rid of letterboxing. This works fine for stretch to fit, but ever since the command bar got nuked it's ended up creating a lot of blackspace for targeted zoom modes. I've changed how it decides on its optimal width slightly, if the client has a non stretch to fit zoom mode, we use it, the world icon size and the clients view size to figure out the exact width we want. The bars on the left and right have been bugging me forever. Want them gone. In light of this, I'm also making changing your zoom amount attempt to fit the viewport, if you have the pref enabled. Oh and I'm trying something with auto fit viewport stuff. It currently waits a second between view change and fitting. The comment implies this is to avoid winget strangeness from Login calls. When I blamed it, I found a commit from antruk talking about client dropping, and this being a potential fix. Unfortunately none wrote down what dropping means, and anturk's forgotten. I'm making the assumption that it's related to attempting the related winsets before an inital login is over. I might be wrong about this, if I am we'll know what went wrong I suppose. * Whoops, this needs to be invoke async * Ensures client safety, autodocs code, adds proper cleanup --- code/datums/view.dm | 26 ++++++++++++++++++++--- code/modules/client/client_defines.dm | 3 +++ code/modules/client/client_procs.dm | 4 ++-- code/modules/client/verbs/ooc.dm | 30 +++++++++++++++++++++------ 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/code/datums/view.dm b/code/datums/view.dm index 860ccb8bf1f..dffbc90a4f2 100644 --- a/code/datums/view.dm +++ b/code/datums/view.dm @@ -1,10 +1,23 @@ //This is intended to be a full wrapper. DO NOT directly modify its values ///Container for client viewsize /datum/view_data + /// Width offset to apply to the default view string if we're not supressed for some reason var/width = 0 + /// Height offset to apply to the default view string, see above var/height = 0 + /// This client's current "default" view, in the format "WidthxHeight" + /// We add/remove from this when we want to change their window size var/default = "" + /// This client's current zoom level, if it's not being supressed + /// If it's 0, we autoscale to the size of the window. Otherwise it's treated as the ratio between + /// the pixels on the map and output pixels. Only looks proper nice in increments of whole numbers (iirc) + /// Stored here so other parts of the code have a non blocking way of getting a user's functional zoom + var/zoom = 0 + /// If the view is currently being supressed by some other "monitor" + /// For when you want to own the client's eye without fucking with their viewport + /// Doesn't make sense for a binocoler to effect your view in a camera console var/is_suppressed = FALSE + /// The client that owns this view packet var/client/chief = null /datum/view_data/New(client/owner, view_string) @@ -12,6 +25,10 @@ chief = owner apply() +/datum/view_data/Destroy() + chief = null + return ..() + /datum/view_data/proc/setDefault(string) default = string apply() @@ -24,12 +41,15 @@ /datum/view_data/proc/assertFormat()//T-Pose winset(chief, "mapwindow.map", "zoom=0") + zoom = 0 /datum/view_data/proc/resetFormat()//Cuck - winset(chief, "mapwindow.map", "zoom=[chief.prefs.read_preference(/datum/preference/numeric/pixel_size)]") + zoom = chief?.prefs.read_preference(/datum/preference/numeric/pixel_size) + winset(chief, "mapwindow.map", "zoom=[zoom]") + chief?.attempt_auto_fit_viewport() // If you change zoom mode, fit the viewport /datum/view_data/proc/setZoomMode() - winset(chief, "mapwindow.map", "zoom-mode=[chief.prefs.read_preference(/datum/preference/choiced/scaling_method)]") + winset(chief, "mapwindow.map", "zoom-mode=[chief?.prefs.read_preference(/datum/preference/choiced/scaling_method)]") /datum/view_data/proc/isZooming() return (width || height) @@ -78,7 +98,7 @@ apply() /datum/view_data/proc/apply() - chief.change_view(getView()) + chief?.change_view(getView()) safeApplyFormat() /datum/view_data/proc/supress() diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index de58ddfb8c9..fe324b6d665 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -251,3 +251,6 @@ /// Whether or not this client has the combo HUD enabled var/combo_hud_enabled = FALSE + + /// If this client has been fully initialized or not + var/fully_created = FALSE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 11d669cef6b..d3628060cdc 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -488,6 +488,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( view_size.setZoomMode() Master.UpdateTickRate() SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CLIENT_CONNECT, src) + fully_created = TRUE ////////////// //DISCONNECT// @@ -1039,8 +1040,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if (isliving(mob)) var/mob/living/M = mob M.update_damage_hud() - if (prefs.read_preference(/datum/preference/toggle/auto_fit_viewport)) - addtimer(CALLBACK(src,.verb/fit_viewport,10)) //Delayed to avoid wingets from Login calls. + attempt_auto_fit_viewport() /client/proc/generate_clickcatcher() if(!void) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index d8eaa5c4c78..a8932c107b3 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -359,13 +359,23 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") var/list/map_size = splittext(sizes["mapwindow.size"], "x") - // Looks like we expect mapwindow.size to be "ixj" where i and j are numbers. - // If we don't get our expected 2 outputs, let's give some useful error info. - if(length(map_size) != 2) - CRASH("map_size of incorrect length --- map_size var: [map_size] --- map_size length: [length(map_size)]") + // Gets the type of zoom we're currently using from our view datum + // If it's 0 we do our pixel calculations based off the size of the mapwindow + // If it's not, we already know how big we want our window to be, since zoom is the exact pixel ratio of the map + var/zoom_value = src.view_size?.zoom || 0 + + var/desired_width = 0 + if(zoom_value) + desired_width = round(view_size[1] * zoom_value * world.icon_size) + else + + // Looks like we expect mapwindow.size to be "ixj" where i and j are numbers. + // If we don't get our expected 2 outputs, let's give some useful error info. + if(length(map_size) != 2) + CRASH("map_size of incorrect length --- map_size var: [map_size] --- map_size length: [length(map_size)]") + var/height = text2num(map_size[2]) + desired_width = round(height * aspect_ratio) - var/height = text2num(map_size[2]) - var/desired_width = round(height * aspect_ratio) if (text2num(map_size[1]) == desired_width) // Nothing to do return @@ -401,6 +411,14 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") pct += delta winset(src, "mainwindow.split", "splitter=[pct]") +/// Attempt to automatically fit the viewport, assuming the user wants it +/client/proc/attempt_auto_fit_viewport() + if (!prefs.read_preference(/datum/preference/toggle/auto_fit_viewport)) + return + if(fully_created) + INVOKE_ASYNC(src, .verb/fit_viewport) + else //Delayed to avoid wingets from Login calls. + addtimer(CALLBACK(src, .verb/fit_viewport, 1 SECONDS)) /client/verb/policy() set name = "Show Policy"