Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Need Support? Post here! Sticky

A topic by Feniks created Jul 09, 2023 Views: 467 Replies: 13
Viewing posts 1 to 6
Developer

If you're having trouble or run into any bugs with the code, post a comment here! I will try to get back to you within a few days.

Hello, first of all. Thank you for the time and effort you've dedicated to creating renpy tools and guides. Its wonderful. Next, I was trying out the layered image mask code to see what I could do with it, but I kept running into an issue. Anytime I try to use:

LayeredImageMask() 

to define something, I get the following error

AttributeError: 'MultiBox' object has no attribute '_choose_attributes'

would you happen to know why that is?

Developer

Can you show an example of code which is causing this error, and the full error message? What Ren'Py version are you using?

Oh! Apologies for the delayed response. The error appears when I use

show angel cutin

which is defined as shown in the example on the itch page as

image angel cutin = LayeredImageMask("angel", Transform(crop=(230, 0, 564, 953)), mask="gui/mask.png")

The "angel" image is a layered image defined as

image angel = LiveComposite(
     (277, 277),
     (0, 0), "angelbase@3.png",
     (0, 0), "angel normal",
     (0, 0), WhileSpeaking("angel", "angel talk", "angelbasemouthclosed@3.png"),
     )

However, I also get the error message when I attempt this with a basic png. My renpy version is: 8.3.0.24082114

Thanks again for your time.

The full error message is:

I'm sorry, but an uncaught exception occurred.

While running game code:

  File "game/script.rpy", line 680, in script

    show angel cutin

  File "renpy/common/00layeredimage.rpy", line 1195, in _choose_attributes

    return self.filter_attributes(self.image._choose_attributes(tag, attributes, optional))

AttributeError: 'MultiBox' object has no attribute '_choose_attributes'

-- Full Traceback ------------------------------------------------------------

