How/When/Where to add ConditionSwitches to LayeredImages? [Solved?]

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.
Post Reply
Message
Author
User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

How/When/Where to add ConditionSwitches to LayeredImages? [Solved?]

#1 Post by HEXdidnt »

I've been looking into a few different options for customising sprites - BáiYù's LayeredImage Tutorial, Moonpearl's Dynamic Paper Dolls, and Pippin123's Dynamic Dress Up Framework - but am having trouble figuring out the best method for what I want to achieve...

I have a generally hard time with programming, and my brain has just been seizing up while trying to figure out what's happening and how it's happening in each of these, but Dynamic Paper Dolls so far seems most intuitive to me purely in terms of adjusting the character's expression on the fly. That said, I get the impression that LayeredImage effectively supercedes it (Dynamic Paper Dolls having been posted back in 2017!), and would likely be the preferable option going forward.

So, let's say there's a character who, during the course of the story, would need to change clothes, hairstyle, makeup, etc. I think the clothes and hair are simple enough as they remain static once applied... But say this character has x eye expressions and y mouth expressions which are duplicated for each variation in her makeup, z (say 2, maybe 3 options)

Do I just need to add a ConditionSwitch somewhere in a LayeredImage that determines which set of eyes and which set of mouths gets used according to the value of z, which would be changed at certain points during the story?

And then have the images broken up into subdirectories something like:

Code: Select all

Character/base.png
	 /clothing/
	 /hair/
	 /eyes_set1/
	 /eyes_set2/
	 /eyes_set3/
	 /mouth_set1/
	 /mouth_set2/
	 /mouth_set3/
Any advice gratefully received.
Last edited by HEXdidnt on Wed Jun 02, 2021 5:39 pm, edited 1 time in total.
As ever, dropping litter in the zen garden of your mind...

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#2 Post by HEXdidnt »

OK... having Googled up some additional information on ConditionSwitching, I've come up with a solution:

Before starting the LayeredImage, I've set up a bunch of image ConditionSwitches for each expression, thus:

Code: Select all

image mouth_normal = ConditionSwitch( 
    "lipstick == 'Red'", "images/test/mouth_ntrl_red.png",
    "lipstick == 'Nude'", "images/test/mouth_ntrl_nd.png",
    "True", "images/test/mouth_ntrl.png",
    )
etc. for each mouth expression, plus

Code: Select all

image eyes_normal = ConditionSwitch( 
    "eyeshadow == 'Blue'", "images/test/eyes_ntrl_blu.png",
    "eyeshadow == 'Green'", "images/test/eyes_ntrl_grn.png",
    "True", "images/test/eyes_ntrl.png",
    )
etc. for each eye expression.

Then, the LayeredImage features:

Code: Select all

layeredimage testcharacter:
    always:
        "images/test/base.png"
    
    group test_eyes:
        attribute eyesnormal default:
            "eyes_normal"
        attribute eyesfrown1:
            "eyes_frown1"
        attribute eyesfrown2:
            "eyes_frown2"
        attribute eyessmirk:
            "eyes_smirk"
            
    group test_mouth:
        attribute mouthnormal default:
            "mouth_normal"
        attribute mouthnarrow1:
            "mouth_narrow1"
        attribute mouthnarrow2:
            "mouth_narrow2"
        attribute mouthsmirk:
            "mouth_smirk"
The downside to this is that I appear to have to use an additional show statements for each part of an expression that changes as I mix and match eye and mouth shapes, and I'm sure there must be a more elegant way of doing it on the fly - as in, a means of changing both items in one show statement?

If it can't be done on the fly, I guess I'll just have to put in a load more image statements to predefine all the combinations of expressions?
As ever, dropping litter in the zen garden of your mind...

User avatar
Sunlit-Dreamer
Veteran
Posts: 400
Joined: Thu Sep 22, 2011 12:41 am
Completed: NaNo2015 Bedtime, NaNo2016 The Doll and the Spider, NaNo2017 What's Your Name?, NaNo2018 Painting Your Skin, NaNo2019 Home's Embrace, NaNo2020 Molly
Projects: NaNo2021 Cracked Moonstone
Deviantart: Sunlit-Dreamer
itch: Sunlit-Dreamer
Location: Lala land~
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#3 Post by Sunlit-Dreamer »

