Resetting animations within a live composite

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
Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Resetting animations within a live composite

#1 Post by Onishion » Sat Feb 27, 2016 4:13 am

I have an LC. at various points in it, the options may display a complex image that includes transforms. The problem I'm having is that when I do this, the animation begins when I first change the variable that would first display the relevant image, but then apparently keeps looping in the background forever, because if I then hide the image and return to it, it will be at a random point in the animation, not the beginning, and if the animation does one thing and then stops, then it will stay permanently stuck at the end of the animation. Is there any way to reset these animations? I've tried hiding and showing the containing LC, I've tried hiding the image tag for the animation (which does nothing), I've tried using "on show" blocks, etc., nothing works. Here's a simplified example of what I'm working with, the actual versions are more complex, but basically I have to use LCs or something similar to achieve the intended results.

Code: Select all

image TestLC = LiveComposite(                                                                     
    (100,100),  
    (0,0), ConditionSwitch(                                                   
        "Variable", "TestAnimatedImage",
        "True", Null(),           
        ),  
    )

image TestAnimatedImage:                                                                              
    contains:                                                                         
        "images/image1.png"    
    contains:
        "images/image2.png" 
        pos (0,100)             #I've tried each of the below things, not all at once like shown, but one at a time:
        on show:
            ease .5 pos (100,0) #Option A
        block:
            ease .5 pos (100,0) #Option B            
        block:
            ease .5 pos (100,0) #Option C
            repeat
So, basically, I'd like something that would make this work. Right now it would display right the very first time this happens in the game, but would be broken on all subsequent showings. What I would like is to be able to reset this animation to it's default whenever necessary. Whether I can do that within the images themselves, or through some code I'd place around where I change the variable that would show/hide it, I can live with either way.

User avatar
namastaii
Miko-Class Veteran
Posts: 980
Joined: Mon Feb 02, 2015 8:35 pm
Projects: What Life; Barakana, Truth Beneath the Rose, Water Girl
Organization: Koompire, Clockwork Cafe
Github: namastaii
Skype: Discord: lunalucid#7684
Soundcloud: deadseed
Location: USA
Contact:

Re: Resetting animations within a live composite

#2 Post by namastaii » Sun Feb 28, 2016 1:14 am

Maybe the only way to prevent it from always doing the cycle and you ending up seeing the random parts and not from the beginning like you want, is to take that repeat off? Other than that, I don't know.

Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Re: Resetting animations within a live composite

#3 Post by Onishion » Sun Feb 28, 2016 1:46 am

Maybe the only way to prevent it from always doing the cycle and you ending up seeing the random parts and not from the beginning like you want, is to take that repeat off? Other than that, I don't know.
But if you take the repeat off, which I've tried, the result is that it will play through the animation exactly once and stick there. That might be what I want it to do the first time, bu the second time I cause the animation to happen, I want it to do it again, instead, it just appears already done with the animation and in its final position.

The only way to get the animation to start over again is to reload the game. I'm just wondering if there's some way to get the game to forcible reboot that animation cycle without having to reload the entire game.

User avatar
namastaii
Miko-Class Veteran
Posts: 980
Joined: Mon Feb 02, 2015 8:35 pm
Projects: What Life; Barakana, Truth Beneath the Rose, Water Girl
Organization: Koompire, Clockwork Cafe
Github: namastaii
Skype: Discord: lunalucid#7684
Soundcloud: deadseed
Location: USA
Contact:

Re: Resetting animations within a live composite

#4 Post by namastaii » Sun Feb 28, 2016 2:14 am

Well I don't think the animation can tell when it's being looked at or not so I think it just runs in the background. The only thing I can think of is somehow making the animation turn on and off somehow. And whenever you bring up the image on screen and want it to start again you change the variable to true and when it's taken off, change it to false? I'm not entirely sure what I'm talking about but that is what comes to mind.

Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Re: Resetting animations within a live composite

#5 Post by Onishion » Sun Feb 28, 2016 5:41 am

Right, I mean, to my mind, the animation should just automatically stop any time it's not being shown, but for some reason, this is not the case.

There is not a way, that I'm aware of, to cause the animation to stop once it's been started, at least not when it's part of a live composite. If it's a standalone image then doing "show image" and "hide image" and then "show image" again will cause it to start over, but using a variable inside an LC to show and hide an animated image does not do this.