Full traceback:

  File "game/script.rpy", line 680, in script

    show angel cutin

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\ast.py", line 1111, in execute

    show_imspec(self.imspec, atl=getattr(self, "atl", None))

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\ast.py", line 1074, in show_imspec

    renpy.config.show(name,

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\exports\displayexports.py", line 474, in show

    name, what = _find_image(layer, key, name, what)

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\exports\displayexports.py", line 278, in _find_image

    new_image = renpy.game.context().images.apply_attributes(layer, key, name)

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\display\image.py", line 990, in apply_attributes

    return self.choose_image(nametag, required, optional, name)

  File "C:\Users\streg\Documents\Visual Novels\renpy-8.3.0-sdk\renpy\display\image.py", line 1011, in choose_image

    newattrs = ca(tag, ca_required, ca_optional)

  File "renpy/common/00layeredimage.rpy", line 1195, in _choose_attributes

    return self.filter_attributes(self.image._choose_attributes(tag, attributes, optional))

AttributeError: 'MultiBox' object has no attribute '_choose_attributes'

Windows-10-10.0.19044 AMD64

Ren'Py 8.3.0.24082114

HEATWAVE MINIMUM WAGE MAXIMUM DEBT 1.0

Mon Oct  7 10:23:32 2024

Developer

The problem is your angel image is not a layered image - if you don't have a layered image you'd just use regular AlphaMask and not the LayeredImageMask. Layered images are declared like layeredimage angel and have a specific format that Ren'Py expects. I suggest you look into it, as it's the modern and simpler way to put together images with multiple layers. https://www.renpy.org/doc/html/layeredimage.html#LayeredImage

Interesting...Thank you for the reply!

Does this accept defined image displayable? I know making black bars aren't hard in other programs but using a solid feels so simple 

Developer

If your question is whether you can use a defined image displayable instead of a layered image - the answer is no, that's what a regular AlphaMask displayable is for. If your question is if you can use a defined image displayable for the mask image, sure! LayeredImageMask takes any kind of displayable for the mask, just like AlphaMask does.

good to hear

(1 edit)

Heyo Fen! Ley and I discovered that trying to use the baked-in Ren'Py interactive director with a layered image that has a mask causes.

TypeError: can only concatenate list (not "tuple") to list 

Is it possible to move an image within the mask? I’ve set it up, but when I try to move the image the mask moves along with the image.

Developer

Sure! It's a bit of a weird setup, but you can use a regular function as the Transform argument to LayeredImageMask. Here's an example:

image fen_masked = LayeredImageMask("feniks", lambda x : At(x, adjust_crop), mask="mask2", background="bg2")
transform adjust_crop:
    animation
    crop (0, 0, 637, 431)
    linear 2.0 crop (1171-637, 950-431, 637, 431)
    linear 2.0 crop (0, 0, 637, 431)
    repeat
label start:
    "Start"
    show fen_masked at truecenter
    "Tada"
    show fen_masked sparkle animated right2
    "Sparkle"


The important part is the lambda - that's a function. You could also make a regular function that returns At(<img>, <transform>) yourself and set that as the second argument to LayeredImageMask. The `animation` property in the transform is also important so that the transform doesn't reset for every new expression change. Hope that helps!

(1 edit)

SO. first off. please please please do simply disregard me if you don't wanna deal with this, since it concerns someone else's extension/a weird implementation of your thing. 😎✨ i'm still a baby coder so i'm not sure how easy or laborious this may or may not be but it FEELS like im just having a syntax problem. ....potentially with an obvious answer right in my face (that's often the case with me lmfao)

i've been trying to figure out how to use this in conjunction with Auto Highlight by Wattson. For some scenes, I want to mask the layered character sprites onto boxes, like so:

image erikabox = LayeredImageMask("erika",    
    Transform(crop=(120, 170, 500, 500),zoom=0.7),
    mask="masks/blankbox_ghost.png",
    foreground="transparent.png",
    background="masks/blankbox_ghost.png",
)


the boxes look like this ingame. when a character is speaking, their box brightens and zooms in; when another character speaks, it dims and zooms out. it works great on regular masked images. mr. suspicious on the right there is just a placeholder image masked with the torn-paper-looking box, and it works on him. but it's been a conundrum trying to figure out how to get it to work on a masked layered image (ms. ghost on the left)

here's part of the instructions from the auto highlight script:

# - Second, you'll need to apply the sprite_highlight transform to all images you want this
#   applied to. For people using layeredimages, this is very easy. As an example:
# layeredimage eileen:
#     at sprite_highlight('eileen')
#     ...
# - However, if you're using individual sprites, you'll have to be sure this is applied to every one.
# image eileen happy = At('eileen_happy', sprite_highlight('eileen'))
# image eileen sad = At('eileen_sad', sprite_highlight('eileen'))
#   Or, if you'd prefer an ATL example
# image eileen happy:
#     'eileen_happy'
#     function SpriteFocus('eileen')

if i try putting it into the layeredimage, it won't highlight the whole box correctly... but when i try to cram function SpriteFocus('erikabox') anywhere into the LayeredImageMask statement, i get nothing but errors. neither of these work and i don't really know what else to try.

#nope
image erikabox = LayeredImageMask("erika",
    Transform(crop=(120, 170, 500, 500),zoom=0.7),
    mask="masks/blankbox_ghost.png",
    foreground="transparent.png",
    background="masks/blankbox_ghost.png",
    function SpriteFocus('erikabox')
)
# yeah i didn't expect this to work lol
image erikabox = LayeredImageMask("erika",
    Transform(crop=(120, 170, 500, 500),zoom=0.7),
    mask="masks/blankbox_ghost.png",
    foreground="transparent.png",
    background="masks/blankbox_ghost.png"
    
)
    function SpriteFocus('erikabox')

ANYWAY... tl;dr do you think there's any way to sneak that function into the LayeredImageMask??? also regardless of anything THANK YOU for my life, your ren'py extensions and tutorials are THE BEE'S KNEES

Developer

I haven't downloaded that extension to check, but you should be able to make an ATL transform that handles it. For example, the following code will apply the highlighting to the layered image:

transform highlight_mask(child, crop=(0.0, 0.0, 1.0, 1.0), zoom=1.0, who='eileen'):
    crop crop zoom zoom
    function SpriteFocus(who)
image fen mask_highlight = LayeredImageMask("feniks", highlight_mask(crop=(0.2, 0.2, 0.5, 0.5), zoom=0.7, who="fen"), mask=..., foreground=...)

If you want the highlighting to apply to the background/foreground too, then you should be able to use At(), so like, background=At("whatsit.png", highlight_mask(who="fen")) and that in theory should highlight the background too.

Hope that works!