Skip to content

Commit

Permalink
Adding a priority list system for mouse cursor icons.
Browse files Browse the repository at this point in the history
  • Loading branch information
MistakeNot4892 committed Dec 2, 2024
1 parent 95c5050 commit 7ac5722
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 13 deletions.
5 changes: 4 additions & 1 deletion code/_helpers/cmp.dm
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,7 @@
if(a == prerequisite)
return -1 // goes after
return cmp_skill_asc(a, GET_DECL(b.prerequisites[1]))
return cmp_name_or_type_asc(a, b)
return cmp_name_or_type_asc(a, b)

/proc/cmp_priority_list(list/A, list/B)
return A["priority"] - B["priority"]
5 changes: 1 addition & 4 deletions code/_helpers/visual_filters.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
/atom/movable
var/list/filter_data // For handling persistent filters

/proc/cmp_filter_data_priority(list/A, list/B)
return A["priority"] - B["priority"]

// Defining this for future proofing and ease of searching for erroneous usage.
/image/proc/add_filter(filter_name, priority, list/params)
filters += filter(arglist(params))
Expand Down Expand Up @@ -35,7 +32,7 @@

/atom/movable/proc/update_filters()
filters = null
filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE)
filter_data = sortTim(filter_data, /proc/cmp_priority_list, TRUE)
for(var/f in filter_data)
var/list/data = filter_data[f]
var/list/arguments = data.Copy()
Expand Down
67 changes: 67 additions & 0 deletions code/modules/client/mouse_pointer/_mouse_pointer.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Adds pointer entries to clients to allow for multiple sources wanting to modify the cursor at once.
* - add_mouse_pointer(pointer_type, pointer_priority, icon_index) will add or replace a pointer of the specified /decl/mouse_pointer type.
* - remove_mouse_pointer(pointer_type) will clear that entry.
* - Updates are handled automatically by adding/removing, other procs should not be used without a good reason.
*/

/client
VAR_PRIVATE/list/_mouse_pointers

/client/proc/clear_mouse_pointers()
if(LAZYLEN(_mouse_pointers))
LAZYCLEARLIST(_mouse_pointers)
update_mouse_pointer()
return TRUE
return FALSE

/client/proc/set_mouse_pointer_icon(new_cursor)
if(isnull(new_cursor))
new_cursor = initial(mouse_pointer_icon)
if(mouse_pointer_icon != new_cursor)
mouse_pointer_icon = new_cursor
return TRUE
return FALSE

/client/proc/add_mouse_pointer(pointer_type, pointer_priority = 1, icon_index = 1)

// Is an identical pointer already being tracked?
var/decl/mouse_pointer/pointer_decl = ispath(pointer_type) ? GET_DECL(pointer_type) : pointer_type
if(!isnum(icon_index) || icon_index < 1 || icon_index > length(pointer_decl.icons))
CRASH("Invalid icon_index passed to add_mouse_pointer() for [pointer_type].")

var/pointer_icon = pointer_decl.icons[icon_index]
var/list/comparing = _mouse_pointers?[pointer_type]
if(islist(comparing) && comparing["icon"] == pointer_icon && comparing["priority"] == pointer_priority)
return FALSE

// Update our list entry. If we have multiple pointers, sort by priority.
var/need_update = !(pointer_type in _mouse_pointers)
LAZYSET(_mouse_pointers, pointer_type, list("icon" = pointer_icon, "priority" = pointer_priority))
if(LAZYLEN(_mouse_pointers) > 1)
_mouse_pointers = sortTim(_mouse_pointers, /proc/cmp_priority_list, TRUE)
need_update = TRUE

// Refresh if needed.
if(need_update)
update_mouse_pointer()

/client/proc/remove_mouse_pointer(pointer_type)
if(!_mouse_pointers?[pointer_type])
return FALSE
var/current_pointer = _mouse_pointers[1]
LAZYREMOVE(_mouse_pointers, pointer_type)
if(pointer_type == current_pointer)
update_mouse_pointer()
return TRUE

/client/proc/update_mouse_pointer()
if(!LAZYLEN(_mouse_pointers))
return set_mouse_pointer_icon()
var/list/pointer = _mouse_pointers[_mouse_pointers[1]]
if(!islist(pointer))
return set_mouse_pointer_icon()
var/set_pointer = pointer["icon"]
if(isicon(set_pointer))
return set_mouse_pointer_icon(set_pointer)
return set_mouse_pointer_icon()
31 changes: 31 additions & 0 deletions code/modules/client/mouse_pointer/mouse_pointer_definitions.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/decl/mouse_pointer
abstract_type = /decl/mouse_pointer
/// Icon to set on the client for this cursor.
var/list/icons

/decl/mouse_pointer/Initialize()
. = ..()
if(icons && !islist(icons))
icons = list(icons)

/decl/mouse_pointer/validate()
. = ..()
if(length(icons))
var/static/list/check_states = list(
"",
"over",
"drag",
"drop",
"all"
)
for(var/icon in icons)
for(var/check_state in check_states)
if(!check_state_in_icon(check_state, icon))
. += "missing state '[check_state]' from icon '[icon]'"
else
. += "null or empty icon list"

// Subtypes for use in add_mouse_pointer() below.
/decl/mouse_pointer/examine
uid = "pointer_examine"
icons = 'icons/effects/mouse_pointers/examine_pointer.dmi'
1 change: 1 addition & 0 deletions code/modules/mob/login.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

/mob/Login()

client.clear_mouse_pointers() // in case we are transferring mobs.
global.player_list |= src
update_Login_details()
world.update_status()
Expand Down
9 changes: 4 additions & 5 deletions code/modules/mob/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1135,11 +1135,10 @@
/mob/proc/update_mouse_pointer()
if(!client)
return

client.mouse_pointer_icon = initial(client.mouse_pointer_icon)

if(examine_cursor_icon && client.keys_held["Shift"])
client.mouse_pointer_icon = examine_cursor_icon
if(client.keys_held["Shift"])
client.add_mouse_pointer(/decl/mouse_pointer/examine)
else
client.remove_mouse_pointer(/decl/mouse_pointer/examine)

/mob/keybind_face_direction(direction)
facedir(direction)
Expand Down
3 changes: 0 additions & 3 deletions code/modules/mob/mob_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@
*/
var/obj/screen/zone_selector/zone_sel = null

/// Cursor icon used when holding shift over things.
var/examine_cursor_icon = 'icons/effects/mouse_pointers/examine_pointer.dmi'

var/damageoverlaytemp = 0
var/obj/machinery/machine = null

Expand Down
Binary file modified icons/effects/mouse_pointers/examine_pointer.dmi
Binary file not shown.
2 changes: 2 additions & 0 deletions nebula.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,8 @@
#include "code\modules\client\preferences_spawnpoints.dm"
#include "code\modules\client\preferences_storage.dm"
#include "code\modules\client\preferences_toggle.dm"
#include "code\modules\client\mouse_pointer\_mouse_pointer.dm"
#include "code\modules\client\mouse_pointer\mouse_pointer_definitions.dm"
#include "code\modules\client\preference_setup\_defines.dm"
#include "code\modules\client\preference_setup\preference_setup.dm"
#include "code\modules\client\preference_setup\antagonism\01_candidacy.dm"
Expand Down

0 comments on commit 7ac5722

Please sign in to comment.