ID:2859363
 
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
We call Crop() 478 times in initialize on SS13, at the most conservative configuration. This costs 3 seconds+ on my i7-9700k. We are calling Crop() this much for a character menu--we are putting hair on a mock character, scaling it up, then cropping it, so that it only shows the head, and we're showing you all of them so you can visually see the potential hairstyles you can choose.

We do not want to cache the output of this or do any other tricks because the current system lets artists simply make the hair they want to make, and everything else will magically work without any possibility of going wrong.

We also cannot use CSS tricks to do the cropping on the client side. We have to combine all these into a spritesheet for maximum efficiency, but you cannot zoom in on pieces of a spritesheet without also losing nearest neighbor interpolation (even with -ms-interpolate-mode).

The new \ref stuff is cool, but will ultimately end up being much more complex code than what we are doing now. It would be great to use for a lot of our UI, but our character creation UI is simply too complex.

Currently to fix this, we are thinking of several hacky options like having a pre-compile step that pre-crops everything. I would like to not feel the need to do this. It would be great if Crop() was a lot faster.
Crop() is an icon operation. Icon operations are never going to be quick.

You can get the same results by using an alpha mask filter ircc. That should be much more efficient.
Alpha mask filters don't send through HTML. It is also absurd to completely give up and assume they can't be any faster and that a feature request to be faster isn't completely reasonable. The world can be a better place Meme01
Then I would think a better implementation would be to somehow allow filters to be compatible with HTML.
Logically I am cropping. So I call Crop(). Crop() is slow. The solution to that shouldn't be a separate hack that is meant to simulate the effects of crop.
In response to Jaredfogle
Jaredfogle wrote:
Logically I am cropping. So I call Crop(). Crop() is slow. The solution to that shouldn't be a separate hack that is meant to simulate the effects of crop.

You misunderstand. Alpha Masking is intended for cropping as well. That was the entire point -- to make cropping images in-game a quick and seamless endeavor.

Things like matrices, filters, animate (and so forth) were all created for the sole purpose of there being efficient ways to manipulate appearances.

This is like saying because there is a Scale() operation for icons that you shouldn't instead use matrices to dynamically change the size of a sprite.

Although, I can't articulate why precisely icon operations just are always going to be worse.

But yeah, imo. Use the updated features that was intended for what you're attempting to do
Although, I can't articulate why precisely icon operations just are always going to be worse.

Because they need to put the files in the dyn.rsc and transfer them to every player on demand. Doing it in the build setup isn't ideal for sure, but a very simple alpha masking setup can be constructed using vis_contents KEEP_TOGETHER, and BLEND_INSET_OVERLAY.



obj/maskpane
icon = 'masktest.dmi'
appearance_flags = KEEP_TOGETHER
var
obj/charpreview
obj/hairpreview

New()
charpreview = new/obj()
charpreview.icon = 'facetest.dmi'
charpreview.transform = matrix(2,0,0,0,2,-12)
charpreview.appearance_flags = PIXEL_SCALE
charpreview.blend_mode = BLEND_INSET_OVERLAY

hairpreview = new/obj()
hairpreview.icon = 'hairtest.dmi'
hairpreview.appearance_flags = PIXEL_SCALE

charpreview.vis_contents += hairpreview
vis_contents += charpreview
..()


There are tons of shortcuts you can take to achieve this effect, including merging the KT pass for a whole swarm of objects, or using a render target/source approach that would further allow you to control the outcome.

I overall agree that Crop() is slower than what is desirable.
Please stop XYZing ss13 devs who are just trying to improve the engine.

We asked for faster crop.

We did not ask for critiques on our design or ideas on how to change the entire layout of our UI to better fit the engine's shortcomings. This is neither the Developer Help forums nor the Design Philosophy forums.
In response to MrStonedOne
MrStonedOne wrote:
Please stop XYZing ss13 devs who are just trying to improve the engine.

We asked for faster crop.

We did not ask for critiques on our design or ideas on how to change the entire layout of our UI to better fit the engine's shortcomings. This is neither the Developer Help forums nor the Design Philosophy forums.

All fair points. Will purge all but the snippet. Had nothing to do with his subcommunity tho.
In response to Ter13
Ter13 wrote:
Because they need to put the files in the dyn.rsc and transfer them to every player on demand. Doing it in the build setup isn't ideal for sure, but a very simple alpha masking setup can be constructed using vis_contents KEEP_TOGETHER, and BLEND_INSET_OVERLAY.

There are tons of shortcuts you can take to achieve this effect, including merging the KT pass for a whole swarm of objects, or using a render target/source approach that would further allow you to control the outcome.

I overall agree that Crop() is slower than what is desirable.

This would work, already thought about it actually, except we want to physically shrink the appearance so it fits in the 32x32 spritesheets we generate.
We can't do that with just appearance modification, which means we can't say, cut around a human's head and scale it up to a usable size.

var/icon/head_icon = icon('icons/mob/species/human/bodyparts_greyscale.dmi', "human_head_m")
head_icon.Blend(skintone2hex("caucasian1"), ICON_MULTIPLY)

for (var/name in values)
var/datum/sprite_accessory/accessory = accessories[name]
if (accessory == null || accessory.icon_state == null)
continue

var/icon/final_icon = new(head_icon)

var/icon/beard_icon = values[name]
beard_icon.Blend(COLOR_DARK_BROWN, ICON_MULTIPLY)
final_icon.Blend(beard_icon, ICON_OVERLAY)

final_icon.Crop(10, 19, 22, 31)
final_icon.Scale(32, 32)

values[name] = final_icon

return values



That's the trouble here, we can't shrink the actual bounds of the appearance in how it's displayed. Least I don't think so, still need to hack together a resource loader for uis like this.