I also worry that this might cause background issues, like if an LC contains multiple potential animated elements, but only shows a few at a time, once you get all of them started would they just keep animating in the background until you close the program, and would keeping track of all these animations cause any added workload?

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#6 Post by xela » Sun Feb 28, 2016 7:13 am

Onishion wrote:Right, I mean, to my mind, the animation should just automatically stop any time it's not being shown, but for some reason, this is not the case.
Depends on how the animation was coded and tracked. There are advantages and disadvantages to both approaches.
Onishion wrote:There is not a way, that I'm aware of, to cause the animation to stop once it's been started, at least not when it's part of a live composite. If it's a standalone image then doing "show image" and "hide image" and then "show image" again will cause it to start over, but using a variable inside an LC to show and hide an animated image does not do this.
There should be no difference between the two. LC is just a Fixed container that tries to position other displayable within it's bounds. The difference could be that it creates objects and works with those object from the time it was created until it is destroyed and show/hide recreate the object or reset their st/at.
Onishion wrote:I also worry that this might cause background issues, like if an LC contains multiple potential animated elements, but only shows a few at a time, once you get all of them started would they just keep animating in the background until you close the program, and would keeping track of all these animations cause any added workload?
No added workload, no need to worry about that. LC (being a simple Fixed) does not do it's own magic of any kind. Do not treat it as something special, unique or advanced.

===>>
There is no simple answer to your question, if you're looking to create a complex, controlled animation that jumps through any hoops, you may want to look into using a UDD for that because that is one of the simplest UDDs you can write. LC is a function that returns a Fixed with all of it's children as objects so it's a bit harder to control making it not the best choice for those tasks. If you just want to reset it, try writing a simple function that returns LC instead of declaring that as an image, that may work well if you which to reset it and it will not require copy/pasting the LC declaration all over the place (I am not sure but you may have to cheat a little bit to make LC objects unique as Ren'Py may try to check them for equality and use the last one shown instead of your new shiny object).
Like what we're doing? Support us at:
Image

Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Re: Resetting animations within a live composite

#7 Post by Onishion » Sun Feb 28, 2016 7:44 am

There should be no difference between the two. LC is just a Fixed container that tries to position other displayable within it's bounds. The difference could be that it creates objects and works with those object from the time it was created until it is destroyed and show/hide recreate the object or reset their st/at.
Well, be aware that showing and hiding and re-showing the LC that contains the images, as shown in the code above, does not reset the animations. It's possible that hiding it and then well later re-opening it might cause it to reset, but just flickering it certainly doesn't.
No added workload, no need to worry about that. LC (being a simple Fixed) does not do it's own magic of any kind. Do not treat it as something special, unique or advanced.
Well, I'm just saying, if you have an LC that includes, say, two dozen potential images that animate, but only shows two of them at any given time, right? then ideally, it would only cause the workload of calculating two different animations at a time, right? But if each time it starts an animation, it never stops, and keeps tracking those animations in the background the entire time, then once you've opened each, the game is juggling the full two dozen animations at once, even if that LC is put away entirely, and won't stop until the user closes and re-opens the game. I imagine at some point that could get "expensive."

I am only treating the LC as "special" in the sense that if the animation that I reference as "TestAnimatedImage" in the sample code above is called using the default "show/hide" commands, then they can work exactly like I want, they either start looping at the moment I call them, or they run once and then stop, but after hiding and showing them, they'll start from scratch. If, however, I make them visible/invisible as part of an LC construct, this behavior does not take place, it never resets.
There is no simple answer to your question, if you're looking to create a complex, controlled animation that jumps through any hoops, you may want to look into using a UDD for that because that is one of the simplest UDDs you can write. LC is a function that returns a Fixed with all of it's children as objects so it's a bit harder to control making it not the best choice for those tasks. If you just want to reset it, try writing a simple function that returns LC instead of declaring that as an image, that may work well if you which to reset it and it will not require copy/pasting the LC declaration all over the place (I am not sure but you may have to cheat a little bit to make LC objects unique as Ren'Py may try to check them for equality and use the last one shown instead of your new shiny object).
Hmm. I'm not sure how to do any of those things right now so I'd have to learn what would or would not work for my purposes. The actual LCs in question involve 16+ layers, containing a total of 60+ variable options, and I want to be able to move that entire construct around on the screen, which works for most of the things I want so far, but it's just not working out for some of the animations I'd like to run with it, which would require the ability to start and stop the animations at specific locations/timings/etc.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#8 Post by xela » Sun Feb 28, 2016 9:11 am

