Skip to content

Commit

Permalink
lays
Browse files Browse the repository at this point in the history
  • Loading branch information
NPC1314 committed Dec 16, 2024
1 parent a162a30 commit 6c3fa96
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 184 deletions.
16 changes: 7 additions & 9 deletions code/__DEFINES/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,19 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define CONDUCT_1 (1<<5)
/// For machines and structures that should not break into parts, eg, holodeck stuff
#define NODECONSTRUCT_1 (1<<7)
/// atom queued to SSoverlay
#define OVERLAY_QUEUED_1 (1<<8)
/// item has priority to check when entering or leaving
#define ON_BORDER_1 (1<<9)
#define ON_BORDER_1 (1<<8)
/// Prevent clicking things below it on the same turf eg. doors/ fulltile windows
#define PREVENT_CLICK_UNDER_1 (1<<11)
#define HOLOGRAM_1 (1<<12)
#define PREVENT_CLICK_UNDER_1 (1<<9)
#define HOLOGRAM_1 (1<<10)
/// TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define TESLA_IGNORE_1 (1<<13)
#define TESLA_IGNORE_1 (1<<11)
///Whether /atom/Initialize() has already run for the object
#define INITIALIZED_1 (1<<14)
#define INITIALIZED_1 (1<<12)
/// was this spawned by an admin? used for stat tracking stuff.
#define ADMIN_SPAWNED_1 (1<<15)
#define ADMIN_SPAWNED_1 (1<<13)
/// should not get harmed if this gets caught by an explosion?
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16)
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<14)

//turf-only flags
#define NOJAUNT_1 (1<<0)
Expand Down
6 changes: 1 addition & 5 deletions code/__DEFINES/stat_tracking.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
#define STAT_LOG_ENTRY(entrylist, entryname) \
var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH));\
STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME;\
var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT));\
if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) {\
STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT;\
};\

STAT_ENTRY[STAT_ENTRY_COUNT] += 1;


40 changes: 18 additions & 22 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -195,29 +195,25 @@


//! ## Overlays subsystem
// A reasonable number of maximum overlays an object needs
// If you think you need more, rethink it
#define MAX_ATOM_OVERLAYS 200

///Compile all the overlays for an atom from the cache lists
#define COMPILE_OVERLAYS(A)\
do {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(rm)){\
A.overlays -= rm;\
rm.Cut();\
}\
if(LAZYLEN(ad)){\
A.overlays |= ad;\
ad.Cut();\
}\
if(LAZYLEN(po)){\
A.overlays |= po;\
}\
for(var/I in A.alternate_appearances){\
var/datum/atom_hud/alternate_appearance/AA = A.alternate_appearances[I];\
#define POST_OVERLAY_CHANGE(changed_on) \
if(length(changed_on.overlays) >= MAX_ATOM_OVERLAYS) { \
var/text_lays = overlays2text(changed_on.overlays); \
stack_trace("Too many overlays on [changed_on.type] - [length(changed_on.overlays)], refusing to update and cutting.\
\n What follows is a printout of all existing overlays at the time of the overflow \n[text_lays]"); \
changed_on.overlays.Cut(); \
changed_on.add_overlay(mutable_appearance('icons/testing/greyscale_error.dmi')); \
} \
if(alternate_appearances) { \
for(var/I in changed_on.alternate_appearances){\
var/datum/atom_hud/alternate_appearance/AA = changed_on.alternate_appearances[I];\
if(AA.transfer_overlays){\
AA.copy_overlays(A, TRUE);\
AA.copy_overlays(changed_on, TRUE);\
}\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
} while (FALSE)
} \
}

1 change: 0 additions & 1 deletion code/__HELPERS/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,6 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing")
for(var/D in showDirs)
body.setDir(D)
COMPILE_OVERLAYS(body)
var/icon/partial = getFlatIcon(body)
out_icon.Insert(partial,dir=D)

