vgstation-coders/vgstation13

(Help Request) - Improved Frying Pan Sprite Generation

Open

#33,915 opened on Dec 29, 2022

View on GitHub
 (0 comments) (0 reactions) (0 assignees)DM (272 stars) (552 forks)batch import
Help Wanted

Description

I'd like to ask if anyone can please help me with something that I want to improve about how frying pan sprites are handled (copy-pasted from the BYOND forums where I also asked about this). There's also some feedback there that could possibly help indicate the right way to do this.

[When items are put into a frying pan,] ...it scales each ingredient down and renders it in the pan. To avoid the ingredients overlapping the obverse rim of the pan, we overlay a copy of that rim. This goes over the blood overlay, so we then have to re-add the blood overlay, only over the new front rim. However there are a few issue with this. One is that items that are big enough to appear pixel-south of the pan lid appear under it. I want to use ICON_ADD to mask this, which would also obviate the need for redrawing the front rim and second blood overlay, however, I'm just not quite there in terms of understanding how to do this, between the concepts of icons, images, and mutable appearances. Below the current code is my attempted refactor. It "almost" works except the scaled icon is in the bottom right corner, and Shift() doesn't seem to work. Do I need to re-Blend() the new 16x16 icon onto a blank 32x32 (world.icon_size) icon again and then Shift()? Also I don't know if it's efficient to create new temporary icons every time (are they stored on disk or something?), and feel like the mutable appearance thing might be better.. but I don't know how to mask those.

Also, ideally I would like to take a snapshot of each ingredient that includes any overlays it has on it, if such a thing is feasible. For example if there was a blood-stained knife in the pan I'd want it to appear bloody in the pan as well.

Current situation: https://github.com/vgstation-coders/vgstation13/blob/81690891b56df80bd11d3b3384a7ca298a2e0c08/code/game/objects/items/weapons/pan.dm#L68

/obj/item/weapon/reagent_containers/pan/update_icon()

    overlays.len = 0

    if(blood_overlay)
        overlays += blood_overlay

    //ingredients:
    if(contents.len)
        var/matrix/M = matrix()
        M.Scale(0.5, 0.5)
        for(var/atom/content in contents)
            var/mutable_appearance/mini_ingredient = image("icon"=content)
            mini_ingredient.transform = M
            mini_ingredient.pixel_x = 0
            mini_ingredient.pixel_y = 0
            mini_ingredient.layer = FLOAT_LAYER
            mini_ingredient.plane = FLOAT_PLANE
            overlays += mini_ingredient

        //put a front over the ingredients where they're occluded from view by the side of the pan
        var/image/pan_front = image('icons/obj/pan.dmi', src, "pan_front")
        overlays += pan_front
        //put blood back onto the pan front
        if(blood_overlay)

            var/icon/I = new /icon('icons/obj/pan.dmi', "pan_front")
            I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent)
            I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant

            var/image/frontblood = image(I)
            frontblood.color = blood_color

            overlays += frontblood

Attempted refactor:

/obj/item/weapon/reagent_containers/pan/update_icon()

    overlays.Cut()

    if(blood_overlay)
        overlays += blood_overlay

    //non-reagent ingredients:
    if(contents.len)
        //start with blank icon
        var/icon/pan_contents = new /icon('icons/obj/pan.dmi', "pan_blank")
        for(var/atom/content in contents)
            //overlay each ingredient
            var/icon/thisingredient = new /icon(content.icon, content.icon_state)
            pan_contents.Blend(thisingredient, ICON_OVERLAY)
        message_admins(world.icon_size)
        //half-size
        var/sizeval = world.icon_size / 2
        pan_contents.Scale(sizeval, sizeval)
        pan_contents.Shift(NORTHEAST, sizeval)
        //mask it with pan_mask
        pan_contents.Blend(new /icon('icons/obj/pan.dmi', "pan_mask"), ICON_ADD)
        overlays += pan_contents

[help]

Contributor guide