Onishion wrote:
There should be no difference between the two. LC is just a Fixed container that tries to position other displayable within it's bounds. The difference could be that it creates objects and works with those object from the time it was created until it is destroyed and show/hide recreate the object or reset their st/at.
Well, be aware that showing and hiding and re-showing the LC that contains the images, as shown in the code above, does not reset the animations. It's possible that hiding it and then well later re-opening it might cause it to reset, but just flickering it certainly doesn't.
As I've said, LC is a function that is returning a Fixed object and it's children as objects, you'll have to make sure that Ren'Py resets those objects somehow (shows them at st/at 0), create a new set of objects that do not equal to the former once.
Onishion wrote:if you have an LC that includes, say, two dozen potential images that animate, but only shows two of them at any given time, right? then ideally, it would only cause the workload of calculating two different animations at a time, right? But if each time it starts an animation, it never stops, and keeps tracking those animations in the background the entire time, then once you've opened each, the game is juggling the full two dozen animations at once, even if that LC is put away entirely, and won't stop until the user closes and re-opens the game. I imagine at some point that could get "expensive."
It's a fair question and I can see where it is coming from, personally I don't believe that it's working the way you describe and Ren'Py is not calculating each displayable "in the background" after it was hidden. My understanding of this process is that the state of a displayable is being calculated based of it's st/at at times it is shown but it is possible that some calculation are ran, I never really looked into this topic deeply...

In any case, these calculations take very, very little effort (CPU power) and you should not worry about them even if they are running, it will require massive computations to slow things down that may not be reachable in normal 2D environment without taking extraordinary measures, even with PL like Python and without code optimizations.
Onishion wrote:I am only treating the LC as "special" in the sense that if the animation that I reference as "TestAnimatedImage" in the sample code above is called using the default "show/hide" commands, then they can work exactly like I want, they either start looping at the moment I call them, or they run once and then stop, but after hiding and showing them, they'll start from scratch. If, however, I make them visible/invisible as part of an LC construct, this behavior does not take place, it never resets.
LC == Fixed. As I've said in previous post and in explanation above, st/at is what actually matters and st is 0 at the moment the container containing the displayable is shown for all of it's children. So when you are changing the value of your condition, lets say after 5 seconds have passed, displayable bound to "TestAnimatedImage" is getting st of 5 instead of a 0 and returns the appropriate render to that time-stamp. Screens that also hold displayable work in the same way, all other containers do the same thing as far as I know.

If it never resets at all even if you show it under different tag is that it's tracking it's own st and it's object is never reset in any way or form (so I suggested to recreate the object using a (for example) function).
Onishion wrote:which would require the ability to start and stop the animations at specific locations/timings/etc.
That would require either a wrapper around the displayable you're using or UDDs (which are more or less the same thing with slightly different degrees of complexity), I do not believe that what you're asking is doable using the standard Ren'Py tools (if it is, I don't know how to do it without the UDD or anything that gets st/at and we can control).
Like what we're doing? Support us at:
Image

Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Re: Resetting animations within a live composite

#9 Post by Onishion » Sun Feb 28, 2016 10:08 am

