[MIRROR] Increased cached_icon_states usage and tweaks to unit testing (#11445)

Co-authored-by: Drathek <76988376+Drulikar@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-08-16 12:05:13 -07:00
committed by GitHub
parent 403a7e0267
commit 14fed02701
15 changed files with 160 additions and 153 deletions

View File

@@ -368,18 +368,22 @@
return composite return composite
GLOBAL_LIST_EMPTY(icon_state_lists) GLOBAL_LIST_EMPTY(icon_state_lists)
/proc/cached_icon_states(var/icon/I) /// Gets the cached icon_state for the provided icon (only cached if its a file).
/// mode=0 will only show the sub-states ("open 0,0" and so on)
/// mode=1 will show the main state names ("open")
/// mode=2 will show all of the states
/proc/cached_icon_states(icon/I, mode=1)
if(!I) if(!I)
return list() return list()
var/key = I var/key = I
var/returnlist = GLOB.icon_state_lists[key] var/returnlist = GLOB.icon_state_lists[key]
if(!returnlist) if(!returnlist)
returnlist = icon_states(I) returnlist = icon_states(I, mode)
if(isfile(I)) // It's something that will stick around if(isfile(I)) // It's something that will stick around
GLOB.icon_state_lists[key] = returnlist GLOB.icon_state_lists[key] = returnlist
return returnlist return returnlist
/proc/expire_states_cache(var/key) /proc/expire_states_cache(key)
if(GLOB.icon_state_lists[key]) if(GLOB.icon_state_lists[key])
GLOB.icon_state_lists -= key GLOB.icon_state_lists -= key
return TRUE return TRUE

View File

@@ -72,7 +72,7 @@
var/state = A.icon_state var/state = A.icon_state
var/none = !icon var/none = !icon
if(!none) if(!none)
var/list/states = icon_states(icon) var/list/states = cached_icon_states(icon)
if(!(state in states)) if(!(state in states))
if(!("" in states)) if(!("" in states))
none = TRUE none = TRUE

View File

@@ -141,7 +141,7 @@ SUBSYSTEM_DEF(robot_sprites)
RS.icon_x = text2num(splitted[1]) RS.icon_x = text2num(splitted[1])
RS.icon_y = text2num(splitted[2]) RS.icon_y = text2num(splitted[2])
RS.vis_height = text2num(splitted[2]) RS.vis_height = text2num(splitted[2])
var/list/icon_states = icon_states(RS.sprite_icon) var/list/icon_states = cached_icon_states(RS.sprite_icon)
for(var/icon in icon_states) for(var/icon in icon_states)
// testing whitelist functionality ckey-... // testing whitelist functionality ckey-...
if(findtext(icon, regex("ckey-"))) if(findtext(icon, regex("ckey-")))

View File

@@ -40,7 +40,7 @@
var/icon/Cutter var/icon/Cutter
if("[initial_icon]_cutter" in icon_states(icon)) if("[initial_icon]_cutter" in cached_icon_states(icon))
Cutter = new(src.icon, "[initial_icon]_cutter") Cutter = new(src.icon, "[initial_icon]_cutter")
if(Cutter) if(Cutter)

View File

@@ -5,7 +5,6 @@
icon_state = "magazine" icon_state = "magazine"
var/headline var/headline
var/static/list/tabloid_states = icon_states('icons/obj/magazine.dmi')
var/static/list/tabloid_publishers = list( var/static/list/tabloid_publishers = list(
"\improper Solar Enquirer", "\improper Solar Enquirer",
"\improper Stellar Examiner", "\improper Stellar Examiner",
@@ -76,7 +75,7 @@
pixel_x = 5-rand(10) pixel_x = 5-rand(10)
pixel_x = 5-rand(10) pixel_x = 5-rand(10)
icon_state = pick(tabloid_states) icon_state = pick(cached_icon_states('icons/obj/magazine.dmi'))
headline = pick(tabloid_headlines) headline = pick(tabloid_headlines)
name = pick(tabloid_publishers) name = pick(tabloid_publishers)

View File

@@ -440,7 +440,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/spritesheet/proc/queuedInsert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) /datum/asset/spritesheet/proc/queuedInsert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE)
I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving)
if(!I || !length(icon_states(I))) // that direction or state doesn't exist if(!I || !length(cached_icon_states(I))) // that direction or state doesn't exist
return return
var/size_id = "[I.Width()]x[I.Height()]" var/size_id = "[I.Width()]x[I.Height()]"
var/size = sizes[size_id] var/size = sizes[size_id]
@@ -476,7 +476,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
if(!directions) if(!directions)
directions = list(SOUTH) directions = list(SOUTH)
for(var/icon_state_name in icon_states(I)) for(var/icon_state_name in cached_icon_states(I))
for(var/direction in directions) for(var/direction in directions)
var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : ""
Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction)

