From c5966cdec99f29b776f3e1ddee07d75dac963c0c Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Thu, 15 May 2014 20:14:32 +0930 Subject: [PATCH] Added a caching system for human icons. Conflicts: code/modules/mob/living/carbon/human/update_icons.dm code/modules/mob/living/carbon/species.dm --- code/__HELPERS/global_lists.dm | 3 + .../mob/living/carbon/human/update_icons.dm | 159 ++++++++++++------ code/modules/mob/living/carbon/species.dm | 11 +- icons/mob/human_races/r_armalis.dmi | Bin 4065 -> 4073 bytes 4 files changed, 122 insertions(+), 51 deletions(-) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index b0f471a12ad..f1c3afd8ef4 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -103,9 +103,12 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al var/datum/language/L = new T all_languages[L.name] = L + var/rkey = 0 paths = typesof(/datum/species)-/datum/species for(var/T in paths) + rkey++ var/datum/species/S = new T + S.race_key = rkey //Used in mob icon caching. all_species[S.name] = S if(S.flags & IS_WHITELISTED) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 90147c666e6..f67d95551ba 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,3 +1,11 @@ +/* + Global associative list for caching humanoid icons. + Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0. + TODO: Proper documentation + icon_key is [species.race_key][g][husk][fat][hulk][skeleton][s_tone] +*/ +var/global/list/human_icon_cache = list() + /////////////////////// //UPDATE_ICONS SYSTEM// /////////////////////// @@ -206,7 +214,6 @@ proc/get_damage_icon_part(damage_state, body_part) var/image/standing_image = new /image("icon" = standing) - // blend the individual damage states with our icons for(var/datum/organ/external/O in organs) if(!(O.status & ORGAN_DESTROYED)) @@ -217,14 +224,12 @@ proc/get_damage_icon_part(damage_state, body_part) standing_image.overlays += DI - overlays_standing[DAMAGE_LAYER] = standing_image if(update_icons) update_icons() //BASE MOB SPRITE /mob/living/carbon/human/proc/update_body(var/update_icons=1) - if(stand_icon) del(stand_icon) var/husk_color_mod = rgb(96,88,80) var/hulk_color_mod = rgb(48,224,40) @@ -235,29 +240,65 @@ proc/get_damage_icon_part(damage_state, body_part) var/hulk = (M_HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) - var/g = "m" - if(gender == FEMALE) g = "f" - - var/datum/organ/external/chest = get_organ("chest") - stand_icon = chest.get_icon(g,fat) - if(!skeleton) - if(husk) - stand_icon.ColorTone(husk_color_mod) - else if(hulk) - var/list/TONE = ReadRGB(hulk_color_mod) - stand_icon.MapColors(rgb(TONE[1],0,0),rgb(0,TONE[2],0),rgb(0,0,TONE[3])) - - var/datum/organ/external/head/head = get_organ("head") + var/g = (gender == FEMALE ? "f" : "m") var/has_head = 0 var/brain_showing = 0 - if(head && !(head.status & ORGAN_DESTROYED)) - has_head = 1 - if(head.brained==1) - brain_showing = 1 + + //CACHING: Generate an index key from visible bodyparts. + //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. + + //Create a new, blank icon for our mob to use. + if(stand_icon) + del(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]" for(var/datum/organ/external/part in organs) - if(!istype(part, /datum/organ/external/chest) && !(part.status & ORGAN_DESTROYED)) - var/icon/temp + + if(istype(part,/datum/organ/external/head) && !(part.status & ORGAN_DESTROYED)) + has_head = 1 + var/datum/organ/external/head/head = part + if(head.brained==1) + brain_showing = 1 + + + if(part.status & ORGAN_DESTROYED) + icon_key = "[icon_key]0" + else if(part.status & ORGAN_ROBOT) + icon_key = "[icon_key]2" + else if(part.status & ORGAN_DEAD) //Do we even have necrosis in our current code? ~Z + icon_key = "[icon_key]3" + else + icon_key = "[icon_key]1" + + icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0][s_tone]" + + var/icon/base_icon + if(human_icon_cache[icon_key]) + //Icon is cached, use existing icon. + base_icon = human_icon_cache[icon_key] + + log_debug("Retrieved cached mob icon ([icon_key] \icon[human_icon_cache[icon_key]]) for [src].") + + else + + //BEGIN CACHED ICON GENERATION. + + //Icon is not cached, generate and store it. + //Robotic limbs are handled in get_icon() so all we worry about are missing or dead limbs. + //No icon stored, so we need to start with a basic one. + var/datum/organ/external/chest = get_organ("chest") + base_icon = chest.get_icon(g) + + for(var/datum/organ/external/part in organs) + + var/icon/temp //Hold the bodypart icon for processing. + + if(part.status & ORGAN_DESTROYED) + continue + if (istype(part, /datum/organ/external/groin) || istype(part, /datum/organ/external/head)) temp = part.get_icon(g,fat) else @@ -267,51 +308,71 @@ proc/get_damage_icon_part(damage_state, body_part) temp.ColorTone(necrosis_color_mod) temp.SetIntensity(0.7) - else if(!skeleton) - if(husk) - temp.ColorTone(husk_color_mod) - else if(hulk) - var/list/TONE = ReadRGB(hulk_color_mod) - temp.MapColors(rgb(TONE[1],0,0),rgb(0,TONE[2],0),rgb(0,0,TONE[3])) - //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) if(part.icon_position&(LEFT|RIGHT)) + var/icon/temp2 = new('icons/mob/human.dmi',"blank") + temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) + if(!(part.icon_position & LEFT)) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) + if(!(part.icon_position & RIGHT)) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - stand_icon.Blend(temp2, ICON_OVERLAY) - temp2 = new('icons/mob/human.dmi',"blank") + + base_icon.Blend(temp2, ICON_OVERLAY) + if(part.icon_position & LEFT) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) + if(part.icon_position & RIGHT) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - stand_icon.Blend(temp2, ICON_UNDERLAY) + + base_icon.Blend(temp2, ICON_UNDERLAY) + else - stand_icon.Blend(temp, ICON_OVERLAY) - //Skin tone - if(!skeleton && !husk && !hulk && (species.bodyflags & HAS_SKIN_TONE)) - if(s_tone >= 0) - stand_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) - else - stand_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + base_icon.Blend(temp, ICON_OVERLAY) - //Skin color - if(!skeleton && !husk && !hulk && (species.bodyflags & HAS_SKIN_COLOR)) + if(!skeleton) + if(husk) + base_icon.ColorTone(husk_color_mod) + else if(hulk) + var/list/tone = ReadRGB(hulk_color_mod) + base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3])) + + //Handle husk overlay. + if(husk) + var/icon/mask = new(base_icon) + var/icon/husk_over = new(race_icon,"overlay_husk") + mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) + husk_over.Blend(mask, ICON_ADD) + base_icon.Blend(husk_over, ICON_OVERLAY) + + + //Skin tone. + if(!husk && !hulk) + if(species.flags & HAS_SKIN_TONE) + if(s_tone >= 0) + base_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + base_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + + human_icon_cache[icon_key] = base_icon + + log_debug("Generated new cached mob icon ([icon_key] \icon[human_icon_cache[icon_key]]) for [src]. [human_icon_cache.len] cached mob icons.") + + //END CACHED ICON GENERATION. + + stand_icon.Blend(base_icon,ICON_OVERLAY) + + //Skin colour. Not in cache because highly variable (and relatively benign). + if (species.flags & HAS_SKIN_COLOR) stand_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) - if(husk) - var/icon/mask = new(stand_icon) - var/icon/husk_over = new(race_icon,"overlay_husk") - mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) - husk_over.Blend(mask, ICON_ADD) - stand_icon.Blend(husk_over, ICON_OVERLAY) - if(has_head) //Eyes if(!skeleton) @@ -341,6 +402,8 @@ proc/get_damage_icon_part(damage_state, body_part) update_tail_showing(0) + + //HAIR OVERLAY /mob/living/carbon/human/proc/update_hair(var/update_icons=1) //Reset our hair diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index b8bc3adc851..0c91bb073fd 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -46,9 +46,6 @@ var/list/abilities = list() // For species-derived or admin-given powers - var/blood_color = "#A10808" // Red. - var/flesh_color = "#FFC896" // Pink. - var/uniform_icons = 'icons/mob/uniform.dmi' var/fat_uniform_icons = 'icons/mob/uniform_fat.dmi' var/gloves_icons = 'icons/mob/hands.dmi' @@ -60,6 +57,13 @@ var/wear_mask_icons = 'icons/mob/mask.dmi' var/back_icons = 'icons/mob/back.dmi' + var/blood_color = "#A10808" //Red. + var/flesh_color = "#FFC896" //Pink. + + //Used in icon caching. + var/race_key = 0 + var/icon/icon_template + /datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. //This is a basic humanoid limb setup. H.organs = list() @@ -242,6 +246,7 @@ flesh_color = "#808D11" tail = "armalis_tail" + icon_template = 'icons/mob/human_races/r_armalis.dmi' wear_mask_icons = 'icons/mob/species/vox/armalis/mask.dmi' shoes_icons = 'icons/mob/species/vox/armalis/shoes.dmi' diff --git a/icons/mob/human_races/r_armalis.dmi b/icons/mob/human_races/r_armalis.dmi index 9013f485a857295c9b2824a42c59937007a8f4f7..b7609d942759dc5c44177a41064a9455bb2a10e9 100644 GIT binary patch delta 211 zcmV;^04)FEAL$>k2?2k+dQ@0+L}hbha%pgMX>V=-0C=2@(yc)yJ^+c z#k6TU*jFGJXdzNAIZ)%<+uA{$xa|nv{nM4=+;;sSnoG|g2BU)@PU5($ID0ys?D9D5 zIkU!1HmyGuk4Yu7j0G$UUcIEf$6LXfb{JQ|*@$X3>s)`aHA+Uyk;djMOMnpwxy|K! z6M_qb-sbW>lnV38lN3s;f+oaB45c>{Ax2RsM}S0#k=WI%@N-A?pDIN=G@mPd1C|WK NCN~&ET(iaj8xGs0Vq^dS delta 203 zcmV;+05t#UAK@Rc2?2k!dQ@0+L}hbha%pgMX>V=-0C=2@(!CDCAP~UunR^P-?xudM zE~bs?U|)fdKnsy_$$=W*-qsFoa@&#n@t>}im+smRvc2{2w3IwXd6uVL1LEaPcFW^< z0O72kTwXT~q^z@D#tN4YLBExIq(J*2xMk?5e5#uOQBVuO6{;^tiL;JnI4>yRofL`LA`?Jmg F8xE8pW?BFM