From 58cf5d5641b2a764151be48bd802ceb7aa6aec1a Mon Sep 17 00:00:00 2001 From: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:02:21 -0800 Subject: [PATCH] Move MouseEntered to a queue, such that only the most recently hovered atom will be processed (#63567) bout The Pull Request MouseEntered currently fires multiple (multiple) times per frame, presumably over every atom that was hovered in some timeframe (though it appears to be much worse than that). This makes MouseEntered only add to a queue, while a per-tick subsystem ensures only the most recent MouseEntered gets the screentip work done on it, through a generic on_mouse_enter proc call. Contextual screen tips are coming and are going to make the screen tip code more computationally expensive, so slimming it down is going to be a must. Would like to hear from @LemonInTheDark if this makes any obvious difference in time dilation, since it of course won't be as easy as just checking MouseEntered overtime anymore. --- code/__DEFINES/subsystems.dm | 1 + code/controllers/subsystem/mouse_entered.dm | 23 +++++++++++++++++++++ code/game/atoms.dm | 14 ++++++++++--- code/modules/client/client_procs.dm | 1 + tgstation.dme | 1 + 5 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 code/controllers/subsystem/mouse_entered.dm diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index ae8be558fed..5c020c0f819 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -197,6 +197,7 @@ #define FIRE_PRIORITY_STATPANEL 390 #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_RUNECHAT 410 +#define FIRE_PRIORITY_MOUSE_ENTERED 450 #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_EXPLOSIONS 666 #define FIRE_PRIORITY_TIMER 700 diff --git a/code/controllers/subsystem/mouse_entered.dm b/code/controllers/subsystem/mouse_entered.dm new file mode 100644 index 00000000000..6dc8d995a52 --- /dev/null +++ b/code/controllers/subsystem/mouse_entered.dm @@ -0,0 +1,23 @@ +/// Defers MouseEntered inputs to only apply to the most recently hovered over atom in the tick +SUBSYSTEM_DEF(mouse_entered) + name = "MouseEntered" + wait = 1 + flags = SS_NO_INIT | SS_TICKER + priority = FIRE_PRIORITY_MOUSE_ENTERED + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + + var/list/hovers = list() + +/datum/controller/subsystem/mouse_entered/fire() + for (var/hovering_client in hovers) + var/atom/hovering_atom = hovers[hovering_client] + if (isnull(hovering_atom)) + continue + + hovering_atom.on_mouse_enter(hovering_client) + + // This intentionally runs `= null` and not `-= hovering_client`, as we want to prevent the list from shrinking, + // which could cause problems given the heat of MouseEntered. + // Lummox has teased this for 515: https://www.byond.com/forum/post/2621745 + // ...though you're most likely reading this on BYOND version 600. + hovers[hovering_client] = null diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 606f9bcf981..0a299188953 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -2079,11 +2079,19 @@ return TRUE -//Update the screentip to reflect what we're hoverin over /atom/MouseEntered(location, control, params) - . = ..() + SSmouse_entered.hovers[usr.client] = src + +/// Fired whenever this atom is the most recent to be hovered over in the tick. +/// Preferred over MouseEntered if you do not need information such as the position of the mouse. +/// Especially because this is deferred over a tick, do not trust that `client` is not null. +/atom/proc/on_mouse_enter(client/client) + SHOULD_NOT_SLEEP(TRUE) + + var/mob/user = client?.mob + // Screentips - var/datum/hud/active_hud = usr.hud_used + var/datum/hud/active_hud = user?.hud_used if(active_hud) if(!active_hud.screentips_enabled || (flags_1 & NO_SCREENTIPS_1)) active_hud.screentip_text.maptext = "" diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index a7721cdebd5..f94e5cc2bdb 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -539,6 +539,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( active_mousedown_item = null SSambience.remove_ambience_client(src) + SSmouse_entered.hovers -= src QDEL_NULL(view_size) QDEL_NULL(void) QDEL_NULL(tooltips) diff --git a/tgstation.dme b/tgstation.dme index ac1070cefdd..763fa762953 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -441,6 +441,7 @@ #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" #include "code\controllers\subsystem\moods.dm" +#include "code\controllers\subsystem\mouse_entered.dm" #include "code\controllers\subsystem\nightshift.dm" #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\overlays.dm"