From 646aad945e67ccfa15df55d3f9eb941eac4dde27 Mon Sep 17 00:00:00 2001 From: JimTheCactus Date: Sun, 27 Jul 2014 17:21:19 -0600 Subject: [PATCH] Merged getFlatIcon rendering from tgstation Based on tgstation #2826. This is not all of it though. --- code/__HELPERS/icons.dm | 96 +++++++++++++++++++++++++------------ code/__HELPERS/type2type.dm | 7 +++ code/datums/datacore.dm | 2 +- 3 files changed, 73 insertions(+), 32 deletions(-) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 0ca515486b..d193fcb26e 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -634,20 +634,60 @@ as a single icon. Useful for when you want to manipulate an icon via the above a The _flatIcons list is a cache for generated icon files. */ -proc - getFlatIcon(atom/A, dir) // 1 = use cache, 2 = override cache, 0 = ignore cache +proc // Creates a single icon from a given /atom or /image. Only the first argument is required. + getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode) + // We start with a blank canvas, otherwise some icon procs crash silently + var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon + if(!A) + return flat + if(A.alpha <= 0) + return flat + var/noIcon = FALSE + + var/curicon + if(A.icon) + curicon = A.icon + else + curicon = deficon + + if(!curicon) + noIcon = TRUE // Do not render this object. + + var/curstate + if(A.icon_state) + curstate = A.icon_state + else + curstate = defstate + + if(!noIcon && !(curstate in icon_states(curicon))) + if("" in icon_states(curicon)) + curstate = "" + else + noIcon = TRUE // Do not render this object. + + var/curdir + if(A.dir) + curdir = A.dir + else + curdir = defdir + + var/curblend + if(A.blend_mode == BLEND_DEFAULT) + curblend = defblend + else + curblend = A.blend_mode + // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() - - // Add the atom's icon itself - if(A.icon) - // Make a copy without pixel_x/y settings - var/image/copy = image(icon=A.icon,icon_state=A.icon_state,layer=A.layer,dir=A.dir) + var/image/copy + // Add the atom's icon itself, without pixel_x/y offsets. + if(!noIcon) + copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) + copy.color = A.color + copy.alpha = A.alpha + copy.blend_mode = curblend layers[copy] = A.layer - // dir defaults to A's dir - if(!dir) dir = A.dir - // Loop through the underlays, then overlays, sorting them into the layers list var/list/process = A.underlays // Current list being processed var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays @@ -662,7 +702,7 @@ proc if(!current) continue currentLayer = current:layer if(currentLayer<0) // Special case for FLY_LAYER - if(currentLayer <= -1000) return 0 + if(currentLayer <= -1000) return flat if(pSet == 0) // Underlay currentLayer = A.layer+currentLayer/1000 else // Overlay @@ -688,8 +728,6 @@ proc else // All done break - // We start with a blank canvas, otherwise some icon procs crash silently - var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon var/icon/add // Icon of overlay being added // Current dimensions of flattened icon @@ -699,24 +737,15 @@ proc for(var/I in layers) - if(I:icon) - if(I:icon_state) - // Has icon and state set - add = icon(I:icon, I:icon_state) - else - if(A.icon_state in icon_states(I:icon)) - // Inherits icon_state from atom - add = icon(I:icon, A.icon_state) - else - // Uses default state ("") - add = icon(I:icon) - else if(I:icon_state) - // Inherits icon from atom - add = icon(A.icon, I:icon_state) - else - // Unknown + if(I:alpha == 0) continue + if(I == copy) // 'I' is an /image based on the object being flattened. + curblend = BLEND_OVERLAY + add = icon(I:icon, I:icon_state, I:dir) + else // 'I' is an appearance object. + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) + // Find the new dimensions of the flat icon to fit the added overlay addX1 = min(flatX1, I:pixel_x+1) addX2 = max(flatX2, I:pixel_x+add.Width()) @@ -730,9 +759,14 @@ proc flatY1=addY1;flatY2=addY2 // Blend the overlay into the flattened icon - flat.Blend(add,ICON_OVERLAY,I:pixel_x+2-flatX1,I:pixel_y+2-flatY1) + flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) - return flat + if(A.color) + flat.Blend(A.color, ICON_MULTIPLY) + if(A.alpha < 255) + flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + + return icon(flat, "", SOUTH) getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 885de82c44..8c188d0d18 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -298,6 +298,13 @@ proc/tg_list2text(list/list, glue=",") /proc/angle2text(var/degree) return dir2text(angle2dir(degree)) +//Converts a blend_mode constant to one acceptable to icon.Blend() +/proc/blendMode2iconMode(blend_mode) + switch(blend_mode) + if(BLEND_MULTIPLY) return ICON_MULTIPLY + if(BLEND_ADD) return ICON_ADD + if(BLEND_SUBTRACT) return ICON_SUBTRACT + else return ICON_OVERLAY //Converts a rights bitfield into a string /proc/rights2text(rights,seperator="") diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 98da4a58de..a1a626313b 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -119,7 +119,7 @@ L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.SE // Used in respawning L.fields["identity"] = H.dna.UI // " - L.fields["image"] = getFlatIcon(H,0) //This is god-awful + L.fields["image"] = getFlatIcon(H) //This is god-awful locked += L return