View File

@@ -58,7 +58,7 @@
var/obj/machinery/computer/C = item var/obj/machinery/computer/C = item
var/screen = initial(C.icon_screen) var/screen = initial(C.icon_screen)
var/keyboard = initial(C.icon_keyboard) var/keyboard = initial(C.icon_keyboard)
var/all_states = icon_states(icon_file) var/all_states = cached_icon_states(icon_file)
if (screen && (screen in all_states)) if (screen && (screen in all_states))
transform.blend_icon(uni_icon(icon_file, screen), ICON_OVERLAY) transform.blend_icon(uni_icon(icon_file, screen), ICON_OVERLAY)
if (keyboard && (keyboard in all_states)) if (keyboard && (keyboard in all_states))

View File

@@ -22,7 +22,7 @@
var/datum/universal_icon/I var/datum/universal_icon/I
var/icon_states_list = icon_states(icon_file) var/icon_states_list = cached_icon_states(icon_file)
if(icon_state in icon_states_list) if(icon_state in icon_states_list)
I = uni_icon(icon_file, icon_state, SOUTH) I = uni_icon(icon_file, icon_state, SOUTH)
var/c = initial(item.color) var/c = initial(item.color)

View File

@@ -1376,7 +1376,7 @@
// only override icon if a corresponding digitigrade replacement icon_state exists // only override icon if a corresponding digitigrade replacement icon_state exists
// otherwise, keep the old non-digi icon_define (or nothing) // otherwise, keep the old non-digi icon_define (or nothing)
if(icon_state && icon_states(update_icon_define_digi)?.Find(icon_state)) if(icon_state && cached_icon_states(update_icon_define_digi):Find(icon_state))
update_icon_define = update_icon_define_digi update_icon_define = update_icon_define_digi

View File

@@ -25,10 +25,10 @@
author = _author author = _author
/obj/effect/decal/writing/Initialize(mapload) /obj/effect/decal/writing/Initialize(mapload)
var/list/random_icon_states = icon_states(icon) var/list/random_icon_states = cached_icon_states(icon)
for(var/obj/effect/decal/writing/W in loc) for(var/obj/effect/decal/writing/writing in loc)
random_icon_states.Remove(W.icon_state) random_icon_states.Remove(writing.icon_state)
if(random_icon_states.len) if(length(random_icon_states))
icon_state = pick(random_icon_states) icon_state = pick(random_icon_states)
if(!mapload || !CONFIG_GET(flag/persistence_ignore_mapload)) if(!mapload || !CONFIG_GET(flag/persistence_ignore_mapload))
SSpersistence.track_value(src, /datum/persistent/graffiti) SSpersistence.track_value(src, /datum/persistent/graffiti)

View File