As I've said, LC is a function that is returning a Fixed object and it's children as objects, you'll have to make sure that Ren'Py resets those objects somehow (shows them at st/at 0), create a new set of objects that do not equal to the former once.
Ok, I just have no idea how to do that, hence the question. ;)
It's a fair question and I can see where it is coming from, personally I don't believe that it's working the way you describe and Ren'Py is not calculating each displayable "in the background" after it was hidden. My understanding of this process is that the state of a displayable is being calculated based of it's st/at at times it is shown but it is possible that some calculation are ran, I never really looked into this topic deeply...
It could be possible that it pauses them, but I think the way it works is that if you have an animation in an LC that is like, say a clock, and you start it at 12 o'clock and let it run to 4, and then swap it out with something else for several seconds, and then back on, then it definitely won't be back at 12, and I don't think it'll still be at 4, I think it'll be at 6 or wherever it would have gotten to if it had been visible the entire time. Haven't tried that specific example, but I'm pretty sure it just keeps moving.
In any case, these calculations take very, very little effort (CPU power) and you should not worry about them even if they are running, it will require massive computations to slow things down that may not be reachable in normal 2D environment without taking extraordinary measures, even with PL like Python and without code optimizations.
Ok, well that at least is not an issue then. I always worry a bit too much about how much things "cost" and try to make them as efficient as possible. Turning out the lights when I leave a room is just common decency. ;)
If it never resets at all even if you show it under different tag is that it's tracking it's own st and it's object is never reset in any way or form (so I suggested to recreate the object using a (for example) function).
Could you provide a code example though? Because I'm unsure how to do that in this context. Like if the example code in the OP is a base, how would one display that as a function? Is it something simple in just the way I "show/hide" the existing LC, or would I need to write the LC differently, or design some entirely new block of code, which would be way outside my capabilities. I mean, just for reference, I've been using Renpy for about a year now, and Python within that context, and have been able to do some relatively complex things within that framework, but that's the extend of my programming skills, so a lot of the "break Renpy" stuff just flies right over my head when not in very simple terms. I appreciate the help, I'm just left unsure how to apply it.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#10 Post by xela » Sun Feb 28, 2016 11:38 am

Couldn't delete the post...
Last edited by xela on Sun Feb 28, 2016 6:15 pm, edited 1 time in total.
Like what we're doing? Support us at:
Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#11 Post by xela » Sun Feb 28, 2016 12:31 pm

Couldn't delete the post...
Last edited by xela on Sun Feb 28, 2016 6:15 pm, edited 1 time in total.
Like what we're doing? Support us at:
Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#12 Post by xela » Sun Feb 28, 2016 2:32 pm

Couldn't delete the post...
Last edited by xela on Sun Feb 28, 2016 6:16 pm, edited 1 time in total.
Like what we're doing? Support us at:
Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#13 Post by xela » Sun Feb 28, 2016 3:29 pm

Ok.. so after a couple of posts and 100+ edits, I'll just summarize the whole thing here:

1) Ren'Py will NOT calculate anything "in the background" when the image is not shown. Period, there should be no "ifs"/"buts" here unless I've missed something.

2) Both versions of the "clock" you've mentioned are possible and neither will calculate anything "in the background" when not shown, so any concerns about computations and loading cpu are not valid.

3) I came up with this class to have some control over animations:

Code: Select all

init python:
    class DisplayableSwitcher(renpy.Displayable, NoRollback):
        DEFAULT = {"d": Null(), "start_st": 0, "pause_st": 0}
        
        """This plainly switches displayable without reshowing the image/changing any variables by calling change method.
        """
        
        def __init__(self, start_displayable="default", displayable=None, **kwargs):
            """Expects a dict of displayable={"string": something we can show in Ren'Py}
           
            Default is Null() unless specified otherwise.
            """
            super(DisplayableSwitcher, self).__init__(**kwargs)
            if not isinstance(displayable, dict):
                self.displayable = {"default": self.DEFAULT.copy()}
            else:
                self.displayable = {}
                for s, d in displayable.iteritems():
                    self.displayable[s] = self.DEFAULT.copy()
                    d = renpy.easy.displayable(d)
                    if isinstance(d, ImageReference):
                        d = renpy.display.image.images[(d.name)]
                    self.displayable[s]["d"] = d
                    if isinstance(d, renpy.atl.ATLTransformBase):
                        self.displayable[s]["atl"] = d.copy()
                        
                self.displayable["default"] = displayable.get("default", self.DEFAULT.copy())
               
            self.d = self.displayable[start_displayable]
            self.animation_mode = "normal"
            self.last_st = 0
           
        def change(self, s, mode="normal"):
            self.d = self.displayable.get(s, self.displayable["default"])
            
            self.animation_mode = mode
            if mode == "reset":
                self.d["force_restart"] = 1
            elif mode == "pause":
                self.d["pause_st"] = self.last_st - self.d["start_st"]
            elif mode == "resume":
                self.d["force_resume"] = 1
            
        def render(self, width, height, st, at):
            if not st:
                for d in self.displayable.itervalues():
                    d["start_st"] = 0
                    d["pause_st"] = 0
                    self.animation_mode = "normal"
                    
            rp = store.renpy
            
            self.last_st = st
            
            render = rp.Render(width, height)
            
            if self.animation_mode == "reset":
                if "force_restart" in self.d:
                    del self.d["force_restart"]
                    if "atl" in self.d:
                        self.d["d"].take_execution_state(self.d["atl"])
                        self.d["d"].atl_st_offset = st
                    else:
                        self.d["start_st"] = st
                st = st - self.d["start_st"] if not "atl" in self.d else st
            elif self.animation_mode in ("pause", "show_paused"):
                st = self.d["pause_st"]
            elif self.animation_mode == "resume":
                if "force_resume" in self.d:
                    del self.d["force_resume"]
                    self.d["start_st"] = st
                st = st - self.d["start_st"] + self.d["pause_st"]
                
            d = self.d["d"]
            cr = d.render(width, height, st, at)
            
            try:
                position = d.get_placement()
                x, y = position[:2]
            except:
                x, y = 0, 0
            render.blit(cr, (x, y))
            
            rp.redraw(self, 0)
            return render
           
        def visit(self):
            return [v["d"] for v in self.displayable.values()]