Hmm, seeing as no one has replied yet I'll do my best.

Regarding conditions, there actually was an example within the tutorial. I'm going to copy/pasta straight from the tutorial's code. You can see here that the "condition switches" are created where you keep your sprite code.

Code: Select all

init -1:

    $ evil = False            

layeredimage augustina:

    always:
        "augustina_base"

    group outfit:

        attribute dress:
            "augustina_outfit_dress"

        attribute jeans:
            "augustina_outfit_jeans"

    group eyes:

        attribute open default:
            "augustina_eyes_open"
            #default True

        attribute wink:
            "augustina_eyes_wink"

    group eyebrows:

        attribute normal default:
            "augustina_eyebrows_normal"

        attribute oneup:
            "augustina_eyebrows_oneup"

    group mouth:

        #pos (100, 100)

        attribute smile default:
            "augustina_mouth_smile"

        attribute happy:
            "augustina_mouth_happy"

    if evil:
        "augustina_glasses_evil"

    else:
        "augustina_glasses"
And shown in action below within the script itself.

Code: Select all

    $ evil = True 

    a "Maybe I'm angry at you, or being sneaky. At some point in the game, the {i}evil{/i} variable was set to {i}True{/i}."

    show august normal smile regular with dissolve

    $ evil = False

    a "When the {i}evil{/i} variable is set to {i}False{/i}, my glasses will look normal."
With that as a base, I'll whip up the below as examples.

Code: Select all

    "Hmm, what should I go with today?
    
    menu:
	“Let's use blue.”
		$ blue = True
		jump blah
	“Feeling green today.”
		$ green = True
		jump blah
    	"Not feeling anything"
    		jump blah
   
label blah:
    		
    "..."
    
    "All right the day's over, let's clean up."
    
    $ blue = False
    $ green = False
Of course, you don't only have to use them in a menu. Let's say the character bumped into someone, and spilled coffee on their shirt. You'd then made the stain attribute true. From then on, even in a new scene, the character will have a coffee stain on their shirt. Not until you have them go home and change clothes.

Code: Select all

layeredimage testcharacter:
    always:
        "images/test/base.png"
    
    group test_eyes auto:
        attribute eyesnormal default:
            "testcharacter_eyes_normal"
            
    group test_mouth auto:
        attribute mouthneutral default:
            "testcharacter_mouth_neutral"
            
    if blue:
    	"eyes_ntrl_blu"
    elif green:
    	"eyes_ntrl_grn"
    else:
    	"eyes_ntrl"
    	
    if stain:
    	"clothes_shirtwhite_coffee"
    else:
    	"clothes_shirtwhite"
I cleaned it up a bit, auto makes things much easier.
To make the auto work, you have to name the image files exactly.

"charactername_body/clothingpart_nameyouwillusetochangeit"

Such as

"testcharacter_mouth_shysmile".

It's not shown in the code, but it's how it's named in the files.

Regarding being able to change more than one attribute, yup! It is possible! The key though is to give everything its own name. You can't name several neutral things normal for example, which is why I changed the mouth to neutral. It'll cause errors because it won't know which "normal" image you're trying to pull up. I'll post some of my code below as an example. I'll be adding in ## to describe what's changing.

Code: Select all

    show melanie closed1
    
    #Her eyes are closed now.

    m "Make sure to hold my hand tight so we don't get separated."

    show asher two lup2 rup2 eplain2 normal2 smile2
    
    #He was originally in pose 1. Now he's in pose 2, so I have to update his left arm, right arm, eyes, eyebrows, and mouth.

    a "No one could pull you away from my grasp."

    "Ahh, he always makes me feel safe."
    
    #She has also now changed from pose 1 to pose 2. Cute2 are two arms together so the 2nd arm attribute will remain empty for now.

    show melanie two cute2 happyopen2 normal2 closed2

    m "Could you hold me a while longer? My legs have still not quite recovered from last night."
    
    #His right hand is now on his hip and smiling with his teeth.

    show asher righthip2 smileopen2

    a "If that's what my wife wishes, then it shall be."
As you can see, a single show statement is enough to make all necessary changes.

Hopefully this was able to clear things up.
ImageImageImageImage

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#4 Post by HEXdidnt »

