From 1eb15390d7e9f1ad98f059ac945d05bdb7ac9a31 Mon Sep 17 00:00:00 2001 From: Evildragon Date: Wed, 10 Apr 2024 14:02:53 +0900 Subject: [PATCH] view fix port --- code/__byond_version_compat.dm | 4 +++ 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 | 39 ++++++++++++++++++++++++--- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/code/__byond_version_compat.dm b/code/__byond_version_compat.dm index b9b454db721aa..0b6ff6cad451e 100644 --- a/code/__byond_version_compat.dm +++ b/code/__byond_version_compat.dm @@ -42,6 +42,8 @@ #if DM_VERSION < 515 /// Call by name proc reference, checks if the proc exists on this type or as a global proc #define PROC_REF(X) (.proc/##X) +/// Call by name verb reference, checks if the proc exists on this type or as a global verb +#define VERB_REF(X) (.verb/##X) /// Call by name proc reference, checks if the proc exists on given type or as a global proc #define TYPE_PROC_REF(TYPE, X) (##TYPE.proc/##X) /// Call by name verb reference, checks if the verb exists on given type or as a global verb @@ -51,6 +53,8 @@ #else /// Call by name proc reference, checks if the proc exists on this type or as a global proc #define PROC_REF(X) (nameof(.proc/##X)) +/// Call by name verb references, checks if the proc exists on this type or as a global verb +#define VERB_REF(X) (nameof(.verb/##X)) /// Call by name proc reference, checks if the proc exists on given type or as a global proc #define TYPE_PROC_REF(TYPE, X) (nameof(##TYPE.proc/##X)) /// Call by name verb reference, checks if the verb exists on given type or as a global verb diff --git a/code/datums/view.dm b/code/datums/view.dm index 7cc142149aecb..1996ce38e9742 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/viewData + /// 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/viewData/New(client/owner, view_string) @@ -12,6 +25,10 @@ chief = owner apply() +/datum/viewData/Destroy() + chief = null + return ..() + /datum/viewData/proc/setDefault(string) default = string apply() @@ -24,12 +41,15 @@ /datum/viewData/proc/assertFormat()//T-Pose winset(chief, "mapwindow.map", "zoom=0") + zoom = 0 /datum/viewData/proc/resetFormat() - winset(chief, "mapwindow.map", "zoom=[chief.prefs.read_player_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/viewData/proc/setZoomMode() - winset(chief, "mapwindow.map", "zoom-mode=[chief.prefs.read_player_preference(/datum/preference/choiced/scaling_method)]") + winset(chief, "mapwindow.map", "zoom-mode=[chief?.prefs.read_preference(/datum/preference/choiced/scaling_method)]") /datum/viewData/proc/isZooming() return (width || height) @@ -80,7 +100,7 @@ apply() /datum/viewData/proc/apply() - chief.change_view(getView()) + chief?.change_view(getView()) safeApplyFormat() /datum/viewData/proc/supress() diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index d0543a335f72e..0635927001b80 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -8,6 +8,9 @@ //ADMIN THINGS// //////////////// + /// If this client has been fully initialized or not + var/fully_created = FALSE + /// The admin state of the client. If this is null, the client is not an admin. var/datum/admins/holder = null var/datum/click_intercept = null // Needs to implement InterceptClickOn(user,params,atom) proc diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index be4056cfa17e3..511ee095a3530 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -493,6 +493,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( //Load the TGUI stat in case of TGUI subsystem not ready (startup) mob.UpdateMobStat(TRUE) + fully_created = TRUE /client/proc/time_to_redirect() var/redirect_address = CONFIG_GET(string/redirect_address) @@ -1045,8 +1046,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if (isliving(mob)) var/mob/living/M = mob M.update_damage_hud() - if (prefs?.read_player_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 3c5274ac23ab7..55f0306eb15e5 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -239,7 +239,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") SSticker.show_roundend_report(src, TRUE) /client/verb/fit_viewport() - set name = "Fit Viewport" + set name = "Fit Viewport asdfasdf" set category = "OOC" set desc = "Fit the width of the map window to match the viewport" @@ -249,9 +249,31 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") // Calculate desired pixel width using window size and aspect ratio var/sizes = params2list(winget(src, "mainwindow.split;mapwindow", "size")) - var/map_size = splittext(sizes["mapwindow.size"], "x") - var/height = text2num(map_size[2]) - var/desired_width = round(height * aspect_ratio) + + // Client closed the window? Some other error? This is unexpected behaviour, let's + // CRASH with some info. + if(!sizes["mapwindow.size"]) + CRASH("sizes does not contain mapwindow.size key. This means a winget failed to return what we wanted. --- sizes var: [sizes] --- sizes length: [length(sizes)]") + + var/list/map_size = splittext(sizes["mapwindow.size"], "x") + + // 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) + if (text2num(map_size[1]) == desired_width) // Nothing to do return @@ -284,6 +306,15 @@ 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_REF(fit_viewport)) + else //Delayed to avoid wingets from Login calls. + addtimer(CALLBACK(src, VERB_REF(fit_viewport), 1 SECONDS)) + /client/verb/view_runtimes_minimal() set name = "View Minimal Runtimes" set category = "OOC"