@@ -13,48 +13,44 @@
validate_accessory_list(/datum/sprite_accessory/tail) validate_accessory_list(/datum/sprite_accessory/tail)
validate_accessory_list(/datum/sprite_accessory/wing) validate_accessory_list(/datum/sprite_accessory/wing)
/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_accessory_list(var/path) /datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_accessory_list(path)
var/list/collection = list() var/list/collection = list()
for(var/SP in subtypesof(path)) for(var/datum/sprite_accessory/accessory as anything in subtypesof(path))
var/datum/sprite_accessory/A = new SP() if(accessory::name == DEVELOPER_WARNING_NAME)
TEST_ASSERT(A, "[SP]: Cosmetic - Path resolved to null in list.")
if(!A)
continue continue
TEST_ASSERT(A.name, "[A] - [A.type]: Cosmetic - Missing name.") TEST_ASSERT(accessory::name, "[accessory::name] - [accessory::type]: Cosmetic - Missing name.")
if(A.name == DEVELOPER_WARNING_NAME) TEST_ASSERT(!collection[accessory::name], "[accessory::name] - [accessory::type]: Cosmetic - Name defined twice. Original def [collection[accessory::name]]")
continue if(!collection[accessory::name])
collection[accessory::name] = accessory::type
TEST_ASSERT(!collection[A.name], "[A] - [A.type]: Cosmetic - Name defined twice. Original def [collection[A.name]]") if(ispath(accessory, text2path("[path]/invisible")))
if(!collection[A.name]) TEST_ASSERT(!accessory::icon_state, "[accessory::name] - [accessory::type]: Cosmetic - Invisible subtype has icon_state.")
collection[A.name] = A.type else if(!accessory::icon_state)
TEST_FAIL("[accessory::name] - [accessory::type]: Cosmetic - Has no icon_state.")
if(istype(A,text2path("[path]/invisible")))
TEST_ASSERT(!A.icon_state, "[A] - [A.type]: Cosmetic - Invisible subtype has icon_state.")
else if(!A.icon_state)
TEST_ASSERT(A.icon_state, "[A] - [A.type]: Cosmetic - Has no icon_state.")
else else
// Check if valid icon // Check if valid icon
validate_icons(A) validate_icons(accessory)
qdel(A) /datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_icons(datum/sprite_accessory/accessory)
var/actual_icon_state = accessory::icon_state
/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_icons(datum/sprite_accessory/A) if(istype(accessory, /datum/sprite_accessory/hair))
var/actual_icon_state = A.icon_state actual_icon_state += "_s"
TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].")
return
if(istype(A,/datum/sprite_accessory/hair)) if(istype(accessory, /datum/sprite_accessory/facial_hair))
actual_icon_state = "[A.icon_state]_s" actual_icon_state += "_s"
TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].") TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].")
return
if(istype(A,/datum/sprite_accessory/facial_hair)) if(istype(accessory, /datum/sprite_accessory/marking))
actual_icon_state = "[A.icon_state]_s" var/datum/sprite_accessory/marking/marking = accessory
TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].") for(var/body_part in marking.body_parts)
TEST_ASSERT(body_part in BP_ALL, "[accessory::name] - [accessory::type]: Cosmetic - Has an illegal bodypart \"[body_part]\". ONLY use parts listed in BP_ALL.")
if(istype(A,/datum/sprite_accessory/marking)) actual_icon_state = "[accessory::icon_state]-[body_part]"
var/datum/sprite_accessory/marking/MA = A TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].")
for(var/BP in MA.body_parts) return
TEST_ASSERT(BP in BP_ALL, "[A] - [A.type]: Cosmetic - Has an illegal bodypart \"[BP]\". ONLY use parts listed in BP_ALL.")
actual_icon_state = "[A.icon_state]-[BP]"
TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].")

View File

