mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge pull request #5091 from drexample/master
Fixes cameras making completely black photos
This commit is contained in:
@@ -634,26 +634,16 @@ 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.
|
||||
*/
|
||||
|
||||
// Creates a single icon from a given /atom or /image. Only the first argument is required.
|
||||
/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
|
||||
// Creates a single icon from a given /atom or /image. Only the first argument is required.
|
||||
/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
|
||||
var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon
|
||||
var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon
|
||||
if(!A)
|
||||
return flat
|
||||
if(A.alpha <= 0)
|
||||
return flat
|
||||
var/noIcon = FALSE
|
||||
|
||||
if(start)
|
||||
if(!defdir)
|
||||
defdir = A.dir
|
||||
if(!deficon)
|
||||
deficon = A.icon
|
||||
if(!defstate)
|
||||
defstate = A.icon_state
|
||||
if(!defblend)
|
||||
defblend = A.blend_mode
|
||||
|
||||
var/curicon
|
||||
if(A.icon)
|
||||
curicon = A.icon
|
||||
@@ -676,31 +666,10 @@ The _flatIcons list is a cache for generated icon files.
|
||||
noIcon = TRUE // Do not render this object.
|
||||
|
||||
var/curdir
|
||||
var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
|
||||
|
||||
//These should use the parent's direction (most likely)
|
||||
if(!A.dir || A.dir == SOUTH)
|
||||
curdir = defdir
|
||||
else
|
||||
if(A.dir != 2 && !always_use_defdir)
|
||||
curdir = A.dir
|
||||
|
||||
//Let's check if the icon actually contains any diagonals, just skip if it's south to save (lot of) time
|
||||
if(curdir != SOUTH)
|
||||
var/icon/test_icon
|
||||
var/directionals_exist = FALSE
|
||||
var/list/dirs_to_check = cardinal - SOUTH
|
||||
outer:
|
||||
for(var/possible_dir in dirs_to_check)
|
||||
test_icon = icon(curicon,curstate,possible_dir,frame=1)
|
||||
for(var/x in 1 to world.icon_size)
|
||||
for(var/y in 1 to world.icon_size)
|
||||
if(!isnull(test_icon.GetPixel(x,y)))
|
||||
directionals_exist = TRUE
|
||||
break outer
|
||||
if(!directionals_exist)
|
||||
base_icon_dir = SOUTH
|
||||
if(!base_icon_dir)
|
||||
base_icon_dir = curdir
|
||||
else
|
||||
curdir = defdir
|
||||
|
||||
var/curblend
|
||||
if(A.blend_mode == BLEND_DEFAULT)
|
||||
@@ -708,18 +677,12 @@ The _flatIcons list is a cache for generated icon files.
|
||||
else
|
||||
curblend = A.blend_mode
|
||||
|
||||
// Before processing overlays, make sure any pending overlays are applied
|
||||
if (isloc(A))
|
||||
var/atom/aAtom = A
|
||||
if(aAtom.flags & OVERLAY_QUEUED)
|
||||
COMPILE_OVERLAYS(aAtom)
|
||||
|
||||
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
|
||||
var/list/layers = list()
|
||||
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=base_icon_dir)
|
||||
copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir)
|
||||
copy.color = A.color
|
||||
copy.alpha = A.alpha
|
||||
copy.blend_mode = curblend
|
||||
@@ -736,71 +699,78 @@ The _flatIcons list is a cache for generated icon files.
|
||||
while(TRUE)
|
||||
if(curIndex<=process.len)
|
||||
current = process[curIndex]
|
||||
if(!current)
|
||||
curIndex++ //Try the next layer
|
||||
continue
|
||||
var/image/I = current
|
||||
if(I.plane != FLOAT_PLANE && I.plane != A.plane)
|
||||
curIndex++
|
||||
continue
|
||||
currentLayer = I.layer
|
||||
if(currentLayer<0) // Special case for FLOAT_LAYER
|
||||
if(currentLayer <= -1000)
|
||||
return flat
|
||||
if(pSet == 0) // Underlay
|
||||
currentLayer = A.layer+currentLayer/1000
|
||||
else // Overlay
|
||||
currentLayer = A.layer+(1000+currentLayer)/1000
|
||||
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
|
||||
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
|
||||
// Sort add into layers list
|
||||
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++
|
||||
|
||||
if(curIndex>process.len)
|
||||
if(pSet == 0) // Switch to overlays
|
||||
curIndex = 1
|
||||
pSet = 1
|
||||
process = A.overlays
|
||||
else // All done
|
||||
break
|
||||
else if(pSet == 0) // Switch to overlays
|
||||
curIndex = 1
|
||||
pSet = 1
|
||||
process = A.overlays
|
||||
else // All done
|
||||
break
|
||||
|
||||
var/icon/add // Icon of overlay being added
|
||||
|
||||
// Current dimensions of flattened icon
|
||||
var/flatX1=1
|
||||
var/flatX2=flat.Width()
|
||||
var/flatY1=1
|
||||
var/flatY2=flat.Height()
|
||||
// Dimensions of overlay being added
|
||||
var/addX1
|
||||
var/addX2
|
||||
var/addY1
|
||||
var/addY2
|
||||
// Current dimensions of flattened icon
|
||||
var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()}
|
||||
// Dimensions of overlay being added
|
||||
var/{addX1;addX2;addY1;addY2}
|
||||
|
||||
for(var/V in layers)
|
||||
var/image/I = V
|
||||
if(I.alpha == 0)
|
||||
for(var/I in layers)
|
||||
|
||||
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, base_icon_dir)
|
||||
add = icon(I:icon, I:icon_state, I:dir)
|
||||
// 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:dir != SOUTH && add.Width() == 32 && add.Height() == 32)
|
||||
// Check every pixel for blank (computationally expensive, but the process is limited
|
||||
// by the amount of film on the station, only happens when we hit something that's
|
||||
// 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)
|
||||
break
|
||||
// If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0)
|
||||
if (blankpixel)
|
||||
// Pull the default direction.
|
||||
add = icon(I:icon, I:icon_state)
|
||||
else // 'I' is an appearance object.
|
||||
add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, FALSE, no_anim)
|
||||
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
|
||||
addX1 = min(flatX1, I.pixel_x+1)
|
||||
addX2 = max(flatX2, I.pixel_x+add.Width())
|
||||
addY1 = min(flatY1, I.pixel_y+1)
|
||||
addY2 = max(flatY2, I.pixel_y+add.Height())
|
||||
addX1 = min(flatX1, I:pixel_x+1)
|
||||
addX2 = max(flatX2, I:pixel_x+add.Width())
|
||||
addY1 = min(flatY1, I:pixel_y+1)
|
||||
addY2 = max(flatY2, I:pixel_y+add.Height())
|
||||
|
||||
if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
|
||||
// Resize the flattened icon so the new icon fits
|
||||
@@ -809,20 +779,14 @@ The _flatIcons list is a cache for generated icon files.
|
||||
flatY1=addY1;flatY2=addY2
|
||||
|
||||
// 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)
|
||||
flat.Blend(A.color, ICON_MULTIPLY)
|
||||
if(A.alpha < 255)
|
||||
flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
|
||||
|
||||
if(no_anim)
|
||||
//Clean up repeated frames
|
||||
var/icon/cleaned = new /icon()
|
||||
cleaned.Insert(flat, "", SOUTH, 1, 0)
|
||||
return cleaned
|
||||
else
|
||||
return icon(flat, "", SOUTH)
|
||||
return icon(flat, "", SOUTH)
|
||||
|
||||
/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.
|
||||
@@ -835,10 +799,10 @@ The _flatIcons list is a cache for generated icon files.
|
||||
|
||||
//getFlatIcon but generates an icon that can face ALL four directions. The only four.
|
||||
/proc/getCompoundIcon(atom/A)
|
||||
var/icon/north = getFlatIcon(A,defdir=NORTH)
|
||||
var/icon/south = getFlatIcon(A,defdir=SOUTH)
|
||||
var/icon/east = getFlatIcon(A,defdir=EAST)
|
||||
var/icon/west = getFlatIcon(A,defdir=WEST)
|
||||
var/icon/north = getFlatIcon(A,defdir=NORTH,always_use_defdir=1)
|
||||
var/icon/south = getFlatIcon(A,defdir=SOUTH,always_use_defdir=1)
|
||||
var/icon/east = getFlatIcon(A,defdir=EAST,always_use_defdir=1)
|
||||
var/icon/west = getFlatIcon(A,defdir=WEST,always_use_defdir=1)
|
||||
|
||||
//Starts with a blank icon because of byond bugs.
|
||||
var/icon/full = icon('icons/effects/effects.dmi', "icon_state"="nothing")
|
||||
@@ -854,7 +818,7 @@ The _flatIcons list is a cache for generated icon files.
|
||||
return full
|
||||
|
||||
/proc/downloadImage(atom/A, dir)
|
||||
var/icon/this_icon = getFlatIcon(A,defdir=dir)
|
||||
var/icon/this_icon = getFlatIcon(A,defdir=dir||A.dir,always_use_defdir=1)
|
||||
|
||||
usr << ftp(this_icon,"[A.name].png")
|
||||
|
||||
@@ -922,8 +886,7 @@ proc/sort_atoms_by_layer(var/list/atoms)
|
||||
/proc/gen_hud_image(var/file, var/person, var/state, var/plane)
|
||||
var/image/img = image(file, person, state)
|
||||
img.plane = plane //Thanks Byond.
|
||||
img.layer = MOB_LAYER-0.2
|
||||
img.appearance_flags = APPEARANCE_UI
|
||||
img.appearance_flags = APPEARANCE_UI|KEEP_APART
|
||||
return img
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user