Skip to content

Commit

Permalink
Get Flat Icon Fixes (#4505)
Browse files Browse the repository at this point in the history
# About the pull request

This PR fixes two issues with getFlatIcon: It failing to properly resize
its template dimensions to whatever icon dimensions it was passed, and
it ignoring appearance_flags for RESET_COLOR and RESET_ALPHA. This was
done to address issues with #4475 but can be even more performance
costly than it already was because now it applies color and alpha blends
per overlay/underlay layer rather than once per recursive call if there
is a color/alpha to apply.

# Explain why it's good for the game

Fixes the broader potential uses for getFlatIcon such as flattening the
tacmap.

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Example of tacmap flattened prior to dimension fixes: 

![image](https://github.com/cmss13-devs/cmss13/assets/76988376/d74dcfcf-bd13-47bb-ae04-ef6caa281bae)

Example of tacmap flatted prior to color fixes: 

![image](https://github.com/cmss13-devs/cmss13/assets/76988376/81fb7d26-7c10-485b-8f5c-bc153ffbf74c)

Example of tacmap properly flattened: 

![image](https://github.com/cmss13-devs/cmss13/assets/76988376/0923382e-6dd5-44f6-8d72-9343784e26f1)

</details>


# Changelog
:cl: Drathek
fix: Fix getFlatIcon not resizing its template nor respect
appearance_flags of RESET_COLOR and RESET_ALPHA
/:cl:
  • Loading branch information
Drulikar authored Oct 4, 2023
1 parent e90e945 commit eb614a6
Showing 1 changed file with 38 additions and 14 deletions.
52 changes: 38 additions & 14 deletions code/__HELPERS/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ world
/// appearance system (overlays/underlays, etc.) is not available.
///
/// Only the first argument is required.
/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
/// appearance_flags indicates whether appearance_flags should be respected (at the cost of about 10-20% perf)
/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE, appearance_flags = FALSE)
// Loop through the underlays, then overlays, sorting them into the layers list
#define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \
for (var/i in 1 to process.len) { \
Expand Down Expand Up @@ -435,11 +436,21 @@ world
if(layer_image.alpha == 0)
continue

// variables only relevant when accounting for appearance_flags:
var/apply_color = TRUE
var/apply_alpha = TRUE

if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir)
else // 'I' is an appearance object.
add = getFlatIcon(image(layer_image), curdir, curicon, curstate, curblend, FALSE, no_anim)
var/image/layer_as_image = image(layer_image)
if(appearance_flags)
if(layer_as_image.appearance_flags & RESET_COLOR)
apply_color = FALSE
if(layer_as_image.appearance_flags & RESET_ALPHA)
apply_alpha = FALSE
add = getFlatIcon(layer_as_image, curdir, curicon, curstate, curblend, FALSE, no_anim, appearance_flags)
if(!add)
continue

Expand All @@ -451,9 +462,9 @@ world

if (
addX1 != flatX1 \
&& addX2 != flatX2 \
&& addY1 != flatY1 \
&& addY2 != flatY2 \
|| addX2 != flatX2 \
|| addY1 != flatY1 \
|| addY2 != flatY2 \
)
// Resize the flattened icon so the new icon fits
flat.Crop(
Expand All @@ -464,21 +475,34 @@ world
)

flatX1 = addX1
flatX2 = addY1
flatY1 = addX2
flatX2 = addX2
flatY1 = addY1
flatY2 = addY2

if(appearance_flags)
// apply parent's color/alpha to the added layers if the layer didn't opt
if(apply_color && appearance.color)
if(islist(appearance.color))
add.MapColors(arglist(appearance.color))
else
add.Blend(appearance.color, ICON_MULTIPLY)

if(apply_alpha && appearance.alpha < 255)
add.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)

// Blend the overlay into the flattened icon
flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1)

if(appearance.color)
if(islist(appearance.color))
flat.MapColors(arglist(appearance.color))
else
flat.Blend(appearance.color, ICON_MULTIPLY)
if(!appearance_flags)
// If we didn't apply parent colors individually per layer respecting appearance_flags, then do it just the one time now
if(appearance.color)
if(islist(appearance.color))
flat.MapColors(arglist(appearance.color))
else
flat.Blend(appearance.color, ICON_MULTIPLY)

if(appearance.alpha < 255)
flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
if(appearance.alpha < 255)
flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)

if(no_anim)
//Clean up repeated frames
Expand Down

0 comments on commit eb614a6

Please sign in to comment.