Much appreciated, Sunlit-Dreamer - your examples have clarified much of what I'm trying to accomplish, and I am now able to make static items (like clothing) change on the fly, as well as make expression changes within a single colour variant. There's something I'm still not understanding about the colour changes, though. In your code, you have:

Code: Select all

layeredimage testcharacter:
    always:
        "images/test/base.png"
    
    group test_eyes auto:
        attribute eyesnormal default:
            "testcharacter_eyes_normal"
            
    ...other groups...
            
    if blue:
    	"eyes_ntrl_blu"
    elif green:
    	"eyes_ntrl_grn"
    else:
    	"eyes_ntrl"
and I don't understand how the if / elif / else part relates to group test_eyes auto:

Will I need to if / elif / else every individual expression for its colour, or is the _blu/_grn part of the filename supposed let auto handle the expression's colour setting automatically? Do I need to store the image components in separate folders by expression or by colour? So, for example, do I organise them as "eyes_normal_(colour)", "eyes_surprised_(colour)", "eyes_crying_(colour)" or "eyes_(colour)_normal", "eyes_(colour)_surprised", "eyes_(colour)_crying", all loose in an "eyes" folder or batched into subfolders?

And then, is a new True/False variable required for each colour variant, or is can they all be governed by a single variable, for example:

Code: Select all

if eyeshadow == "blue":
	"eyes_ntrl_blu"
elif eyeshadow == "green":
	"eyes_ntrl_grn"
else:
	"eyes_ntrl"
I thought it'd tried this without success, but it's possible I'd got something wrong in the filenames and/or directory structure...
Last edited by HEXdidnt on Mon Jun 07, 2021 9:34 am, edited 1 time in total.
As ever, dropping litter in the zen garden of your mind...

User avatar
Sunlit-Dreamer
Veteran
Posts: 400
Joined: Thu Sep 22, 2011 12:41 am
Completed: NaNo2015 Bedtime, NaNo2016 The Doll and the Spider, NaNo2017 What's Your Name?, NaNo2018 Painting Your Skin, NaNo2019 Home's Embrace, NaNo2020 Molly
Projects: NaNo2021 Cracked Moonstone
Deviantart: Sunlit-Dreamer
itch: Sunlit-Dreamer
Location: Lala land~
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#5 Post by Sunlit-Dreamer »

Regarding the below.

Code: Select all

if eyeshadow == "blue":
	"eyes_ntrl_blu"
elif eyeshadow == "green":
	"eyes_ntrl_grn"
else:
	"eyes_ntrl"
Ahh, I'll make this more clear. This will not be part of the eyes group at all. It'll be its own eyeshadow group. If anything it should be renamed to:

Code: Select all

if eyeshadow == "blue":
	"eyelids_ntrl_blu"
elif eyeshadow == "green":
	"eyelids_ntrl_grn"
else:
	"eyelids_ntrl"
But yes, the above should work.

I personally haven't used the conditions much yet. But you can think of as another attribute group. The only difference being instead of writing
"show blue", you'd write "$ blue = True". That way each time the scene or pose changes, you don't have to rewrite it. I only used the colors as examples based off what you wrote regarding eyeshadow. If you meant eye color,

As for the files, everything will be in the same folder for a single character, no need for subfolders.

I do believe though this will help you out.

https://jaimescribblesgames.com/2019/02 ... -tutorial/

It's simple, but it shows another way if you're aiming for customizing the main character.

(Note: A detail I forgot to add to the example code in the first post was the init. You will need the init and $ blah = False for the conditions to work.)
ImageImageImageImage

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#6 Post by HEXdidnt »