@@ -6,15 +6,16 @@
var/failed = 0 var/failed = 0
/datum/unit_test/all_robot_sprites_must_be_valid/Run() /datum/unit_test/all_robot_sprites_must_be_valid/Run()
for(var/sprite in subtypesof(/datum/robot_sprite)) for(var/datum/robot_sprite/robot_type as anything in subtypesof(/datum/robot_sprite))
var/datum/robot_sprite/RS = new sprite() if(!robot_type::name) // Parent type, ignore me
if(!RS.name) // Parent type, ignore me
continue continue
TEST_ASSERT(RS.sprite_icon, "[RS.type]: Robots - Robot sprite \"[RS.name]\", missing sprite_icon.") if(!robot_type::sprite_icon)
if(!RS.sprite_icon) TEST_FAIL("[robot_type]: Robots - Robot sprite \"[robot_type::name]\", missing sprite_icon.")
continue continue
var/datum/robot_sprite/robot = new robot_type()
var/list/checks = list( var/list/checks = list(
"[ROBOT_HAS_SPEED_SPRITE]" = "-roll", "[ROBOT_HAS_SPEED_SPRITE]" = "-roll",
"[ROBOT_HAS_SHIELD_SPRITE]" = "-shield", "[ROBOT_HAS_SHIELD_SPRITE]" = "-shield",
@@ -27,143 +28,143 @@
"[ROBOT_HAS_TASER_SPRITE]" = "-taser", "[ROBOT_HAS_TASER_SPRITE]" = "-taser",
"[ROBOT_HAS_DISABLER_SPRITE]" = "-disabler" "[ROBOT_HAS_DISABLER_SPRITE]" = "-disabler"
) )
for(var/C in checks) for(var/check in checks)
if(RS.sprite_flag_check(text2num(C))) if(robot.sprite_flag_check(text2num(check)))
check_state(RS,checks[C]) check_state(robot,checks[check])
// eyes, lights, markings // eyes, lights, markings
if(RS.has_eye_sprites) if(robot.has_eye_sprites)
check_state(RS,"-eyes") check_state(robot,"-eyes")
if(RS.has_eye_light_sprites) if(robot.has_eye_light_sprites)
check_state(RS,"-lights") check_state(robot,"-lights")
if(LAZYLEN(RS.sprite_decals)) if(LAZYLEN(robot.sprite_decals))
for(var/decal in RS.sprite_decals) for(var/decal in robot.sprite_decals)
check_state(RS,"-[decal]") check_state(robot,"-[decal]")
if(LAZYLEN(RS.sprite_animations)) if(LAZYLEN(robot.sprite_animations))
for(var/animation in RS.sprite_animations) for(var/animation in robot.sprite_animations)
check_state(RS,"-[animation]") check_state(robot,"-[animation]")
// Control panel // Control panel
if(RS.has_custom_open_sprites) if(robot.has_custom_open_sprites)
check_state(RS,"-openpanel_nc") check_state(robot,"-openpanel_nc")
check_state(RS,"-openpanel_c") check_state(robot,"-openpanel_c")
check_state(RS,"-openpanel_w") check_state(robot,"-openpanel_w")
// Glow State // Glow State
if(RS.has_glow_sprites) if(robot.has_glow_sprites)
check_state(RS,"-glow") check_state(robot,"-glow")
// Bellies // Bellies
if(RS.has_vore_belly_sprites && !RS.belly_capacity_list) if(robot.has_vore_belly_sprites && !robot.belly_capacity_list)
if(RS.has_sleeper_light_indicator) if(robot.has_sleeper_light_indicator)
// belly r/g light // belly r/g light
check_state(RS,"-sleeper-r") check_state(robot,"-sleeper-r")
check_state(RS,"-sleeper-g") check_state(robot,"-sleeper-g")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-sleeper-r-[rest_style]") check_state(robot,"-sleeper-r-[rest_style]")
check_state(RS,"-sleeper-g-[rest_style]") check_state(robot,"-sleeper-g-[rest_style]")
// struggling // struggling
if(RS.has_vore_struggle_sprite) if(robot.has_vore_struggle_sprite)
check_state(RS,"-sleeper-r-struggle") check_state(robot,"-sleeper-r-struggle")
check_state(RS,"-sleeper-g-struggle") check_state(robot,"-sleeper-g-struggle")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-sleeper-r-[rest_style]-struggle") check_state(robot,"-sleeper-r-[rest_style]-struggle")
check_state(RS,"-sleeper-g-[rest_style]-struggle") check_state(robot,"-sleeper-g-[rest_style]-struggle")
else else
// belly // belly
check_state(RS,"-sleeper") check_state(robot,"-sleeper")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-sleeper-[rest_style]") check_state(robot,"-sleeper-[rest_style]")
// struggling // struggling
if(RS.has_vore_struggle_sprite) if(robot.has_vore_struggle_sprite)
check_state(RS,"-sleeper-struggle") check_state(robot,"-sleeper-struggle")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-sleeper-[rest_style]-struggle") check_state(robot,"-sleeper-[rest_style]-struggle")
else if (RS.belly_capacity_list) else if(robot.belly_capacity_list)
for(var/belly in RS.belly_capacity_list) for(var/belly in robot.belly_capacity_list)
for(var/num = 1 to RS.belly_capacity_list[belly]) for(var/num = 1 to robot.belly_capacity_list[belly])
// big belly // big belly
check_state(RS,"-[belly]-[num]") check_state(robot,"-[belly]-[num]")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-[belly]-[num]-[rest_style]") check_state(robot,"-[belly]-[num]-[rest_style]")
// struggling // struggling
if(RS.has_vore_struggle_sprite) if(robot.has_vore_struggle_sprite)
check_state(RS,"-[belly]-[num]-struggle") check_state(robot,"-[belly]-[num]-struggle")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-[belly]-[num]-[rest_style]-struggle") check_state(robot,"-[belly]-[num]-[rest_style]-struggle")
if(RS.belly_light_list) if(robot.belly_light_list)
for(var/belly in RS.belly_light_list) for(var/belly in robot.belly_light_list)
for(var/num = 1 to RS.belly_light_list[belly]) for(var/num = 1 to robot.belly_light_list[belly])
// multi belly r/g light // multi belly r/g light
check_state(RS,"-[belly]-[num]-r") check_state(robot,"-[belly]-[num]-r")
check_state(RS,"-[belly]-[num]-g") check_state(robot,"-[belly]-[num]-g")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-[belly]-[num]-r-[rest_style]") check_state(robot,"-[belly]-[num]-r-[rest_style]")
check_state(RS,"-[belly]-[num]-g-[rest_style]") check_state(robot,"-[belly]-[num]-g-[rest_style]")
// struggling // struggling
if(RS.has_vore_struggle_sprite) if(robot.has_vore_struggle_sprite)
check_state(RS,"-[belly]-[num]-r-struggle") check_state(robot,"-[belly]-[num]-r-struggle")
check_state(RS,"-[belly]-[num]-g-struggle") check_state(robot,"-[belly]-[num]-g-struggle")
if(RS.has_vore_belly_resting_sprites) if(robot.has_vore_belly_resting_sprites)
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-[belly]-[num]-r-[rest_style]-struggle") check_state(robot,"-[belly]-[num]-r-[rest_style]-struggle")
check_state(RS,"-[belly]-[num]-g-[rest_style]-struggle") check_state(robot,"-[belly]-[num]-g-[rest_style]-struggle")
// reseting // reseting
for(var/rest_style in RS.rest_sprite_options) for(var/rest_style in robot.rest_sprite_options)
rest_style = lowertext(rest_style) rest_style = lowertext(rest_style)
if(rest_style == "default") if(rest_style == "default")
rest_style = "rest" rest_style = "rest"
check_state(RS,"-[rest_style]") check_state(robot,"-[rest_style]")
if(RS.has_glow_sprites) if(robot.has_glow_sprites)
check_state(RS,"-[rest_style]-glow") check_state(robot,"-[rest_style]-glow")
if(RS.has_rest_lights_sprites) if(robot.has_rest_lights_sprites)
check_state(RS,"-[rest_style]-lights") check_state(robot,"-[rest_style]-lights")
if(RS.has_rest_eyes_sprites) if(robot.has_rest_eyes_sprites)
check_state(RS,"-[rest_style]-eyes") check_state(robot,"-[rest_style]-eyes")
// death // death
if(RS.has_dead_sprite) if(robot.has_dead_sprite)
check_state(RS,"-wreck") check_state(robot,"-wreck")
if(RS.has_dead_sprite_overlay) // Only one per dmi if(robot.has_dead_sprite_overlay) // Only one per dmi
TEST_ASSERT("wreck-overlay" in cached_icon_states(RS.sprite_icon), "[RS.type]: Robots - Robot sprite \"[RS.name]\", missing icon_state wreck-overlay, in dmi \"[RS.sprite_icon]\".") TEST_ASSERT("wreck-overlay" in cached_icon_states(robot.sprite_icon), "[robot.type]: Robots - Robot sprite \"[robot.name]\", missing icon_state wreck-overlay, in dmi \"[robot.sprite_icon]\".")
// offset // offset
var/icon/I = new(RS.sprite_icon) var/icon/I = new(robot.sprite_icon)
TEST_ASSERT_EQUAL(RS.icon_x, I.Width(), "[RS.type]: Robots - Robot sprite \"[RS.name]\", icon_x \"[RS.icon_x]\" did not match dmi configured width \"[I.Width()]\"") TEST_ASSERT_EQUAL(robot.icon_x, I.Width(), "[robot.type]: Robots - Robot sprite \"[robot.name]\", icon_x \"[robot.icon_x]\" did not match dmi configured width \"[I.Width()]\"")
TEST_ASSERT_EQUAL(RS.icon_y, I.Height(), "[RS.type]: Robots - Robot sprite \"[RS.name]\", icon_y \"[RS.icon_y]\" did not match dmi configured height \"[I.Height()]\"") TEST_ASSERT_EQUAL(robot.icon_y, I.Height(), "[robot.type]: Robots - Robot sprite \"[robot.name]\", icon_y \"[robot.icon_y]\" did not match dmi configured height \"[I.Height()]\"")
TEST_ASSERT_EQUAL(RS.icon_y, RS.vis_height, "[RS.type]: Robots - Robot sprite \"[RS.name]\", vis_height \"[RS.vis_height]\" did not match icon_y \"[RS.icon_y]\"") TEST_ASSERT_EQUAL(robot.icon_y, robot.vis_height, "[robot.type]: Robots - Robot sprite \"[robot.name]\", vis_height \"[robot.vis_height]\" did not match icon_y \"[robot.icon_y]\"")
var/legal_offset = (I.Width() - world.icon_size) / 2 var/legal_offset = (I.Width() - world.icon_size) / 2
TEST_ASSERT_EQUAL(RS.pixel_x, -legal_offset, "[RS.type]: Robots - Robot sprite \"[RS.name]\", pixel_x \"[RS.pixel_x]\" did not have correct offset, should be \"[-legal_offset]\"") TEST_ASSERT_EQUAL(robot.pixel_x, -legal_offset, "[robot.type]: Robots - Robot sprite \"[robot.name]\", pixel_x \"[robot.pixel_x]\" did not have correct offset, should be \"[-legal_offset]\"")
qdel(I) qdel(I)
qdel(RS) qdel(robot)
/datum/unit_test/all_robot_sprites_must_be_valid/proc/check_state(datum/robot_sprite/RS, append) /datum/unit_test/all_robot_sprites_must_be_valid/proc/check_state(datum/robot_sprite/robot, append)
var/check_state = "[RS.sprite_icon_state][append]" var/check_state = "[robot.sprite_icon_state][append]"
TEST_ASSERT(check_state in cached_icon_states(RS.sprite_icon), "[RS.type]: Robots - Robot sprite \"[RS.name]\", enabled but missing icon_state \"[check_state]\", in dmi \"[RS.sprite_icon]\".") TEST_ASSERT(check_state in cached_icon_states(robot.sprite_icon), "[robot.type]: Robots - Robot sprite \"[robot.name]\", enabled but missing icon_state \"[check_state]\", in dmi \"[robot.sprite_icon]\".")

