absolute pathing

This commit is contained in:
Drexian
2018-03-23 22:52:05 +03:00
parent 36594a3c1b
commit c25fa6dea2

View File

@@ -634,168 +634,168 @@ 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. The _flatIcons list is a cache for generated icon files.
*/ */
proc // Creates a single icon from a given /atom or /image. Only the first argument is required. // Creates a single icon from a given /atom or /image. Only the first argument is required.
getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD)) proc/getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD))
// We start with a blank canvas, otherwise some icon procs crash silently // 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/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon
if(!A) if(!A)
return flat return flat
if(A.alpha <= 0) if(A.alpha <= 0)
return flat return flat
var/noIcon = FALSE var/noIcon = FALSE
var/curicon var/curicon
if(A.icon) if(A.icon)
curicon = 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 else
curicon = deficon
if(!curicon)
noIcon = TRUE // Do not render this object. noIcon = TRUE // Do not render this object.
var/curstate var/curdir
if(A.icon_state) if(A.dir != 2 && !always_use_defdir)
curstate = A.icon_state curdir = A.dir
else else
curstate = defstate curdir = defdir
if(!noIcon && !(curstate in icon_states(curicon))) var/curblend
if("" in icon_states(curicon)) if(A.blend_mode == BLEND_DEFAULT)
curstate = "" curblend = defblend
else else
noIcon = TRUE // Do not render this object. curblend = A.blend_mode
var/curdir // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
if(A.dir != 2 && !always_use_defdir) var/list/layers = list()
curdir = A.dir var/image/copy
else // Add the atom's icon itself, without pixel_x/y offsets.
curdir = defdir 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
var/curblend // Loop through the underlays, then overlays, sorting them into the layers list
if(A.blend_mode == BLEND_DEFAULT) var/list/process = A.underlays // Current list being processed
curblend = defblend var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays
else var/curIndex=1 // index of 'current' in list being processed
curblend = A.blend_mode var/current // Current overlay being sorted
var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER)
var/compare // The overlay 'add' is being compared against
var/cmpIndex // The index in the layers list of 'compare'
while(TRUE)
if(curIndex<=process.len)
current = process[curIndex]
if(current)
var/currentPlane = current:plane
if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes))
curIndex++
continue;
currentLayer = current:layer
if(currentLayer<0) // Special case for FLY_LAYER
if(currentLayer <= -1000) return flat
if(pSet == 0) // Underlay
currentLayer = A.layer+currentLayer/1000
else // Overlay
currentLayer = A.layer+(1000+currentLayer)/1000
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed // Sort add into layers list
var/list/layers = list() for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++)
var/image/copy compare = layers[cmpIndex]
// Add the atom's icon itself, without pixel_x/y offsets. if(currentLayer < layers[compare]) // Associated value is the calculated layer
if(!noIcon) layers.Insert(cmpIndex,current)
copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) layers[current] = currentLayer
copy.color = A.color break
copy.alpha = A.alpha if(cmpIndex>layers.len) // Reached end of list without inserting
copy.blend_mode = curblend layers[current]=currentLayer // Place at end
layers[copy] = A.layer
// Loop through the underlays, then overlays, sorting them into the layers list curIndex++
var/list/process = A.underlays // Current list being processed else if(pSet == 0) // Switch to overlays
var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays curIndex = 1
var/curIndex=1 // index of 'current' in list being processed pSet = 1
var/current // Current overlay being sorted process = A.overlays
var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) else // All done
var/compare // The overlay 'add' is being compared against break
var/cmpIndex // The index in the layers list of 'compare'
while(TRUE)
if(curIndex<=process.len)
current = process[curIndex]
if(current)
var/currentPlane = current:plane
if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes))
curIndex++
continue;
currentLayer = current:layer
if(currentLayer<0) // Special case for FLY_LAYER
if(currentLayer <= -1000) return flat
if(pSet == 0) // Underlay
currentLayer = A.layer+currentLayer/1000
else // Overlay
currentLayer = A.layer+(1000+currentLayer)/1000
// Sort add into layers list var/icon/add // Icon of overlay being added
for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++)
compare = layers[cmpIndex]
if(currentLayer < layers[compare]) // Associated value is the calculated layer
layers.Insert(cmpIndex,current)
layers[current] = currentLayer
break
if(cmpIndex>layers.len) // Reached end of list without inserting
layers[current]=currentLayer // Place at end
curIndex++ // Current dimensions of flattened icon
else if(pSet == 0) // Switch to overlays var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()}
curIndex = 1 // Dimensions of overlay being added
pSet = 1 var/{addX1;addX2;addY1;addY2}
process = A.overlays
else // All done
break
var/icon/add // Icon of overlay being added for(var/I in layers)
// Current dimensions of flattened icon if(I:alpha == 0)
var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} continue
// Dimensions of overlay being added
var/{addX1;addX2;addY1;addY2}
for(var/I in layers) if(I == copy) // 'I' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
if(I:alpha == 0) add = icon(I:icon, I:icon_state, I:dir)
continue // This checks for a silent failure mode of the icon routine. If the requested dir
// doesn't exist in this icon state it returns a 32x32 icon with 0 alpha.
if(I == copy) // 'I' is an /image based on the object being flattened. if (I:dir != SOUTH && add.Width() == 32 && add.Height() == 32)
curblend = BLEND_OVERLAY // Check every pixel for blank (computationally expensive, but the process is limited
add = icon(I:icon, I:icon_state, I:dir) // by the amount of film on the station, only happens when we hit something that's
// This checks for a silent failure mode of the icon routine. If the requested dir // turned, and bails at the very first pixel it sees.
// doesn't exist in this icon state it returns a 32x32 icon with 0 alpha. var/blankpixel;
if (I:dir != SOUTH && add.Width() == 32 && add.Height() == 32) for(var/y;y<=32;y++)
// Check every pixel for blank (computationally expensive, but the process is limited for(var/x;x<32;x++)
// by the amount of film on the station, only happens when we hit something that's blankpixel = isnull(add.GetPixel(x,y))
// turned, and bails at the very first pixel it sees.
var/blankpixel;
for(var/y;y<=32;y++)
for(var/x;x<32;x++)
blankpixel = isnull(add.GetPixel(x,y))
if(!blankpixel)
break
if(!blankpixel) if(!blankpixel)
break break
// If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0) if(!blankpixel)
if (blankpixel) break
// Pull the default direction. // If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0)
add = icon(I:icon, I:icon_state) if (blankpixel)
else // 'I' is an appearance object. // Pull the default direction.
add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes) add = icon(I:icon, I:icon_state)
else // 'I' is an appearance object.
add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes)
// Find the new dimensions of the flat icon to fit the added overlay // Find the new dimensions of the flat icon to fit the added overlay
addX1 = min(flatX1, I:pixel_x+1) addX1 = min(flatX1, I:pixel_x+1)
addX2 = max(flatX2, I:pixel_x+add.Width()) addX2 = max(flatX2, I:pixel_x+add.Width())
addY1 = min(flatY1, I:pixel_y+1) addY1 = min(flatY1, I:pixel_y+1)
addY2 = max(flatY2, I:pixel_y+add.Height()) addY2 = max(flatY2, I:pixel_y+add.Height())
if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
// Resize the flattened icon so the new icon fits // Resize the flattened icon so the new icon fits
flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1)
flatX1=addX1;flatX2=addX2 flatX1=addX1;flatX2=addX2
flatY1=addY1;flatY2=addY2 flatY1=addY1;flatY2=addY2
// Blend the overlay into the flattened icon // Blend the overlay into the flattened icon
flat.Blend(add, blendMode2iconMode(curblend), 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)
if(A.color) if(A.color)
flat.Blend(A.color, ICON_MULTIPLY) flat.Blend(A.color, ICON_MULTIPLY)
if(A.alpha < 255) if(A.alpha < 255)
flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
return icon(flat, "", SOUTH) return icon(flat, "", SOUTH)
getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N proc/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. var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. if(I:layer>A.layer) continue//If layer is greater than what we need, skip it.
var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects.
//Also, icons cannot directly set icon_state. Slower than changing variables but whatever. //Also, icons cannot directly set icon_state. Slower than changing variables but whatever.
alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay.
return alpha_mask//And now return the mask. return alpha_mask//And now return the mask.
//getFlatIcon but generates an icon that can face ALL four directions. The only four. //getFlatIcon but generates an icon that can face ALL four directions. The only four.
/proc/getCompoundIcon(atom/A) /proc/getCompoundIcon(atom/A)