mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
absolute pathing
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user