View File

@@ -2,23 +2,30 @@
/datum/unit_test/spritesheets /datum/unit_test/spritesheets
/datum/unit_test/spritesheets/Run() /datum/unit_test/spritesheets/Run()
var/regex/valid_css_class = new(@"^([\l_][\w\-]|[\l_\-][\l_])")
for(var/datum/asset/spritesheet/sheet as anything in subtypesof(/datum/asset/spritesheet)) for(var/datum/asset/spritesheet/sheet as anything in subtypesof(/datum/asset/spritesheet))
if(!initial(sheet.name)) //Ignore abstract types if(!initial(sheet.name)) //Ignore abstract types
continue continue
if (sheet == initial(sheet._abstract)) if(sheet == initial(sheet._abstract))
continue continue
sheet = get_asset_datum(sheet) sheet = get_asset_datum(sheet)
for(var/sprite_name in sheet.sprites) for(var/sprite_name in sheet.sprites)
if(!sprite_name) if(!sprite_name)
TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.") TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.")
if(!valid_css_class.Find(sprite_name))
// https://www.w3.org/TR/CSS2/syndata.html#value-def-identifier
TEST_FAIL("Spritesheet [sheet.type] has a icon state that doesn't comply with css standards: '[sprite_name]'.")
// Test IconForge generated sheets as well // Test IconForge generated sheets as well
for(var/datum/asset/spritesheet_batched/sheet as anything in subtypesof(/datum/asset/spritesheet_batched)) for(var/datum/asset/spritesheet_batched/sheet as anything in subtypesof(/datum/asset/spritesheet_batched))
if(!initial(sheet.name)) //Ignore abstract types if(!initial(sheet.name)) //Ignore abstract types
continue continue
if (sheet == initial(sheet._abstract)) if(sheet == initial(sheet._abstract))
continue continue
sheet = get_asset_datum(sheet) sheet = get_asset_datum(sheet)
for(var/sprite_name in sheet.sprites) for(var/sprite_name in sheet.sprites)
if(!sprite_name) if(!sprite_name)
TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.") TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.")
if(!valid_css_class.Find(sprite_name))
// https://www.w3.org/TR/CSS2/syndata.html#value-def-identifier
TEST_FAIL("Spritesheet [sheet.type] has a icon state that doesn't comply with css standards: '[sprite_name]'.")

View File

@@ -835,9 +835,9 @@
if(new_disable_hud == 1) if(new_disable_hud == 1)
new_belly.disable_hud = TRUE new_belly.disable_hud = TRUE
var/possible_fullscreens = icon_states('icons/mob/screen_full_vore_list.dmi') var/possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi')
if(!new_belly.colorization_enabled) if(!new_belly.colorization_enabled)
possible_fullscreens = icon_states('icons/mob/screen_full_vore.dmi') possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi')
if(!(new_belly.belly_fullscreen in possible_fullscreens)) if(!(new_belly.belly_fullscreen in possible_fullscreens))
new_belly.belly_fullscreen = "" new_belly.belly_fullscreen = ""

View File

@@ -225,9 +225,9 @@
) )
var/list/belly_fullscreens var/list/belly_fullscreens
if(selected.colorization_enabled) if(selected.colorization_enabled)
belly_fullscreens = icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable. belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable.
else else
belly_fullscreens = icon_states('icons/mob/screen_full_vore.dmi') //Non colorable belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi') //Non colorable
var/list/vs_flags = list() var/list/vs_flags = list()
for(var/flag_name in selected.vore_sprite_flag_list) for(var/flag_name in selected.vore_sprite_flag_list)