and this as a possible testcase scenario:

Code: Select all

 
default test_case = DisplayableSwitcher(displayable={"test": "test_image"})

image test_image:
    Text("MEOW1")
    linear 10 pos (300, 500)
    Text("MEOW2")

label start:
    show expression test_case
    while 1:
        $ test_case.change("test")
        "Shown Normally"
        $ test_case.change("default")
        "Hidden"
        $ test_case.change("test", "reset")
        "Reset"
        $ test_case.change("test", "pause")
        "Pause"
        $ test_case.change("default")
        "Hide Again"
        $ test_case.change("test", "show_paused")
        "Show Paused"
        $ test_case.change("test", "resume")
        "Resume From where we left off"

So your example might look something like (not tested but the general concept is sound):

Code: Select all

default switch_1 = DisplayableSwitcher(                                                   
        {"TAI": "TestAnimatedImage"},           
        )
default TestLC = LiveComposite(                                                                     
    (100,100), 
    (0,0), switch_1, 
    )

image TestAnimatedImage:                                                                             
    contains:                                                                         
        "images/image1.png"   
    contains:
        "images/image2.png"
        pos (0,100)             #I've tried each of the below things, not all at once like shown, but one at a time:
        on show:
            ease .5 pos (100,0) #Option A
        block:
            ease .5 pos (100,0) #Option B           
        block:
            ease .5 pos (100,0) #Option C
            repeat
Note: We're using some of the functionality not directly exposed to developers here so it may be a subject to change and updated in the future.

Note 2: I never use Rollback so my experience with that is very limited, I am not quite sure how to merge "resetting" animation state with rollback. Maybe somebody else can offer a suggestion.

====>>>
This was a lot of fun and I will use it in my projects and improve in the future when I figure out new ways to do so. I've learned boatload about Ren'Py internals in either case :)
Like what we're doing? Support us at:
Image

Onishion
Veteran
Posts: 293
Joined: Mon Apr 20, 2015 10:36 am
Contact:

Re: Resetting animations within a live composite

#14 Post by Onishion » Sun Feb 28, 2016 7:44 pm

Wow, there is a lot to that! Thanks for working it out.

I tried to play with it a bit, but can't get it working right. I copy/pasted the class code into my game, then the "default switch_1" block, but when I tried to have switch_1 in my LC in any form it failed to launch with a "switch_1 not defined" error. Then I removed that bit from the LC just to see if the game would launch at all, but it threw up a traceback error that ended with:

self.d = self.displayable[start_displayable]
TypeError: unhashable type: 'RevertableDict'

Maybe I just put it in wrong or something.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Resetting animations within a live composite

#15 Post by xela » Sun Feb 28, 2016 8:23 pm

Onishion wrote:I tried to play with it a bit, but can't get it working right.
My bad, I made a few bad assumptions, new class (this may need to be updated in the future if new issues arise):