Expand Down
1 change: 0 additions & 1 deletion code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ GLOBAL_LIST_INIT(bitfields, list(
"CONDUCT_1" = CONDUCT_1,
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
"NODECONSTRUCT_1" = NODECONSTRUCT_1,
"OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
"ON_BORDER_1" = ON_BORDER_1,
"NO_RUINS_1" = NO_RUINS_1,
"PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
Expand Down
192 changes: 61 additions & 131 deletions code/controllers/subsystem/overlays.dm
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
wait = 1
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY

var/list/queue
flags = SS_NO_FIRE|SS_NO_INIT
var/list/stats
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
Expand All @@ -14,56 +9,29 @@ SUBSYSTEM_DEF(overlays)
/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/Shutdown()
text2file(render_stats(stats), "[GLOB.log_directory]/overlay.log")


/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)
STAT_START_STOPWATCH
var/atom/A = thing
COMPILE_OVERLAYS(A)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(stats, A.type)
if(count >= amt2process)
break
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK

if (count)
queue.Cut(1,count+1)
count = 0
/// Converts an overlay list into text for debug printing
/// Of note: overlays aren't actually mutable appearances, they're just appearances
/// Don't have access to that type tho, so this is the best you're gonna get
/proc/overlays2text(list/overlays)
var/list/unique_overlays = list()
// As anything because we're basically doing type coercion, rather then actually filtering for mutable appearances
for(var/mutable_appearance/overlay as anything in overlays)
var/key = "[overlay.icon]-[overlay.icon_state]-[overlay.dir]"
unique_overlays[key] += 1
var/list/output_text = list()
for(var/key in unique_overlays)
output_text += "([key]) = [unique_overlays[key]]"
return output_text.Join("\n")

/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
Expand Down Expand Up @@ -91,109 +59,71 @@ SUBSYSTEM_DEF(overlays)
. = 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)
/atom/proc/build_appearance_list(build_overlays)
if (!islist(build_overlays))
build_overlays = list(build_overlays)
for (var/overlay in build_overlays)
if(!overlay)
build_overlays -= overlay
continue
if (istext(overlay))
new_overlays += iconstate2appearance(icon, overlay)
build_overlays -= overlay
build_overlays += iconstate2appearance(icon, overlay)
else if(isicon(overlay))
new_overlays += icon2appearance(overlay)
else
if(isloc(overlay))
var/atom/A = overlay
if (A.flags_1 & OVERLAY_QUEUED_1)
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
build_overlays -= overlay
build_overlays += icon2appearance(overlay)
return build_overlays

#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; 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)
/atom/proc/cut_overlays()
STAT_START_STOPWATCH
overlays = null
POST_OVERLAY_CHANGE(src)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(SSoverlays.stats, type)

/atom/proc/cut_overlay(list/remove_overlays)
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)
STAT_START_STOPWATCH
overlays -= build_appearance_list(remove_overlays)
POST_OVERLAY_CHANGE(src)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(SSoverlays.stats, type)

/atom/proc/add_overlay(list/add_overlays)
if(!overlays)
return
STAT_START_STOPWATCH
overlays += build_appearance_list(add_overlays)
POST_OVERLAY_CHANGE(src)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(SSoverlays.stats, type)

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
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
if(cut_old)
cut_overlays()
return

STAT_START_STOPWATCH
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()
if(cut_old)
if(cached_other)
overlays = cached_other
else
overlays = null
POST_OVERLAY_CHANGE(src)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(SSoverlays.stats, type)
else if(cached_other)
overlays += cached_other
POST_OVERLAY_CHANGE(src)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(SSoverlays.stats, type)



#undef NOT_QUEUED_ALREADY
#undef QUEUE_FOR_COMPILE
Expand Down
3 changes: 0 additions & 3 deletions code/controllers/subsystem/timer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -470,9 +470,6 @@ SUBSYSTEM_DEF(timer)
if (wait < 0)
stack_trace("addtimer called with a negative wait. Converting to [world.tick_lag]")

if (callback.object != GLOBAL_PROC && QDELETED(callback.object) && !QDESTROYING(callback.object))
stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not be supported and may refuse to run or run with a 0 wait")

wait = max(CEILING(wait, world.tick_lag), world.tick_lag)

if(wait >= INFINITY)
Expand Down
10 changes: 7 additions & 3 deletions code/game/objects/inhands_rogue.dm
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@
var/icon/blended
var/skipoverlays = FALSE
if(behind)
var/icon/J = new(icon)
var/list/istates = J.IconStates()
if(istates.Find("[icon_state]_behind"))
if(!(icon in GLOB.IconStates_cache))
var/icon/J = new(icon)
var/list/istates = J.IconStates()
GLOB.IconStates_cache |= icon
GLOB.IconStates_cache[icon] = istates

if("[icon_state]_behind" in GLOB.IconStates_cache[icon])
blended=icon("icon"=icon, "icon_state"="[icon_state]_behind")
skipoverlays = TRUE
else
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
inhand_y_dimension = 32
update_transform()

GLOBAL_LIST_INIT(IconStates_cache, list())

/obj/item/proc/update_transform()
transform = null
Expand Down
Loading

0 comments on commit 6c3fa96

Please sign in to comment.