Wall Icon Refactor (#3023)

changes:

Atom types can now define custom adjacency code for the smoothing system.
Walls now draw using the generic icon smoothing system.
Walls now pre-bake colors into their icons instead of doing it client-side with the color var.
Walls can now use the SSoverlay appearance cache; wall icon updates should be faster.
The "rusty" wall type now actually works.
Smoothing now uses mutable_appearance instead of image in some places.
Should be a bit easier on clients, though I haven't done profiling.

This PR breaks 510 compatibility.
This commit is contained in:
Lohikar
2017-07-15 08:22:21 -05:00
committed by skull132
parent 1bda977ae7
commit 41e39f52d1
12 changed files with 208 additions and 72 deletions

View File

@@ -69,60 +69,62 @@
/turf/unsimulated/wall
smooth_underlays = TRUE
/proc/calculate_adjacencies(atom/A)
if(!A.loc)
/atom/proc/calculate_adjacencies()
if (!loc)
return 0
var/adjacencies = 0
var/atom/movable/AM
if(istype(A, /atom/movable))
AM = A
if(AM.can_be_unanchored && !AM.anchored)
return 0
for(var/direction in cardinal)
AM = find_type_in_direction(A, direction)
AM = find_type_in_direction(src, direction)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
if((smooth & SMOOTH_BORDER))
adjacencies |= 1 << direction
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= 1 << direction
if(adjacencies & N_NORTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, NORTHWEST)
AM = find_type_in_direction(src, NORTHWEST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
if((smooth & SMOOTH_BORDER))
adjacencies |= N_NORTHWEST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, NORTHEAST)
AM = find_type_in_direction(src, NORTHEAST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
if((smooth & SMOOTH_BORDER))
adjacencies |= N_NORTHEAST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHEAST
if(adjacencies & N_SOUTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, SOUTHWEST)
AM = find_type_in_direction(src, SOUTHWEST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
if((smooth & SMOOTH_BORDER))
adjacencies |= N_SOUTHWEST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, SOUTHEAST)
AM = find_type_in_direction(src, SOUTHEAST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
if((smooth & SMOOTH_BORDER))
adjacencies |= N_SOUTHEAST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHEAST
return adjacencies
/atom/movable/calculate_adjacencies()
if (can_be_unanchored && !anchored)
return 0
return ..()
//do not use, use queue_smooth(atom)
/proc/smooth_icon(atom/A)
if(!A || !A.smooth)
@@ -133,7 +135,7 @@
if(QDELETED(A))
return
if((A.smooth & SMOOTH_TRUE) || (A.smooth & SMOOTH_MORE))
var/adjacencies = calculate_adjacencies(A)
var/adjacencies = A.calculate_adjacencies()
if(A.smooth & SMOOTH_DIAGONAL)
A.diagonal_smooth(adjacencies)
@@ -172,7 +174,7 @@
if (smooth_underlays && adjacencies)
// This should be a mutable_appearance, but we're still on 510.
// Alas.
var/image/underlay_appearance = image(layer = TURF_LAYER)
var/mutable_appearance/underlay_appearance = new(layer = TURF_LAYER)
var/list/U = list(underlay_appearance)
if(fixed_underlay)
if(fixed_underlay["space"])
@@ -257,33 +259,103 @@
se = "4-e"
var/list/New
var/list/Old
if(A.top_left_corner != nw)
A.cut_overlay(A.top_left_corner)
if (A.top_left_corner)
LAZYADD(Old, A.top_left_corner)
A.top_left_corner = nw
LAZYADD(New, nw)
if(A.top_right_corner != ne)
A.cut_overlay(A.top_right_corner)
if (A.top_right_corner)
LAZYADD(Old, A.top_right_corner)
A.top_right_corner = ne
LAZYADD(New, ne)
if(A.bottom_right_corner != sw)
A.cut_overlay(A.bottom_right_corner)
if (A.bottom_right_corner)
LAZYADD(Old, A.bottom_right_corner)
A.bottom_right_corner = sw
LAZYADD(New, sw)
if(A.bottom_left_corner != se)
A.cut_overlay(A.bottom_left_corner)
if (A.bottom_left_corner)
LAZYADD(Old, A.bottom_left_corner)
A.bottom_left_corner = se
LAZYADD(New, se)
if(Old)
A.cut_overlay(Old)
if(New)
A.add_overlay(New)
if (A.icon_state && !(A.smooth & SMOOTH_NO_CLEAR_ICON))
A.icon_state = null
// A more stripped down version of the above, meant for using images to apply multiple smooth overlays
// at once.
/proc/cardinal_smooth_fromicon(icon/I, adjacencies)
//NW CORNER
var/nw = "1-i"
if((adjacencies & N_NORTH) && (adjacencies & N_WEST))
if(adjacencies & N_NORTHWEST)
nw = "1-f"
else
nw = "1-nw"
else
if(adjacencies & N_NORTH)
nw = "1-n"
else if(adjacencies & N_WEST)
nw = "1-w"
//NE CORNER
var/ne = "2-i"
if((adjacencies & N_NORTH) && (adjacencies & N_EAST))
if(adjacencies & N_NORTHEAST)
ne = "2-f"
else
ne = "2-ne"
else
if(adjacencies & N_NORTH)
ne = "2-n"
else if(adjacencies & N_EAST)
ne = "2-e"
//SW CORNER
var/sw = "3-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_WEST))
if(adjacencies & N_SOUTHWEST)
sw = "3-f"
else
sw = "3-sw"
else
if(adjacencies & N_SOUTH)
sw = "3-s"
else if(adjacencies & N_WEST)
sw = "3-w"
//SE CORNER
var/se = "4-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_EAST))
if(adjacencies & N_SOUTHEAST)
se = "4-f"
else
se = "4-se"
else
if(adjacencies & N_SOUTH)
se = "4-s"
else if(adjacencies & N_EAST)
se = "4-e"
var/image/nw_i = image(I, nw)
var/image/ne_i = image(I, ne)
var/image/sw_i = image(I, sw)
var/image/se_i = image(I, se)
return list(nw_i, ne_i, sw_i, se_i)
/proc/find_type_in_direction(atom/source, direction)
var/turf/target_turf = get_step(source, direction)
if(!target_turf)
@@ -332,13 +404,10 @@
queue_smooth(A)
/atom/proc/clear_smooth_overlays()
cut_overlay(top_left_corner)
cut_overlay(list(top_left_corner, top_right_corner, bottom_left_corner, bottom_right_corner))
top_left_corner = null
cut_overlay(top_right_corner)
top_right_corner = null
cut_overlay(bottom_right_corner)
bottom_right_corner = null
cut_overlay(bottom_left_corner)
bottom_left_corner = null
/atom/proc/replace_smooth_overlays(nw, ne, sw, se)

View File

@@ -11,6 +11,9 @@
material = get_material_by_name(DEFAULT_WALL_MATERIAL)
if(material)
explosion_resistance = material.explosion_resistance
if (material.wall_icon)
icon = material.wall_icon
if(reinf_material && reinf_material.explosion_resistance > explosion_resistance)
explosion_resistance = reinf_material.explosion_resistance
@@ -26,10 +29,8 @@
else if(material.opacity < 0.5 && opacity)
set_light(0)
update_connections(1)
update_icon()
/turf/simulated/wall/proc/set_material(var/material/newmaterial, var/material/newrmaterial)
material = newmaterial
reinf_material = newrmaterial
@@ -42,37 +43,43 @@
if(!damage_overlays[1]) //list hasn't been populated
generate_overlays()
cut_overlays()
var/list/cutlist = (reinforcement_images||list()) + damage_image
cut_overlay(cutlist, TRUE)
LAZYCLEARLIST(reinforcement_images)
damage_image = null
var/list/overlays_to_add = list()
var/image/I
if(!density)
I = image('icons/turf/wall_masks.dmi', "[material.icon_base]fwall_open")
I.color = material.icon_colour
add_overlay(I)
if (!density) // We're a fake and we're open.
clear_smooth_overlays()
fake_wall_image = image('icons/turf/wall_masks.dmi', "[material.icon_base]fwall_open")
fake_wall_image.color = material.icon_colour
add_overlay(fake_wall_image)
smooth = SMOOTH_FALSE
return
else if (fake_wall_image)
cut_overlay(fake_wall_image)
fake_wall_image = null
smooth = initial(smooth)
for(var/i = 1 to 4)
I = image('icons/turf/wall_masks.dmi', "[material.icon_base][wall_connections[i]]", dir = 1<<(i-1))
I.color = material.icon_colour
overlays_to_add += I
calculate_adjacencies() // Update cached_adjacency
if(reinf_material)
var/image/I
if(construction_stage != null && construction_stage < 6)
I = image('icons/turf/wall_masks.dmi', "reinf_construct-[construction_stage]")
I.color = reinf_material.icon_colour
overlays_to_add += I
LAZYADD(reinforcement_images, I)
else
if("[reinf_material.icon_reinf]0" in icon_states('icons/turf/wall_masks.dmi'))
// Directional icon
for(var/i = 1 to 4)
I = image('icons/turf/wall_masks.dmi', "[reinf_material.icon_reinf][wall_connections[i]]", dir = 1<<(i-1))
I.color = reinf_material.icon_colour
overlays_to_add += I
if (reinf_material.multipart_reinf_icon)
LAZYADD(reinforcement_images, cardinal_smooth_fromicon(reinf_material.multipart_reinf_icon, cached_adjacency))
else
I = image('icons/turf/wall_masks.dmi', reinf_material.icon_reinf)
I.color = reinf_material.icon_colour
overlays_to_add += I
LAZYADD(reinforcement_images, I)
if (reinforcement_images)
overlays_to_add += reinforcement_images
if(damage != 0)
var/integrity = material.integrity
@@ -83,9 +90,12 @@
if(overlay > damage_overlays.len)
overlay = damage_overlays.len
overlays_to_add += damage_overlays[overlay]
damage_image = damage_overlays[overlay]
overlays_to_add += damage_image
add_overlay(overlays_to_add)
add_overlay(overlays_to_add, TRUE)
UNSETEMPTY(reinforcement_images)
queue_smooth(src)
/turf/simulated/wall/proc/generate_overlays()
var/alpha_inc = 256 / damage_overlays.len
@@ -96,23 +106,50 @@
img.alpha = (i * alpha_inc) - 1
damage_overlays[i] = img
/turf/simulated/wall/proc/update_connections(propagate = 0)
if(!material)
/turf/simulated/wall/calculate_adjacencies()
. = 0
if (!loc || !material)
return
var/list/dirs = list()
for(var/turf/simulated/wall/W in orange(src, 1))
if(!W.material)
continue
if(propagate)
W.update_connections()
W.update_icon()
if(can_join_with(W))
dirs += get_dir(src, W)
wall_connections = dirs_to_corner_states(dirs)
var/turf/simulated/wall/W
var/material/M
var/our_icon_base = material.icon_base
/turf/simulated/wall/proc/can_join_with(var/turf/simulated/wall/W)
if(material && W.material && material.icon_base == W.material.icon_base)
return 1
return 0
for (var/dir in cardinal)
W = get_step(src, dir)
if (istype(W) && (W.smooth || !W.density))
M = W.material
if (M && M.icon_base == our_icon_base)
. |= 1 << dir
if (. & N_NORTH)
if (. & N_WEST)
W = get_step(src, NORTHWEST)
if (istype(W) && (W.smooth || !W.density))
M = W.material
if (M && M.icon_base == our_icon_base)
. |= N_NORTHWEST
if (. & N_EAST)
W = get_step(src, NORTHEAST)
if (istype(W) && (W.smooth || !W.density))
M = W.material
if (M && M.icon_base == our_icon_base)
. |= N_NORTHEAST
if (. & N_SOUTH)
if (. & N_WEST)
W = get_step(src, SOUTHWEST)
if (istype(W) && (W.smooth || !W.density))
M = W.material
if (M && M.icon_base == our_icon_base)
. |= N_SOUTHWEST
if (. & N_EAST)
W = get_step(src, SOUTHEAST)
if (istype(W) && (W.smooth || !W.density))
M = W.material
if (M && M.icon_base == our_icon_base)
. |= N_SOUTHEAST
cached_adjacency = .

View File

@@ -19,7 +19,12 @@
var/last_state
var/construction_stage
var/list/wall_connections = list("0", "0", "0", "0")
var/tmp/list/image/reinforcement_images
var/tmp/image/damage_image
var/tmp/image/fake_wall_image
var/tmp/cached_adjacency
smooth = SMOOTH_TRUE | SMOOTH_NO_CLEAR_ICON
// Walls always hide the stuff below them.
/turf/simulated/wall/levelupdate(mapload)
@@ -178,7 +183,6 @@
clear_plants()
material = get_material_by_name("placeholder")
reinf_material = null
update_connections(1)
if (!no_change)
ChangeTurf(/turf/simulated/floor/plating)

View File

@@ -81,9 +81,7 @@
..()
return QDEL_HINT_IWILLGC
// This should be using mutable_appearance, but 510. Woe.
// Update this & all overrides if/when we move to 511.
/turf/proc/get_smooth_underlay_icon(image/underlay_appearance, turf/asking_turf, adjacency_dir)
/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = icon
underlay_appearance.icon_state = icon_state
underlay_appearance.dir = adjacency_dir

View File

@@ -83,6 +83,8 @@ var/list/name_to_material
var/door_icon_base = "metal" // Door base icon tag. See header.
var/icon_reinf = "reinf_metal" // Overlay used
var/list/stack_origin_tech = list(TECH_MATERIAL = 1) // Research level for stacks.
var/icon/wall_icon
var/icon/multipart_reinf_icon
// Attributes
var/cut_delay = 0 // Delay in ticks when cutting through this wall.
@@ -153,6 +155,31 @@ var/list/name_to_material
if(!shard_icon)
shard_icon = shard_type
var/skip_blend = FALSE
switch (icon_base)
if ("solid")
wall_icon = 'icons/turf/smooth/composite_solid.dmi'
if ("stone")
wall_icon = 'icons/turf/smooth/composite_stone.dmi'
multipart_reinf_icon = 'icons/turf/smooth/composite_stone_reinf.dmi'
if ("metal")
wall_icon = 'icons/turf/smooth/composite_metal.dmi'
if ("cult")
wall_icon = 'icons/turf/smooth/cult_wall.dmi'
skip_blend = TRUE
if ("arust")
wall_icon = 'icons/turf/smooth/rusty_wall.dmi'
skip_blend = TRUE
else
world.log << "materials: [src] has unknown icon_base [icon_base]."
if (wall_icon && icon_colour && !skip_blend)
wall_icon = new(wall_icon)
wall_icon.Blend(icon_colour, ICON_MULTIPLY)
if (multipart_reinf_icon)
multipart_reinf_icon = new(multipart_reinf_icon)
multipart_reinf_icon.Blend(icon_colour, ICON_MULTIPLY)
// This is a placeholder for proper integration of windows/windoors into the system.
/material/proc/build_windows(var/mob/living/user, var/obj/item/stack/used_stack)
return 0
@@ -599,6 +626,7 @@ var/list/name_to_material
stack_type = null
icon_colour = "#B7410E"
icon_base = "arust"
icon_reinf = "reinf_over"
integrity = 250
explosion_resistance = 8
hardness = 15

View File

@@ -541,7 +541,7 @@
return INITIALIZE_HINT_NORMAL
/turf/simulated/floor/asteroid/get_smooth_underlay_icon(image/underlay_appearance, turf/asking_turf, adjacency_dir)
/turf/simulated/floor/asteroid/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
. = ..()
underlay_appearance.pixel_x = pixel_x
underlay_appearance.pixel_y = pixel_y

View File

@@ -102,7 +102,7 @@
return ..()
/turf/simulated/open/get_smooth_underlay_icon(image/underlay_appearance, turf/asking_turf, adjacency_dir)
/turf/simulated/open/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.appearance = src
return TRUE

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB