Layered Images and Atribute_Function

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Message
Author
User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Layered Images and Atribute_Function

#1 Post by trooper6 » Wed Jun 20, 2018 12:30 am

Greetings All.

I'm back from being away and trying to get Layered Images to work for me. PyTom recommended I use attribute_function to solve my conundrum...but I don't seem to be able to get it to work. Perhaps some of you all can figure out how I need to write this code?

Problem: Given separate eyes, brows, and mouth images. Supplying the happy attribute, would return happy eyes, happy brows, and happy mouth. But what to do if you want a different combination of eyes, brows, and mouth images.

So given these images:

rex_base
rex_pants_long
rex_pants_short
rex_shirt
rex_eyebrow_neutral
rex_eyebrow_angry
rex_eyebrow_happy
rex_eyebrow_sad
rex_eye_neutral
rex_eye_angry
rex_eye_happy
rex_eye_sad
rex_mouth_neutral
rex_mouth_angry
rex_mouth_happy
rex_mouth_sad

Say you want the following emotions:
happy: eyebrow_happy, eye_happy, mouth_happy
angry: eyebrow_angry, eye_angry, mouth_angry
sad: eyebrow_sad, eye_sad, mouth_sad
manic: eyebrow_angry, eye_angry, mouth_happy
wistful: eyebrow_sad, eye_sad, mouth_happy

Okay...so how to do this with the attribute_function?
Looking at the random picker from the Patreon tutorial, I've tried this:

Code: Select all

define r = Character("Rex", image="rex")

init python:
    class Picker(object):
        def __init__(self, options):
            self.options =  [ i.split() for i in options ]

        def __call__(self, attributes):
            rv = set(attributes)

            choices = [ ]

            for i in self.options:
                if i[0] in attributes:
                    rv.add(i[1:])

            return rv

layeredimage rex:

    attribute_function Picker([
        "manicE eyebrow_angry eye_angry mouth_happy",
        "wistfulE eyebrow_sad eye_sad mouth_happy"
    ])

    always "rex_base"
    group pants auto:
        attribute long default
    always "rex_shirt"
    group eyebrow auto:
        attribute neutral default
    group eye auto:
        attribute neutral default
    group mouth auto:
        attribute neutral default
    group hand auto:
        attribute neutral default

label start:
    scene black
    show rex
    r "This is Rex."
    r sad "This sad works."
    r happy "This happy works."
    r angry "This angry works."
    r manicE "This manic doesn't work."
So I've been playing around with this for a bit...but I just can't figure out how to use attribute_function to give complex emotions.

Any help would be appreciated! If we can figure this out, I think this would be useful to everyone who is using separate eyes, brows, and mouth images.

Note: I get an error Unhashable type: list--perhaps that will help with the troubleshooting!
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

kivik
Miko-Class Veteran
Posts: 784
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Layered Images and Atribute_Function

#2 Post by kivik » Wed Jun 20, 2018 5:09 am

This is very interesting, although I'm wondering if you should ask PyTom directly and remove this post - if the tutorial is meant for patrons only? But without seeing what the tutorial was I can't tell if you're exposing too much of the tutorial out either!

My suspicion is that the problem lies with this line:

Code: Select all

rv.add(i[1:])
I'm not familiar enough with python to know how it plays when you add lists to sets set and lists, so maybe you just need to convert to a set first?

Code: Select all

rv.add(set(i[1:]))
Again, I'm not at all familiar enough with python to know for sure, but I suspect that's the problem given where the error occurs implying that it's consistent with that line being executed.

Also I noticed you've got a list of choices but it's unused?

kivik
Miko-Class Veteran
Posts: 784
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Layered Images and Atribute_Function

#3 Post by kivik » Wed Jun 20, 2018 5:17 am

I just had a google on adding lists to sets and came across this, maybe it can offer more insight:

https://stackoverflow.com/questions/130 ... ist-to-set

At least now I think I understand the difference between lists and sets a bit more.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#4 Post by trooper6 » Wed Jun 20, 2018 8:31 am

kivik thank you for that stack overflow link. It was very informative! This has helped me make a bit of a breakthrough I think!
I still have to do some more experiments to see how this works...but I'm getting somewhere now!
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Arowana
Miko-Class Veteran
Posts: 527
Joined: Thu May 31, 2012 11:17 pm
Completed: a2 ~a due~
Projects: AXIOM.01, The Pirate Mermaid
Organization: Variable X, Navigame
Tumblr: navigame-media
itch: navigame
Contact:

