mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-27 05:57:24 +01:00
SSOverlays & Hover Inventory Indicator
This ports the hover inventory indicator from /tg/, and by necessity, SSOverlays. The hover inventory indicator basically shows where you are trying to put an item, and then shows an item ghost in red or green, giving visual feedback as to if that item will go in the slot or not. SSOverlays is a much broader system for managing overlays, which should eventually take over *all* overlays, but I have only ported the basic system and implemented it where necessary for it to work for the hover inventory items currently.
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
SUBSYSTEM_DEF(overlays)
|
||||
name = "Overlay"
|
||||
flags = SS_TICKER
|
||||
wait = 1
|
||||
priority = FIRE_PRIORITY_OVERLAYS
|
||||
init_order = INIT_ORDER_OVERLAY
|
||||
|
||||
var/list/queue
|
||||
var/list/stats
|
||||
var/list/overlay_icon_state_caches
|
||||
var/list/overlay_icon_cache
|
||||
|
||||
/datum/controller/subsystem/overlays/PreInit()
|
||||
overlay_icon_state_caches = list()
|
||||
overlay_icon_cache = list()
|
||||
queue = list()
|
||||
stats = list()
|
||||
|
||||
/datum/controller/subsystem/overlays/Initialize()
|
||||
initialized = TRUE
|
||||
fire(mc_check = FALSE)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/stat_entry()
|
||||
..("Ov:[length(queue)]")
|
||||
|
||||
/datum/controller/subsystem/overlays/Recover()
|
||||
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
|
||||
overlay_icon_cache = SSoverlays.overlay_icon_cache
|
||||
queue = SSoverlays.queue
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
|
||||
var/list/queue = src.queue
|
||||
var/static/count = 0
|
||||
if (count)
|
||||
var/c = count
|
||||
count = 0 //so if we runtime on the Cut, we don't try again.
|
||||
queue.Cut(1,c+1)
|
||||
|
||||
for (var/thing in queue)
|
||||
count++
|
||||
if(thing)
|
||||
var/atom/A = thing
|
||||
COMPILE_OVERLAYS(A)
|
||||
if(mc_check)
|
||||
if(MC_TICK_CHECK)
|
||||
break
|
||||
else
|
||||
CHECK_TICK
|
||||
|
||||
if (count)
|
||||
queue.Cut(1,count+1)
|
||||
count = 0
|
||||
|
||||
/proc/iconstate2appearance(icon, iconstate)
|
||||
var/static/image/stringbro = new()
|
||||
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
|
||||
var/list/cached_icon = icon_states_cache[icon]
|
||||
if (cached_icon)
|
||||
var/cached_appearance = cached_icon["[iconstate]"]
|
||||
if (cached_appearance)
|
||||
return cached_appearance
|
||||
stringbro.icon = icon
|
||||
stringbro.icon_state = iconstate
|
||||
if (!cached_icon) //not using the macro to save an associated lookup
|
||||
cached_icon = list()
|
||||
icon_states_cache[icon] = cached_icon
|
||||
var/cached_appearance = stringbro.appearance
|
||||
cached_icon["[iconstate]"] = cached_appearance
|
||||
return cached_appearance
|
||||
|
||||
/proc/icon2appearance(icon)
|
||||
var/static/image/iconbro = new()
|
||||
var/list/icon_cache = SSoverlays.overlay_icon_cache
|
||||
. = icon_cache[icon]
|
||||
if (!.)
|
||||
iconbro.icon = icon
|
||||
. = iconbro.appearance
|
||||
icon_cache[icon] = .
|
||||
|
||||
/atom/proc/build_appearance_list(old_overlays)
|
||||
var/static/image/appearance_bro = new()
|
||||
var/list/new_overlays = list()
|
||||
if (!islist(old_overlays))
|
||||
old_overlays = list(old_overlays)
|
||||
for (var/overlay in old_overlays)
|
||||
if(!overlay)
|
||||
continue
|
||||
if (istext(overlay))
|
||||
new_overlays += iconstate2appearance(icon, overlay)
|
||||
else if(isicon(overlay))
|
||||
new_overlays += icon2appearance(overlay)
|
||||
else
|
||||
if(isloc(overlay))
|
||||
var/atom/A = overlay
|
||||
if (A.flags_2 & OVERLAY_QUEUED_2)
|
||||
COMPILE_OVERLAYS(A)
|
||||
appearance_bro.appearance = overlay //this works for images and atoms too!
|
||||
if(!ispath(overlay))
|
||||
var/image/I = overlay
|
||||
appearance_bro.dir = I.dir
|
||||
new_overlays += appearance_bro.appearance
|
||||
return new_overlays
|
||||
|
||||
#define NOT_QUEUED_ALREADY (!(flags_2 & OVERLAY_QUEUED_2))
|
||||
#define QUEUE_FOR_COMPILE flags_2 |= OVERLAY_QUEUED_2; SSoverlays.queue += src;
|
||||
/atom/proc/cut_overlays(priority = FALSE)
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
LAZYINITLIST(add_overlays)
|
||||
remove_overlays = overlays.Copy()
|
||||
add_overlays.Cut()
|
||||
|
||||
if(priority)
|
||||
priority_overlays.Cut()
|
||||
|
||||
//If not already queued for work and there are overlays to remove
|
||||
if(NOT_QUEUED_ALREADY && remove_overlays.len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/cut_overlay(list/overlays, priority)
|
||||
if(!overlays)
|
||||
return
|
||||
overlays = build_appearance_list(overlays)
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/r_len = remove_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
remove_overlays += overlays
|
||||
add_overlays -= overlays
|
||||
|
||||
|
||||
if(priority)
|
||||
var/list/cached_priority = priority_overlays
|
||||
LAZYREMOVE(cached_priority, overlays)
|
||||
|
||||
var/fa_len = add_overlays.len
|
||||
var/fr_len = remove_overlays.len
|
||||
var/fp_len = priority_overlays.len
|
||||
|
||||
//If not already queued and there is work to be done
|
||||
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/add_overlay(list/overlays, priority = FALSE)
|
||||
if(!overlays)
|
||||
return
|
||||
|
||||
overlays = build_appearance_list(overlays)
|
||||
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
|
||||
if(priority)
|
||||
priority_overlays += overlays //or in the image. Can we use [image] = image?
|
||||
var/fp_len = priority_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fp_len != p_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
else
|
||||
add_overlays += overlays
|
||||
var/fa_len = add_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fa_len != a_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !LAZYLEN(overlays))
|
||||
remove_overlays = overlays
|
||||
add_overlays = cached_other
|
||||
if(NOT_QUEUED_ALREADY)
|
||||
QUEUE_FOR_COMPILE
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
|
||||
#undef NOT_QUEUED_ALREADY
|
||||
#undef QUEUE_FOR_COMPILE
|
||||
|
||||
//TODO: Better solution for these?
|
||||
/image/proc/add_overlay(x)
|
||||
overlays |= x
|
||||
|
||||
/image/proc/cut_overlay(x)
|
||||
overlays -= x
|
||||
|
||||
/image/proc/cut_overlays(x)
|
||||
overlays.Cut()
|
||||
|
||||
/image/proc/copy_overlays(atom/other, cut_old)
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !overlays.len)
|
||||
overlays = cached_other
|
||||
else
|
||||
overlays |= cached_other
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
Reference in New Issue
Block a user