Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PORT] Optimizes /proc/icon_exists() #5306

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions code/__HELPERS/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1465,28 +1465,37 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects)
animate(pixel_x = initialpixelx + rand(-pixelshiftx,pixelshiftx), pixel_y = initialpixely + rand(-pixelshifty,pixelshifty), time = shake_interval)
animate(pixel_x = initialpixelx, pixel_y = initialpixely, time = shake_interval)

///Checks if the given iconstate exists in the given file, caching the result. Setting scream to TRUE will print a stack trace ONCE.
/proc/icon_exists(file, state, scream)
/// Checks whether a given icon state exists in a given icon file. If `file` and `state` both exist,
/// this will return `TRUE` - otherwise, it will return `FALSE`.
///
/// If you want a stack trace to be output when the given state/file doesn't exist, use
/// `/proc/icon_exists_or_scream()`.
/proc/icon_exists(file, state)
var/static/list/icon_states_cache = list()
if(icon_states_cache[file]?[state])
return TRUE

if(icon_states_cache[file]?[state] == FALSE)
return FALSE

var/list/states = icon_states(file)
if(isnull(file) || isnull(state))
return FALSE //This is common enough that it shouldn't panic, imo.

if(!icon_states_cache[file])
if(isnull(icon_states_cache[file]))
icon_states_cache[file] = list()
for(var/istate in icon_states(file))
icon_states_cache[file][istate] = TRUE

return !isnull(icon_states_cache[file][state])

if(state in states)
icon_states_cache[file][state] = TRUE
/// Functions the same as `/proc/icon_exists()`, but with the addition of a stack trace if the
/// specified file or state doesn't exist.
///
/// Stack traces will only be output once for each file.
/proc/icon_exists_or_scream(file, state)
if(icon_exists(file, state))
return TRUE
else
icon_states_cache[file][state] = FALSE
if(scream)
stack_trace("Icon Lookup for state: [state] in file [file] failed.")
return FALSE

var/static/list/screams = list()
if(!isnull(screams[file]))
screams[file] = TRUE
stack_trace("State [state] in file [file] does not exist.")

return FALSE

/// Cache of the width and height of icon files, to avoid repeating the same expensive operation
GLOBAL_LIST_EMPTY(icon_dimensions)
Expand Down
2 changes: 1 addition & 1 deletion code/__HELPERS/lighting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

//Test to make sure emissives with broken or missing icon states are created
if(PERFORM_ALL_TESTS(focus_only/invalid_emissives))
if(icon_state && !icon_exists(icon, icon_state, scream = FALSE)) //Scream set to False so we can have a custom stack_trace
if(icon_state && !icon_exists(icon, icon_state)) //Scream set to False so we can have a custom stack_trace
stack_trace("An emissive appearance was added with non-existant icon_state \"[icon_state]\" in [icon]!")

return appearance
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/hud/parallax.dm
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
var/newstate = initial(L.icon_state)
var/T = PARALLAX_LOOP_TIME / L.speed

if (newstate in icon_states(L.icon))
if (icon_exists(L.icon, newstate)) //MONKESTATION EDIT - Refactored to `icon_exists`.
L.icon_state = newstate
L.update_o(C.view)

Expand Down
3 changes: 1 addition & 2 deletions code/controllers/subsystem/overlays.dm
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ SUBSYSTEM_DEF(overlays)
if (istext(overlay))
// This is too expensive to run normally but running it during CI is a good test
if (PERFORM_ALL_TESTS(focus_only/invalid_overlays))
var/list/icon_states_available = icon_states(icon)
if(!(overlay in icon_states_available))
if(!icon_exists(icon, overlay))
var/icon_file = "[icon]" || "Unknown Generated Icon"
stack_trace("Invalid overlay: Icon object '[icon_file]' [REF(icon)] used in '[src]' [type] is missing icon state [overlay].")
continue
Expand Down
3 changes: 1 addition & 2 deletions code/datums/greyscale/layer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@

/datum/greyscale_layer/icon_state/Initialize(icon_file)
. = ..()
var/list/icon_states = icon_states(icon_file)
if(!(icon_state in icon_states))
if(!icon_exists(icon_file, icon_state))
CRASH("Configured icon state \[[icon_state]\] was not found in [icon_file]. Double check your json configuration.")
icon = new(icon_file, icon_state)

Expand Down
4 changes: 1 addition & 3 deletions code/game/objects/items/devices/chameleonproj.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@
saved_appearance = temp.appearance

/obj/item/chameleon/proc/check_sprite(atom/target)
if(target.icon_state in icon_states(target.icon))
return TRUE
return FALSE
return icon_exists(target.icon, target.icon_state)