Re: Layered Images and Atribute_Function

#5 Post by Arowana » Sun Jul 08, 2018 1:07 am

Did anyone ever figure out a good solution for this? I'm using a very similar sprite system (using combos of eyes, mouths, brows, etc. to create new expressions), and would love to figure out how to write the attribute_function to make this work with LayeredImage.

I'm using LayeredImage code similar to the first post (modified slightly to add the prefixes used in the Picker function). I'm also using the Picker function in the first post (just changed rv.add to rv.update, as per a suggestion on Stack Overflow). Not much luck so far though - just lots of "unknown attributes" or "image X not found" errors. :(

I looked at the Patreon post, but couldn't figure out how to adapt it for this case. Any help would be much appreciated!
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#6 Post by trooper6 » Sun Jul 08, 2018 1:16 am

I got it working. Though only in my test game, not in my actual game (which I think I need to rebuild since I started it back in Renpy 6 and something in Layered Images isn't backwards compatible with pre-gui.rpy games). I'll say that "unknown attributes" and "image X not found" is not about the picker, that is about how you are defining your Layered image and how your images themselves are named.

I went through a very methodical bit by bit process to figure out what I was doing wrong. After the rv.update thing, mostly everything was defining things poorly. Someone put a tutorial in the Cookbook...does that cover this?

I will tell you...watching out for trying to nest attributes...or thinking that a group is an attribute...because a group isn't an attribute. If you try to call a group as an attribute, you willet some unknown attributes errors.

For me working through some of those structure/definition issues, see this thread: viewtopic.php?f=8&t=50663
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Arowana
Miko-Class Veteran
Posts: 527
Joined: Thu May 31, 2012 11:17 pm
Completed: a2 ~a due~
Projects: AXIOM.01, The Pirate Mermaid
Organization: Variable X, Navigame
Tumblr: navigame-media
itch: navigame
Contact:

Re: Layered Images and Atribute_Function

#7 Post by Arowana » Sun Jul 08, 2018 2:04 am

trooper6 wrote:
Sun Jul 08, 2018 1:16 am
I got it working. Though only in my test game, not in my actual game (which I think I need to rebuild since I started it back in Renpy 6 and something in Layered Images isn't backwards compatible with pre-gui.rpy games). I'll say that "unknown attributes" and "image X not found" is not about the picker, that is about how you are defining your Layered image and how your images themselves are named.

I went through a very methodical bit by bit process to figure out what I was doing wrong. After the rv.update thing, mostly everything was defining things poorly. Someone put a tutorial in the Cookbook...does that cover this?

I will tell you...watching out for trying to nest attributes...or thinking that a group is an attribute...because a group isn't an attribute. If you try to call a group as an attribute, you willet some unknown attributes errors.

For me working through some of those structure/definition issues, see this thread: viewtopic.php?f=8&t=50663
Hi trooper6, thanks for the quick reply! I actually looked over your other thread and the Cookbook tutorial earlier, but I'm afraid I'm still stuck. :oops:

In my case, I think the "unknown attributes" and "image X not found" errors are actually related to my Picker function, because the attributes that are not being found are the attributes used only in the Picker function. I suspect I need to set up the Picker function differently, but let me know if you think the problem is something else!

I've put together a basic test script to demonstrate the issues I'm running into. Here are the Picker function and some simplified LayeredImage definitions:

Code: Select all

init python:
    class Picker(object):
        def __init__(self, options):
            self.options =  [ i.split() for i in options ]

        def __call__(self, attributes):
            rv = set(attributes)

            for i in self.options:
                if i[0] in attributes:
                    rv.update(i[1:])

            return rv 

layeredimage palette:
    attribute_function Picker([
    "pastel blue_sky red_rose", ### Note that 'pastel' and 'neon' only appear in the Picker function, not as attributes under any groups
    "neon blue_cyan red_magenta"
    ])

    align (0.5, 0.5)

    group blue prefix "blue":
        pos (0, 0)
        attribute sky default:
            Solid("#BFEFFF", xysize=(100,100))
        attribute cyan:
            Solid("#00ffff", xysize=(100,100))

    group red prefix "red":
        pos (100, 0)
        attribute magenta default:
            Solid("#FF00FF", xysize=(100,100))
        attribute rose:
            Solid("#ffe4e1", xysize=(100,100))

layeredimage palette2 tall: ### pretty much the same as above, just using this to demonstrate another error later
    attribute_function Picker([
    "pastel blue_sky red_rose",
    "neon blue_cyan red_magenta"
    ])

    align (0.5, 0.5)

    group blue prefix "blue":
        pos (0, 0)
        attribute sky default:
            Solid("#BFEFFF", xysize=(100,100))
        attribute cyan:
            Solid("#00ffff", xysize=(100,100))

    group red prefix "red":
        pos (0, 100)
        attribute magenta default:
            Solid("#FF00FF", xysize=(100,100))
        attribute rose:
            Solid("#ffe4e1", xysize=(100,100))
And here is a short test script:

Code: Select all

label start:
    show palette
    "Here's our default image, named 'palette'."
    show palette red_rose
    "Here we change an attribute that is defined in the 'red' group. This works as expected."
    show palette neon
    "Here, we try to use a new combination from the Picker function. Although the image shows up, it also displays an 'unknown attribute' error."
    show palette pastel
    "Same error with another combination from the Picker function."
    hide palette
    show palette2 tall
    "Here's another image called 'palette2 tall'. Note this image has a space in its name, similar to what you might see for a sprite with multiple poses."
    show palette2 red_rose
    "Again, changing an attribute that is defined in one of the image's groups works fine."
    show palette2 neon
    "But if we try to use a combination from the Picker function, the image isn't found at all!"
As shown, the attributes appear as "unknown" if they are not explicitly defined within a group in the LayeredImage. In this case, "pastel" and "neon" are combinations that appear in the Picker Function only (I would liken this to how you used "manic" and "wistful" in your original example). I would like to be able to use these attributes as shown above, without the error messages.

If the image name contains a space (i.e., has additional attributes), as in the "palette2 tall" example, and I also try to use a combination from the Picker Function, then that's when I run into the "image not found" issues.

I hope that makes my issues clearer! Let me know if you were able to solve similar problems in your project.
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#8 Post by trooper6 » Sun Jul 08, 2018 4:15 am

I will look at this when I wake up. But could you post a list of your image file names? It would be important to see how your your images are actually named to help figure out problems. Capital letters? Spaces instead of underlines? etc.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Arowana
Miko-Class Veteran
Posts: 527
Joined: Thu May 31, 2012 11:17 pm
Completed: a2 ~a due~
Projects: AXIOM.01, The Pirate Mermaid
Organization: Variable X, Navigame
Tumblr: navigame-media
itch: navigame
Contact:

Re: Layered Images and Atribute_Function

#9 Post by Arowana » Sun Jul 08, 2018 4:23 am

trooper6 wrote:
Sun Jul 08, 2018 4:15 am
I will look at this when I wake up. But could you post a list of your image file names? It would be important to see how your your images are actually named to help figure out problems. Capital letters? Spaces instead of underlines? etc.
Thanks for offering to take a look! The test code I posted doesn't require any additional image files (all the sample images are generated using Solid, which is a built-in Ren'Py function). So you should be able to copy it directly into a new game and run it.

I will note one partial solution I've since come up with, though it's really hacky and I'm sure there must be something better. It requires adding a "fake" group to the LayeredImage with all the combos that will be used in the Picker function. For example:

Code: Select all

layeredimage palette:
    attribute_function Picker([
    "pastel blue_sky red_rose",
    "neon blue_cyan red_magenta"
    ])

    align (0.5, 0.5)

    group combos: ### <---- FAKE GROUP FOR PICKER FUNCTION
        attribute pastel null
        attribute neon null

    group blue prefix "blue":
        pos (0, 0)
        attribute sky default:
            Solid("#BFEFFF", xysize=(100,100))
        attribute cyan:
            Solid("#00ffff", xysize=(100,100))

    group red prefix "red":
        pos (100, 0)
        attribute magenta default:
            Solid("#FF00FF", xysize=(100,100))
        attribute rose:
            Solid("#ffe4e1", xysize=(100,100))
This helps Ren'Py recognize the combinations used in the Picker function, so that we can avoid the "unknown attributes" error. If you have a large number of combinations, however, it's a pain to list them all out like that. I feel like there must be a more efficient solution.

There's also some interaction between the "combo attributes" (neon, pastel) and "normally defined attributes" (red_rose, red_magenta, etc.) that I don't fully understand. :| This sequence, for example, doesn't work at end:

Code: Select all

label start:
   show palette
   "Default."
   show palette red_rose
   "Default with rose."
   show palette neon
   "Neon should have changed the rose into magenta, but it didn't work..."
Whereas this sequence works fine...

Code: Select all

label start:
   show palette
   "Default."
   show palette neon
   "Neon."
   show palette red_rose
   "Magenta changes correctly into rose..."
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#10 Post by trooper6 » Sun Jul 08, 2018 4:25 pm

Okay. I got my everything working after a bunch of trial and error.

Here's the thing. You do need the combo group.
Why?
Because according to the documentation:
"attribute_function: If not None, a function that's called with a set of attributes supplied to the image, and returns the set of attributes used to select layers. This is called when determining the layers to display, after the attribute themselves have been chosen. It can be used to express complex dependencies between attributes or select attributes at random."
So neon and pastel have to be attributes...and without the combo group, you haven't registered those the names as attributes.

The big thing I learned in that other thread is that people keep thinking of groups as attributes...and they aren't. So they have to be registered as attributes before it'll work.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#11 Post by trooper6 » Sun Jul 08, 2018 5:06 pm

Okay...new thing I've noticed...

There seems to be no way to have a default expression if the expressions are compiled using an attribute picker. Now...this isn't a problem at the moment because attribute negation still isn't working properly with layered images...but when it gets fixed...that will be a problem...
More...drawing board...
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Arowana
Miko-Class Veteran
Posts: 527
Joined: Thu May 31, 2012 11:17 pm
Completed: a2 ~a due~
Projects: AXIOM.01, The Pirate Mermaid
Organization: Variable X, Navigame
Tumblr: navigame-media
itch: navigame
Contact:

Re: Layered Images and Atribute_Function

#12 Post by Arowana » Sun Jul 08, 2018 7:02 pm

trooper6 wrote:
Sun Jul 08, 2018 4:25 pm
Okay. I got my everything working after a bunch of trial and error.

Here's the thing. You do need the combo group.
Why?
Because according to the documentation:
"attribute_function: If not None, a function that's called with a set of attributes supplied to the image, and returns the set of attributes used to select layers. This is called when determining the layers to display, after the attribute themselves have been chosen. It can be used to express complex dependencies between attributes or select attributes at random."
So neon and pastel have to be attributes...and without the combo group, you haven't registered those the names as attributes.
Is this similar to what you did in your project then? That is, you have "maniac" and "wistful" from your original post explicitly defined as attributes somewhere in your LayeredImage, as well as in your attribute_function?

I was hoping there might be a more efficient approach that avoids listing the same expressions twice (both in the LayeredImage and attribute_function). But this is at least better than nothing. :)
trooper6 wrote:
Sun Jul 08, 2018 5:06 pm
Okay...new thing I've noticed...

There seems to be no way to have a default expression if the expressions are compiled using an attribute picker. Now...this isn't a problem at the moment because attribute negation still isn't working properly with layered images...but when it gets fixed...that will be a problem...
More...drawing board...
I'm using the latest nightly, which already has the negation bug fixed. It looks like I can set a default combo by doing something like this:

Code: Select all

    group combos:
        attribute pastel default null #<--- default combo
        attribute neon null
If I don't set a default for the "combo" group, then it just shows the defaults for my other groups ("red", "blue"). Either way seems fine for setting a default expression.

I think now my primary concern is the second issue I mentioned in my last post here. Namely, the "combo attributes" (neon, pastel) don't play nice with the "normal attributes" (red_rose, red_magenta, blue_sky, blue_cyan). After some more poking around, I think it's because the Picker function is storing information about both the combo and normal attributes in its set, which leads to confusion about which attributes should actually be shown. Ideally, I'd like to clear out the older attributes and replace them with the newer ones. I haven't found a good way to filter out the older attributes yet though. :(
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#13 Post by trooper6 » Mon Jul 09, 2018 5:26 am

Arowana wrote:
Sun Jul 08, 2018 7:02 pm
Is this similar to what you did in your project then? That is, you have "maniac" and "wistful" from your original post explicitly defined as attributes somewhere in your LayeredImage, as well as in your attribute_function?

I was hoping there might be a more efficient approach that avoids listing the same expressions twice (both in the LayeredImage and attribute_function). But this is at least better than nothing. :)
This is what my current layered image code looks like:

Code: Select all

layeredimage barber:
    group expressions:
        attribute neutral default null
        attribute friendly null

    attribute_function Picker([
        "neutral brow_normal eyes_normal mouth_normal",
        "friendly brow_raised eyes_narrow mouth_grin",
    ])

    always "barber_base"
    group backhand auto prefix "backhand":
        attribute straight default
    always "barber_jacket"

    group brow auto prefix "brow"
    group mouth auto prefix "mouth"
    group eyes auto prefix "eyes"
        
    group hand auto prefix "hand":
        attribute neutral default
This is currently working perfectly. Thanks for the adding the default to the emotions group, by the way! Well I haven't beeb able to test out attribute negation with the nightly, because when I updated to the pre-release it caused my Ren'Py to crash and I had to reinstall 7.0.0...so I'll just have to wait until this actually get officially released.
Arowana wrote:
Sun Jul 08, 2018 7:02 pm
If I don't set a default for the "combo" group, then it just shows the defaults for my other groups ("red", "blue"). Either way seems fine for setting a default expression.
I need to give you a big warning here based on something I learned while testing!
This was my original code:

Code: Select all

layeredimage barber:
    group expressions:
        attribute neutral null
        attribute friendly null

    attribute_function Picker([
        "neutral brow_normal eyes_normal mouth_normal",
        "friendly brow_raised eyes_narrow mouth_grin",
    ])

    always "barber_base"
    group backhand auto prefix "backhand":
        attribute straight default
    always "barber_jacket"

    group brow auto prefix "brow":
        attribute normal default
    group mouth auto prefix "mouth":
        attribute normal default
    group eyes auto prefix "eyes":
        attribute normal default
        
    group hand auto prefix "hand":
        attribute neutral default
I doesn't actually matter if I put

Code: Select all

attribute neutral null
or

Code: Select all

attribute neutral default null
in the expression group, you get the same problematic behavior...which is?

when you put defaults under the brow, mouth, eyes groups as well as having an attribute picker what happens is that you get two emotion layers on top of each other. So that means that if your default under brow, mouth, eyes group is "normal" and then you choose "friendly" through the attribute picker, then you will see both the normal expression and the friendly expression at the same time. That is clearly not optimal. So you have to use code like my first version, not the second version.

This then actually explains your second problem...
Arowana wrote:
Sun Jul 08, 2018 7:02 pm
I think now my primary concern is the second issue I mentioned in my last post here. Namely, the "combo attributes" (neon, pastel) don't play nice with the "normal attributes" (red_rose, red_magenta, blue_sky, blue_cyan). After some more poking around, I think it's because the Picker function is storing information about both the combo and normal attributes in its set, which leads to confusion about which attributes should actually be shown. Ideally, I'd like to clear out the older attributes and replace them with the newer ones. I haven't found a good way to filter out the older attributes yet though. :(
So what is happening is that both of those images are being shown and since the normal attribute layer is on top of the combo attribute you don't see the combo attribute layer if you call it before the normal attribute.

The code I used works with actual image files in the folder section...I can't figure out how to modify your code which uses Solids instead of actual files. But I'd recommend trying out my code with some of your actual image files.

By the way, it is lovely working through these layer image issues with you.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Arowana
Miko-Class Veteran
Posts: 527
Joined: Thu May 31, 2012 11:17 pm
Completed: a2 ~a due~
Projects: AXIOM.01, The Pirate Mermaid
Organization: Variable X, Navigame
Tumblr: navigame-media
itch: navigame
Contact:

Re: Layered Images and Atribute_Function

#14 Post by Arowana » Mon Jul 09, 2018 5:15 pm

trooper6 wrote:
Mon Jul 09, 2018 5:26 am
when you put defaults under the brow, mouth, eyes groups as well as having an attribute picker what happens is that you get two emotion layers on top of each other. So that means that if your default under brow, mouth, eyes group is "normal" and then you choose "friendly" through the attribute picker, then you will see both the normal expression and the friendly expression at the same time. That is clearly not optimal. So you have to use code like my first version, not the second version.

...

So what is happening is that both of those images are being shown and since the normal attribute layer is on top of the combo attribute you don't see the combo attribute layer if you call it before the normal attribute.
Great insight here! You are totally right - both layers (the one from the normal attribute and the one from the combo attribute) are being shown at the same time. Removing the "defaults" from all the groups except for the "combo" one is definitely a good call.

However, even after removing these defaults, I'm still getting issues where both layers get displayed at the same time. It basically happens whenever I use both normal and combo attributes together. For example, do you also get overlap when doing something like this?

Code: Select all

label start:
    show barber
    "Default image."
    show barber mouth_grin
    "Normal attribute."
    show barber neutral
    "Combo attribute."
In a case like this, I'm getting the "mouth_grin" shown everywhere, overlapping with the other "mouth" layers. The only way to remove it is to use negation (e.g., "show barber neutral -mouth_grin").

Of course, I only want one "mouth" layer to be shown at a time. For example, I'd want "neutral" to overwrite "mouth_grin" with "mouth_normal" automatically, without me having to explicitly specify the negation. I'm not sure whether this is possible or not. I've tried filtering the set of attributes from the Picker function to remove extra "mouth" layers. However, I haven't been able to figure out a good way to identify the most recent "mouth" layer (i.e., the one I actually want to keep). :?

I will note this is not a problem if you only use "combo" attributes, e.g., just stick to "neutral" and "friendly" without ever trying to change individual eyes, mouths, etc. This doesn't work well for me, unfortunately - I need the flexibility to be able to tweak individual components without defining every possible combo. So if there's a way to make "normal" and "combo" attributes work together harmoniously, that's definitely what I'd prefer!
trooper6 wrote:
Mon Jul 09, 2018 5:26 am
By the way, it is lovely working through these layer image issues with you.
Likewise! It's been very helpful to be able to discuss this together. :D
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3442
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Layered Images and Atribute_Function

#15 Post by trooper6 » Mon Jul 09, 2018 11:06 pm

Arowana wrote:
Mon Jul 09, 2018 5:15 pm
Great insight here! You are totally right - both layers (the one from the normal attribute and the one from the combo attribute) are being shown at the same time. Removing the "defaults" from all the groups except for the "combo" one is definitely a good call.

However, even after removing these defaults, I'm still getting issues where both layers get displayed at the same time. It basically happens whenever I use both normal and combo attributes together. For example, do you also get overlap when doing something like this?

Code: Select all

label start:
    show barber
    "Default image."
    show barber mouth_grin
    "Normal attribute."
    show barber neutral
    "Combo attribute."
In a case like this, I'm getting the "mouth_grin" shown everywhere, overlapping with the other "mouth" layers. The only way to remove it is to use negation (e.g., "show barber neutral -mouth_grin").
That is indeed what happens.
Arowana wrote:
Mon Jul 09, 2018 5:15 pm
Of course, I only want one "mouth" layer to be shown at a time. For example, I'd want "neutral" to overwrite "mouth_grin" with "mouth_normal" automatically, without me having to explicitly specify the negation. I'm not sure whether this is possible or not. I've tried filtering the set of attributes from the Picker function to remove extra "mouth" layers. However, I haven't been able to figure out a good way to identify the most recent "mouth" layer (i.e., the one I actually want to keep). :?

I will note this is not a problem if you only use "combo" attributes, e.g., just stick to "neutral" and "friendly" without ever trying to change individual eyes, mouths, etc. This doesn't work well for me, unfortunately - I need the flexibility to be able to tweak individual components without defining every possible combo. So if there's a way to make "normal" and "combo" attributes work together harmoniously, that's definitely what I'd prefer!
The problem is that the combo attributes are in a different group than the mouth group...so they don't replace each other. In order for the layers to replace each other they have to be in the same group. My workaround is that you could put every single attribute also in the same group as the combo group. That does "work"...but not in an acceptable way for expressions. What I mean is, if you have neutral, friendly, and mouth_grin in the same group, if you show mouth_grin it will replace neutral and friendly so you won't have both mouths showing...however, the eyes and the brows will also go missing.
This could be useful for some situations, but I don't think for expressions.

Since you want to individually control each brow, eye, mouth separately and don't want to put each combo in the picker, I'd say that the picker is probably not the solution for you. I'd say you'd probably want to do all pieces individually as you'd do in a LiveComposite.

I'm going to put all the expression combos I need into the picker, because I think that will ultimately be easier.
Arowana wrote:
Mon Jul 09, 2018 5:15 pm
trooper6 wrote:
Mon Jul 09, 2018 5:26 am
By the way, it is lovely working through these layer image issues with you.
Likewise! It's been very helpful to be able to discuss this together. :D
I finished my Customer LayeredImage, which is more complicated because it has a lot of condition switches. I got it working including some strange quasi-nested groups. What I need to work on now is the most complicated sprite. It is one sprite of both the barber and the customer together...that is going to be complicated. At the moment I'm trying to figure out the proper naming conventions I'm going to need for the image files so that they will actually work.
I put a comment at the top of my renpy file: image_group_variation_attribute.
Must always remember that.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Post Reply

Who is online

Users browsing this forum: Google [Bot]