Thank you again, Sunlit-Dreamer! You've given me a brilliant new angle on one of the issues: I'd been thinking along the lines of having the coloured eyeshadow as part of the range of eye expressions, but of course it makes much more sense to have that as its own separate layer governed by a unique variable. Way less work that way round. (I'd written 'eyeshadow' only because that was the common aspect to all the expressions)

But... Yes, also changing eye colour (across circa 15 expressions), as well as lip colour (circa 20 expressions). I've also potentially made things even more complicated by realising that I can reduce the number of individual eye expressions by separating off the brows (allowing 5 or 6 brow expressions to add nuance to the 15 eye expressions) but, on the upside, they (currently!) don't need to change colour as well!

Where I'm at, my sprite can have tidy or messy hair (via if/else), various colours/styles of clothing (via attribute groups), wearing a jacket or not (if/else) and cycle through a range of brow, eye and mouth expressions (3x attribute groups), and that seems to be working well...

The bit I'm spectacularly failing to grasp is how a given attribute group can also determine which (colour) set of expressions to use in the latter two cases... I can't seem to get my head around which aspect should be considered the priority in the group: is it an if/elif/else colour list per expression, or an attribute group of expressions per colour?

Taking another look at the Dynamic Dress Up Framework, I can see how it sets up the character with:

Code: Select all

class PCstats(renpy.store.object):
        def __init__(self, name):
            self.name=name
            self.haircut="short"
            self.haircolor="white"
            self.skin="pale"
            self.lipstick="nude"
            self.wearing=[]
And then makes changes by predefining complete sprites with DynamicDisplayables which pick up the relevant attributes... But I'm not getting the necessary lightbulb moment, where it all makes sense and I can apply it to what I'm trying to do.

I think I need to sleep on it and give it another look tomorrow morning...
As ever, dropping litter in the zen garden of your mind...

User avatar
Sunlit-Dreamer
Veteran
Posts: 400
Joined: Thu Sep 22, 2011 12:41 am
Completed: NaNo2015 Bedtime, NaNo2016 The Doll and the Spider, NaNo2017 What's Your Name?, NaNo2018 Painting Your Skin, NaNo2019 Home's Embrace, NaNo2020 Molly
Projects: NaNo2021 Cracked Moonstone
Deviantart: Sunlit-Dreamer
itch: Sunlit-Dreamer
Location: Lala land~
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#7 Post by Sunlit-Dreamer »

You're welcome, and I think we're almost there!

I think the key here will be the numbers. Judging from the tutorial with the Delilah sprite, the only differences in the names are the numbers used. So instead of writing down the colors in the name, use numbers. You can always make notes with # in the code as a reminder which number is which color.

If I'm correct, the code will then search for the attribute name you've written along with the number that was chosen.

Let's say the reader chose to give them green eyes. At this point of the story, they just woke up.

Code: Select all

show test closed

t "Yawn, morning already."

show test wink
#Here, the code will be looking for "test_eyes_wink"
#Say there are three options. Brown, blue, and green.
#What'll be shown in the folder will be "test_eyes_wink1", "test_eyes_wink2", and "test_eyes_wink3"
#The reader chose green, so the code will be looking for the number 3.

t "Ugh the sun is bright."
For now, try to rename the eyes and do a test run.
ImageImageImageImage

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#8 Post by HEXdidnt »

A little bit of progress today.

Looking over the Dynamic Dress Up Framework code - which was somehow more baffling to me this morning than it was last night - I noticed that certain elements were called with the aid of a variable's content added to the filename thus:

Code: Select all

        command_line="LiveComposite((344,600),(0,0),"+startpic
        command_line=command_line+",(0,0),\""+art_path+"_eye_pale_"+eyes+".png\""
        command_line=command_line+",(0,0),\""+art_path+"_mouth_"+mouth+"_"+character.lipstick+".png\""
        if blushing<>"":
             command_line=command_line+",(0,0),\""+art_path+"_blushing_"+blushing+".png\""
        command_line=command_line+",(0,0),im.MatrixColor(\""+art_path+"_hair_"+character.haircut+"_brunette.png\",hair_huearray["+str(character.hair_hue)+"])"
        
And, with a flash of "could it really be that simple?", I added the variable covering the colour changes into the attributes' filenames - eyecolour and lipstick - thus:

Code: Select all

    group test_eyes:
        attribute eyesnormal default:
            "eyes_normal_"+eyecolour
        attribute eyesfrown1:
            "eyes_frown1_"+eyecolour
        attribute eyesfrown2:
            "eyes_frown2_"+eyecolour
        attribute eyessmirk:
            "eyes_smirk_"+eyecolour
            
    group test_mouth:
        attribute mouthnormal default:
            "mouth_normal_"+lipstick
        attribute mouthnarrow1:
            "mouth_narrow1_"+lipstick
        attribute mouthnarrow2:
            "mouth_narrow2_"+lipstick
        attribute mouthsmirk:
            "mouth_smirk_"+lipstick
...and it appears to function as intended, except that it retains the originally-set value of either variable. Making a change within the script by adding $ eyecolour = "(new option)" or $ lipstick = "(new option)" has absolutely no effect on which version gets picked up by the attribute group, though I can confirm that the value has changed by adding [eyecolour] or [lipstick] into the dialogue.

Same thing happens if I substitute the word for a number, with the additional wrinkle that if I define the content of the variable as a number, eg. $ eyecolour = 1 or $ lipstick = 3, it throws up an error telling me:

Code: Select all

TypeError: coercing to Unicode: need string or buffer, int found
Which I take to mean it does actually want a text string, not a number (integer), to add to the filename..? (eg. $ eyecolour = "1" or $ lipstick = "3")

Is there a particular way I need to set up/use these variables, or am I barking up the wrong tree with this method?
As ever, dropping litter in the zen garden of your mind...

User avatar
Sunlit-Dreamer
Veteran
Posts: 400
Joined: Thu Sep 22, 2011 12:41 am
Completed: NaNo2015 Bedtime, NaNo2016 The Doll and the Spider, NaNo2017 What's Your Name?, NaNo2018 Painting Your Skin, NaNo2019 Home's Embrace, NaNo2020 Molly
Projects: NaNo2021 Cracked Moonstone
Deviantart: Sunlit-Dreamer
itch: Sunlit-Dreamer
Location: Lala land~
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#9 Post by Sunlit-Dreamer »

Hmm, that is unfortunate. At this point it might be best to ask for help on the Renpy discord. I will need to do some researching and experimenting myself, since this is also my limit of knowledge.

You should be able to find someone there who has more coding experience with the final piece of the puzzle.
ImageImageImageImage

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages?

#10 Post by HEXdidnt »

Much appreciated, Sunlit-Dreamer - you may be right.

Out of curiosity, I tried making a group of ConditionSwitches ahead of the LayeredImage, to create a new image-per-expression using the appropriate colour set. No changes to the final output, regardless of whether I used text or an integer to make the setting, but showing the variables within dialogue shows that they have definitely changed.
As ever, dropping litter in the zen garden of your mind...

User avatar
HEXdidnt
Regular
Posts: 63
Joined: Tue Aug 11, 2020 1:25 pm
Projects: A Night at the Office, Embracing Christmas, The Masquerade Benefit
Deviantart: HEXdidnt
Location: Harrow, London, UK
Contact:

Re: How/When/Where to add ConditionSwitches to LayeredImages? [Solved?]

#11 Post by HEXdidnt »

OK... This is promising... Did a forum search for 'ConditionSwitch' (admittedly, I don't tend to use the search box, since it seems to have had a high chance of returning a blank screen for me, regardless of what I'm trying to search for) and came across this topic, which appears to deal with a far simpler problem...

...And yet, it also appears to have solved mine.

Following the pattern indicated within Remix's post, if I first define my text variables, thus:

Code: Select all

define eyecolour = "blue"
define lipstick = "none"
Then predefine the images covering each expression variant, thus:

Code: Select all

image cseyes_default = "testcharacter_eyes_default_[eyecolour]"
image cseyes_frown = "testcharacter_eyes_frown_[eyecolour]"
image cseyes_wide = "testcharacter_eyes_wide_[eyecolour]"
...
image csmouth_neutral = "testcharacter_mouth_neutral_[lipstick]"
image csmouth_smile = "testcharacter_mouth_smile_[lipstick]"
image csmouth_gasp = "testcharacter_mouth_gasp_[lipstick]"
...
Then set up the groups within the LayeredImage, thus:

Code: Select all

group testcharacter_eyes auto:
	attribute eyesnormal default:
		"cseyes_default"
	attribute eyesfrown:
		"cseyes_frown"
	attribute eyeswide:
		"cseyes_wide"
	...
	
group testcharacter_mouth auto:
	attribute mouthneutral default:
		"csmouth_neutral"
	attribute mouthsmile:
		"csmouth_smile"
	attribute mouthgasp:
		"csmouth_gasp"
	...
Changes to the content of the variable are reflected in the choice of expression, colour and all!

It ain't exactly a ConditionSwitch, but it acts in the same way and reacts consistently to changes made to the variables on the fly, either via a menu option or just from giving the variable another value at random during the flow of dialogue.
As ever, dropping litter in the zen garden of your mind...

Post Reply

Who is online

Users browsing this forum: Bing [Bot]