/obj/item/chameleon/proc/toggle(mob/user)
if(!can_use || !saved_appearance)
Expand Down
26 changes: 13 additions & 13 deletions code/modules/admin/verbs/debug.dm
Original file line number Diff line number Diff line change
Expand Up @@ -941,56 +941,56 @@
continue
//Is there an explicit worn_icon to pick against the worn_icon_state? Easy street expected behavior.
if(sprite.worn_icon)
if(!(sprite.icon_state in icon_states(sprite.worn_icon)))
if(!icon_exists(sprite.worn_icon, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Slot Flags are [sprite.slot_flags]."), confidential = TRUE)
else if(sprite.worn_icon_state)
if(sprite.slot_flags & ITEM_SLOT_MASK)
actual_file_name = 'icons/mob/clothing/mask.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_NECK)
actual_file_name = 'icons/mob/clothing/neck.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BACK)
actual_file_name = 'icons/mob/clothing/back.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_HEAD)
actual_file_name = 'icons/mob/clothing/head/default.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BELT)
actual_file_name = 'icons/mob/clothing/belt.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_SUITSTORE)
actual_file_name = 'icons/mob/clothing/belt_mirror.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.worn_icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
else if(sprite.icon_state)
if(sprite.slot_flags & ITEM_SLOT_MASK)
actual_file_name = 'icons/mob/clothing/mask.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_NECK)
actual_file_name = 'icons/mob/clothing/neck.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BACK)
actual_file_name = 'icons/mob/clothing/back.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_HEAD)
actual_file_name = 'icons/mob/clothing/head/default.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BELT)
actual_file_name = 'icons/mob/clothing/belt.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_SUITSTORE)
actual_file_name = 'icons/mob/clothing/belt_mirror.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
if(!icon_exists(actual_file_name, sprite.icon_state))
to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
#endif
2 changes: 1 addition & 1 deletion code/modules/asset_cache/assets/crafting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
icon_state ||= initial(preview_item.icon_state_preview) || initial(preview_item.icon_state)

if(PERFORM_ALL_TESTS(focus_only/bad_cooking_crafting_icons))
if(!icon_exists(icon_file, icon_state, scream = TRUE))
if(!icon_exists_or_scream(icon_file, icon_state))
return

Insert("a[id]", icon(icon_file, icon_state, SOUTH))
Expand Down
4 changes: 2 additions & 2 deletions code/modules/asset_cache/assets/research_designs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
icon_file = initial(path.research_icon)
icon_state = initial(path.research_icon_state)
if (PERFORM_ALL_TESTS(focus_only/invalid_research_designs))
if(!(icon_state in icon_states(icon_file)))
if(!icon_exists(icon_file, icon_state))
stack_trace("design [path] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
Expand Down Expand Up @@ -48,7 +48,7 @@

icon_state = initial(item.icon_state)
if (PERFORM_ALL_TESTS(focus_only/invalid_research_designs))
if(!(icon_state in icon_states(icon_file)))
if(!icon_exists(icon_file, icon_state))
stack_trace("design [path] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/projectiles/gun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@
if(bayonet)
var/mutable_appearance/knife_overlay
var/state = "bayonet" //Generic state.
if(bayonet.icon_state in icon_states('icons/obj/weapons/guns/bayonets.dmi')) //Snowflake state?
if(icon_exists('icons/obj/weapons/guns/bayonets.dmi', bayonet.icon_state)) //Snowflake state? //MONKESTATION EDIT - Refactored to `icon_exists`.
state = bayonet.icon_state
var/icon/bayonet_icons = 'icons/obj/weapons/guns/bayonets.dmi'
knife_overlay = mutable_appearance(bayonet_icons, state)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/surgery/bodyparts/_bodyparts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@
if(is_husked)
limb.icon = icon_husk
limb.icon_state = "[husk_type]_husk_[body_zone]"
icon_exists(limb.icon, limb.icon_state, scream = TRUE) //Prints a stack trace on the first failure of a given iconstate.
icon_exists_or_scream(limb.icon, limb.icon_state) //Prints a stack trace on the first failure of a given iconstate. //MONKESTATION EDIT - Refactored to `icon_exists_or_scream`.
. += limb
if(aux_zone) //Hand shit
aux = image(limb.icon, "[husk_type]_husk_[aux_zone]", -aux_layer, image_dir)
Expand All @@ -1016,7 +1016,7 @@
else
limb.icon_state = "[limb_id]_[body_zone]"

icon_exists(limb.icon, limb.icon_state, TRUE) //Prints a stack trace on the first failure of a given iconstate.
icon_exists_or_scream(limb.icon, limb.icon_state) //Prints a stack trace on the first failure of a given iconstate.

. += limb

Expand Down
4 changes: 2 additions & 2 deletions code/modules/unit_tests/suit_storage_icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@
continue

if(worn_icon) //easiest to check since we override everything.
if(!(icon_state in icon_states(worn_icon)))
if(!icon_exists(worn_icon, icon_state))
log_test("\t[count] - [item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in worn_icon override file, '[worn_icon]'")
count++
continue

if(!(icon_state in icon_states('icons/mob/clothing/belt_mirror.dmi')))
if(!icon_exists('icons/mob/clothing/belt_mirror.dmi', icon_state))
already_warned_icons += icon_state
log_test("\t[count] - [item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\"")
count++
Loading