diff --git a/code/_helpers/cmp.dm b/code/_helpers/cmp.dm index e84ecc341fc..32637fecad8 100644 --- a/code/_helpers/cmp.dm +++ b/code/_helpers/cmp.dm @@ -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) \ No newline at end of file + return cmp_name_or_type_asc(a, b) + +/proc/cmp_priority_list(list/A, list/B) + return A["priority"] - B["priority"] diff --git a/code/_helpers/visual_filters.dm b/code/_helpers/visual_filters.dm index deb7162f196..ad1fc910420 100644 --- a/code/_helpers/visual_filters.dm +++ b/code/_helpers/visual_filters.dm @@ -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)) @@ -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() diff --git a/code/modules/client/mouse_pointer/_mouse_pointer.dm b/code/modules/client/mouse_pointer/_mouse_pointer.dm new file mode 100644 index 00000000000..656c2542671 --- /dev/null +++ b/code/modules/client/mouse_pointer/_mouse_pointer.dm @@ -0,0 +1,70 @@ +/* + * Adds pointer entries to clients to allow for multiple sources wanting to modify the pointer 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_pointer) + if(isnull(new_pointer)) + new_pointer = initial(mouse_pointer_icon) + if(mouse_pointer_icon != new_pointer) + mouse_pointer_icon = new_pointer + world << "set mouse pointer to [new_pointer]" + return TRUE + return FALSE + +/client/proc/add_mouse_pointer(pointer_type, pointer_priority = 1, icon_index = 1) + + var/decl/mouse_pointer/pointer_decl = GET_DECL(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].") + + // Is an identical pointer already being tracked? + var/pointer_icon = pointer_decl.icons[icon_index] + if(pointer_type in _mouse_pointers) + var/list/comparing = _mouse_pointers[pointer_type] + if(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) + LAZYINITLIST(_mouse_pointers) + _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(!LAZYLEN(_mouse_pointers) || !_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() diff --git a/code/modules/client/mouse_pointer/mouse_pointer_definitions.dm b/code/modules/client/mouse_pointer/mouse_pointer_definitions.dm new file mode 100644 index 00000000000..4bc35336acb --- /dev/null +++ b/code/modules/client/mouse_pointer/mouse_pointer_definitions.dm @@ -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' diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index a2d7f65ab16..7903631bb68 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -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() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 7554d0e91f5..edf74c14dd0 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -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) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index c6b35aa2872..957cdba36a3 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -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 diff --git a/icons/effects/mouse_pointers/examine_pointer.dmi b/icons/effects/mouse_pointers/examine_pointer.dmi index 41a9cec13b0..a565a554fa7 100644 Binary files a/icons/effects/mouse_pointers/examine_pointer.dmi and b/icons/effects/mouse_pointers/examine_pointer.dmi differ diff --git a/nebula.dme b/nebula.dme index 7c4b88297fe..7de4fd80600 100644 --- a/nebula.dme +++ b/nebula.dme @@ -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"