From 8fcad605eed469788b139bfa62031cfb9e7ebc07 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Tue, 18 Jul 2017 04:22:01 -0500 Subject: [PATCH] More icon caching (#3078) changes: Human-type hair (facial & head), eyes, and lips are now cached in SSicon_cache. Underwear, undershirts, and socks are now cached in SSicon_cache. Removed forced icon regen for update_body - if this actually did anything, the cache key for these icons needs to be made more detailed. Organs now fully use SSoverlays to apply overlays (previously they partially used it, which may have caused bugs). A couple of hair styles (bald, shaved) are pretty common, so this should remove/reduce the overhead of constantly regenerating their icons. Also means that BST's icons only really need to be generated once. --- code/controllers/subsystems/icon_cache.dm | 7 ++ .../mob/living/carbon/human/update_icons.dm | 49 +++++++------ code/modules/organs/organ_icon.dm | 71 ++++++++++++++----- 3 files changed, 88 insertions(+), 39 deletions(-) diff --git a/code/controllers/subsystems/icon_cache.dm b/code/controllers/subsystems/icon_cache.dm index c448fa53df0..d106c33841f 100644 --- a/code/controllers/subsystems/icon_cache.dm +++ b/code/controllers/subsystems/icon_cache.dm @@ -36,6 +36,13 @@ var/list/damage_icon_parts = list() // [icon]-[icon_state]-[limb_name]-[color] var/list/markings_cache = list() + var/list/human_eye_cache = list() + var/list/human_lip_cache = list() + var/list/human_hair_cache = list() + var/list/human_beard_cache = list() + var/list/human_underwear_cache = list() + var/list/human_undershirt_cache = list() + var/list/human_socks_cache = list() /datum/controller/subsystem/icon_cache/New() NEW_SS_GLOBAL(SSicon_cache) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 06974cb32f6..3d36e4b0acb 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -216,9 +216,6 @@ Please contact me on #coderbus IRC. ~Carn x if(update_icons) update_icons() //BASE MOB SPRITE -//Extension by Nanako -//Passing in a value of 2 for update_icons will ignore any cached icon, and force a new one to be generated - /mob/living/carbon/human/proc/update_body(var/update_icons=1) if (QDELING(src)) return @@ -226,10 +223,10 @@ Please contact me on #coderbus IRC. ~Carn x var/husk_color_mod = rgb(96,88,80) var/hulk_color_mod = rgb(48,224,40) - var/husk = (HUSK in src.mutations) - var/fat = (FAT in src.mutations) - var/hulk = (HULK in src.mutations) - var/skeleton = (SKELETON in src.mutations) + var/husk = (HUSK in mutations) + var/fat = (FAT in mutations) + var/hulk = (HULK in mutations) + var/skeleton = (SKELETON in mutations) var/g = (gender == FEMALE ? "f" : "m") pixel_x = species.icon_x_offset @@ -243,12 +240,7 @@ Please contact me on #coderbus IRC. ~Carn x qdel(stand_icon) stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") - - var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]" - if(lip_style) - icon_key += "[lip_style]" - else - icon_key += "nolips" + var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin][lip_style || "nolips"]" var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"] if(eyes) icon_key += "[rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3])]" @@ -257,7 +249,7 @@ Please contact me on #coderbus IRC. ~Carn x for(var/organ_tag in species.has_limbs) var/obj/item/organ/external/part = organs_by_name[organ_tag] - if(isnull(part) || part.is_stump()) + if(!part || part.is_stump()) icon_key += "0" else if(part.status & ORGAN_ROBOT) icon_key += "2[part.model ? "-[part.model]": ""]" @@ -276,11 +268,9 @@ Please contact me on #coderbus IRC. ~Carn x else icon_key += "#000000" - icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" - var/icon/base_icon - if(update_icons != 2 && SSicon_cache.human_icon_cache[icon_key])//If update_icons is 2, then we forcibly generate a new icon - base_icon = SSicon_cache.human_icon_cache[icon_key] - else + icon_key = "[icon_key][!!husk][!!fat][!!hulk][!!skeleton]" + var/icon/base_icon = SSicon_cache.human_icon_cache[icon_key] + if (!base_icon) // Icon ain't in the cache, so generate it. //BEGIN CACHED ICON GENERATION. var/obj/item/organ/external/chest = get_organ("chest") base_icon = chest.get_icon() @@ -328,13 +318,28 @@ Please contact me on #coderbus IRC. ~Carn x //Underwear if(underwear && species.appearance_flags & HAS_UNDERWEAR) - stand_icon.Blend(new /icon('icons/mob/human.dmi', underwear), ICON_OVERLAY) + var/uwear = "[underwear]" + var/icon/undies = SSicon_cache.human_underwear_cache[uwear] + if (!undies) + undies = new('icons/mob/human.dmi', underwear) + SSicon_cache.human_underwear_cache[uwear] = undies + stand_icon.Blend(undies, ICON_OVERLAY) if(undershirt && species.appearance_flags & HAS_UNDERWEAR) - stand_icon.Blend(new /icon('icons/mob/human.dmi', undershirt), ICON_OVERLAY) + var/ushirt = "[undershirt]" + var/icon/shirt = SSicon_cache.human_undershirt_cache[ushirt] + if (!shirt) + shirt = new('icons/mob/human.dmi', undershirt) + SSicon_cache.human_undershirt_cache[ushirt] = shirt + stand_icon.Blend(shirt, ICON_OVERLAY) if(socks && species.appearance_flags & HAS_SOCKS) - stand_icon.Blend(new /icon('icons/mob/human.dmi', socks), ICON_OVERLAY) + var/sockskey = "[socks]" + var/icon/socksicon = SSicon_cache.human_socks_cache[sockskey] + if (!socksicon) + socksicon = new('icons/mob/human.dmi', socks) + SSicon_cache.human_socks_cache[sockskey] = socksicon + stand_icon.Blend(socksicon, ICON_OVERLAY) if(update_icons) update_icons() diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 9147da5453c..da17b80a6e8 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -54,23 +54,38 @@ /obj/item/organ/external/head/get_icon() ..() - overlays.Cut() + cut_overlays() if(!owner || !owner.species) return if(owner.species.has_organ["eyes"] || (owner.species.vision_organ && owner.species.has_organ[species.vision_organ])) var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"] || owner.internal_organs_by_name[species.vision_organ] if(eyes && species.eyes) - var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) - if(eyes) - eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD) - else - eyes_icon.Blend(rgb(128,0,0), ICON_ADD) + var/eyecolor + if (eyes.eye_colour) + eyecolor = rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]) + + var/cache_key = "[species.eyes]_[eyecolor || "nocolor"]" + + var/icon/eyes_icon = SSicon_cache.human_eye_cache[cache_key] + if (!eyes_icon) + eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes) + if(eyecolor) + eyes_icon.Blend(eyecolor, ICON_ADD) + else + eyes_icon.Blend(rgb(128,0,0), ICON_ADD) + + SSicon_cache.human_eye_cache[cache_key] = eyes_icon + mob_icon.Blend(eyes_icon, ICON_OVERLAY) - overlays |= eyes_icon + add_overlay(eyes_icon) if(owner.lip_style && (species && (species.appearance_flags & HAS_LIPS))) - var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") - overlays |= lip_icon + var/icon/lip_icon = SSicon_cache.human_lip_cache["[owner.lip_style]"] + if (!lip_icon) + lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s") + SSicon_cache.human_lip_cache["[owner.lip_style]"] = lip_icon + + add_overlay(lip_icon) mob_icon.Blend(lip_icon, ICON_OVERLAY) for(var/M in markings) @@ -90,18 +105,40 @@ if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype() in facial_hair_style.species_allowed)) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) - overlays |= facial_s + var/facialcolor + if (facial_hair_style.do_colouration) + facialcolor = rgb(owner.r_facial, owner.g_facial, owner.b_facial) + + var/cache_key = "[facial_hair_style.icon]_[facial_hair_style.icon_state]_[facialcolor || "nocolor"]" + + var/icon/facial_s = SSicon_cache.human_beard_cache[cache_key] + if (!facial_s) + facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + if(facial_hair_style.do_colouration) + facial_s.Blend(facialcolor, ICON_ADD) + + SSicon_cache.human_beard_cache[cache_key] = facial_s + + add_overlay(facial_s) if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] if(hair_style && (species.get_bodytype() in hair_style.species_allowed)) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) - hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_ADD) - overlays |= hair_s + var/haircolor + if (hair_style.do_colouration && istype(h_col) && h_col.len >= 3) + haircolor = rgb(h_col[1], h_col[2], h_col[3]) + + var/cache_key = "[hair_style.icon]_[hair_style.icon_state]_[haircolor || "nocolor"]" + var/icon/hair_s = SSicon_cache.human_hair_cache[cache_key] + if (!hair_s) + hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) + hair_s.Blend(haircolor, ICON_ADD) + + SSicon_cache.human_hair_cache[cache_key] = hair_s + add_overlay(hair_s) + + compile_overlays() return mob_icon