Code: Select all

init python:
    class DisplayableSwitcher(renpy.Displayable, NoRollback):
        DEFAULT = {"d": Null(), "start_st": 0, "pause_st": 0, "force_pause": 0, "force_resume": 0}
        
        """This plainly switches displayable without reshowing the image/changing any variables by calling change method.
        """
        
        def __init__(self, start_displayable="default", displayable=None, **kwargs):
            """Expects a dict of displayable={"string": something we can show in Ren'Py}
           
            Default is Null() unless specified otherwise.
            """
            super(DisplayableSwitcher, self).__init__(**kwargs)
            if not isinstance(displayable, dict):
                self.displayable = {"default": self.DEFAULT.copy()}
            else:
                self.displayable = {}
                for s, d in displayable.iteritems():
                    self.displayable[s] = self.DEFAULT.copy()
                    d = renpy.easy.displayable(d)
                    if isinstance(d, ImageReference):
                        d = renpy.display.image.images[(d.name)]
                    self.displayable[s]["d"] = d
                    if isinstance(d, renpy.atl.ATLTransformBase):
                        self.displayable[s]["atl"] = d.copy()
                        
                self.displayable["default"] = displayable.get("default", self.DEFAULT.copy())
               
            self.d = self.displayable[start_displayable]
            self.animation_mode = "normal"
            self.last_st = 0
           
        def change(self, s, mode="normal"):
            self.d = self.displayable.get(s, self.displayable["default"])
            
            self.animation_mode = mode
            if mode == "reset":
                self.d["force_restart"] = 1
            elif mode == "pause":
                self.d["pause_st"] = self.last_st - self.d["start_st"]
            elif mode == "resume":
                self.d["force_resume"] = 1
            
        def render(self, width, height, st, at):
            if not st:
                for d in self.displayable.itervalues():
                    d["start_st"] = 0
                    d["pause_st"] = 0
                    
            rp = store.renpy
            
            self.last_st = st
            
            if self.animation_mode == "reset":
                if self.d["force_restart"]:
                    self.d["force_restart"] = 0
                    if "atl" in self.d:
                        self.d["d"].take_execution_state(self.d["atl"])
                        self.d["d"].atl_st_offset = st
                    else:
                        self.d["start_st"] = st
                st = st - self.d["start_st"] if not "atl" in self.d else st
            elif self.animation_mode in ("pause", "show_paused"):
                st = self.d["pause_st"]
            elif self.animation_mode == "resume":
                if self.d["force_resume"]:
                    self.d["force_resume"] = 0
                    self.d["start_st"] = st
                st = st - self.d["start_st"] + self.d["pause_st"]
                
            d = self.d["d"]
            cr = d.render(width, height, st, at)
            size = cr.get_size()
            render = rp.Render(size[0], size[1])
            
            try:
                position = d.get_placement()
                x, y = position[:2]
                if x is None:
                    x = 0
                if y is None:
                    y = 0
            except:
                x, y = 0, 0
            render.blit(cr, (x, y))
            
            rp.redraw(self, 0)
            return render
           
        def visit(self):
            return [v["d"] for v in self.displayable.values()]
New testing case synced to your example:

Code: Select all

default test_case = DisplayableSwitcher(displayable={"test": "TestAnimatedImage"})
default TestLC = LiveComposite(                                                                     
    (100, 100),
    (0, 0), test_case,
    )

image TestAnimatedImage:
    contains:
        Text("Meow")
    contains:
        Text("Meow2")
        pos (0, 100)             #I've tried each of the below things, not all at once like shown, but one at a time:
        ease .5 pos (100, 0) #Option A

label start:
    show expression TestLC at Transform(align=(0.5, 0.5))
    while 1:
        $ test_case.change("test")
        "Shown Normally"
        $ test_case.change("default")
        "Hidden"
        $ test_case.change("test", "reset")
        "Reset"
        $ test_case.change("test", "pause")
        "Pause"
        $ test_case.change("default")
        "Hide Again"
        $ test_case.change("test", "show_paused")
        "Show Paused"
        $ test_case.change("test", "resume")
        "Resume From where we left off"
Like what we're doing? Support us at:
Image

Post Reply

Who is online

Users browsing this forum: Andredron, Google [Bot]