TransitionShowingSwitch and TransitionConditionSwitch

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

TransitionShowingSwitch and TransitionConditionSwitch

#1 Post by Asceai » Sun May 18, 2014 9:50 pm

Code: Select all

init python:
    class TransitionShowingSwitch(renpy.Displayable):
        def __init__(self, transition, *args, **kwargs):
            super(TransitionShowingSwitch, self).__init__(**kwargs)
            self.layer = kwargs.pop('layer', 'master')
            self.transition = transition
            self.d = zip(args[0::2], args[1::2])
            self.time_reset = True
            self.old_d = None
            self.current_d = None
            self.ta = None
        def render(self, width, height, st, at):
            if self.time_reset:
                self.time_reset = False
                self.st = st
                self.at = at
            return renpy.render(self.ta, width, height, st-self.st, at-self.at)
        def per_interact(self):
            for name, d in self.d:
                if name is None or renpy.showing(name, layer=self.layer):
                    change_to = d
                    break
            if change_to is not self.current_d:
                self.time_reset = True
                self.old_d = self.current_d
                self.current_d = change_to
                if self.old_d is None:
                    self.old_d = self.current_d
                self.ta = anim.TransitionAnimation(self.old_d, 0.00, self.transition, self.current_d)
                renpy.redraw(self, 0)
        def visit(self):
            return [ self.ta ]
This mess is just ShowingSwitch, except you supply a transition (e.g. dissolve) as the first argument and that transition is used when the image changes.

This should be useful for those people (e.g. SelLi) that want fading side images.

EDIT: If you want to use this with alpha-transparent images, use Dissolve(duration, alpha=True) as the transition.
Last edited by Asceai on Fri Jun 06, 2014 10:25 pm, edited 1 time in total.

User avatar
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch

#2 Post by Arowana » Fri Jun 06, 2014 9:12 pm

This looks pretty neat, Asceai! Do you know if it's possible to write something similar for ConditionSwitch? I know many people (including myself) have been looking for a good ConditionSwitch with transitions method. :)
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

Re: TransitionShowingSwitch

#3 Post by Asceai » Fri Jun 06, 2014 9:29 pm

Code: Select all

init python:
    class TransitionConditionSwitch(renpy.Displayable):
        def __init__(self, transition, *args, **kwargs):
            super(TransitionConditionSwitch, self).__init__(**kwargs)
            self.transition = transition
            self.d = zip(args[0::2], args[1::2])
            self.time_reset = True
            self.old_d = None
            self.current_d = None
            self.ta = None
        def render(self, width, height, st, at):
            if self.time_reset:
                self.time_reset = False
                self.st = st
                self.at = at
            return renpy.render(self.ta, width, height, st-self.st, at-self.at)
        def per_interact(self):
            for name, d in self.d:
                if eval(name):
                    change_to = d
                    break
            if change_to is not self.current_d:
                self.time_reset = True
                self.old_d = self.current_d
                self.current_d = change_to
                if self.old_d is None:
                    self.old_d = self.current_d
                self.ta = anim.TransitionAnimation(self.old_d, 0.00, self.transition, self.current_d)
                renpy.redraw(self, 0)
        def visit(self):
            return [ self.ta ]

User avatar
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch

#4 Post by Arowana » Fri Jun 06, 2014 10:10 pm

Wow, thanks for replying so quickly! I did have to add one line to avoid errors:

Code: Select all

    def per_interact(self):
        change_to = self.current_d #default value 
        for name, d in self.d:
            ...
but after that, your code works wonderfully for me! Thank you *so* much - this is absolutely lovely and a huge time saver! if I could send you cookies through the internet right now, I would! :D :D :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
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch and TransitionConditionSwitch

#5 Post by Arowana » Sat Jun 28, 2014 11:08 pm

Sorry to double post, but I've run into a problem using TransitionConditionSwitch with side sprites. I think it might have to do with the way the "say" screen updates?

For example, here is a simple image with TransitionConditionSwitch that is used as a side sprite:

Code: Select all

image girl = TransitionConditionSwitch(Dissolve(0.5, alpha=True),
    "face == 'normal' ", "girl_normal.png",
    "face == 'sad' ", "girl_sad.png")

define e = Character('Eileen', color="#c8ffc8", show_side_image = "girl")
Now try to run something like

Code: Select all

label start:
    $ face = "normal"
    e "My normal face."
    $ face = "sad"
    e "My sad face."
    e "If I keep talking, my face starts to flicker back to normal, then sad."
    e "Maybe the sprite state isn't updating properly?"
The same "girl" image works fine when it is a regular image, not a side sprite, so I'm guessing it has to do with the "say" screen? Any idea how to fix this?
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
chocoberrie
Veteran
Posts: 254
Joined: Wed Jun 19, 2013 10:34 pm
Projects: Marshmallow Days
Contact:

Re: TransitionShowingSwitch and TransitionConditionSwitch

#6 Post by chocoberrie » Sun Jun 29, 2014 12:14 am

I'm having issues with the TransitionShowingSwitch myself, and I could really use some help as well. :( (Here's my original post.)

User avatar
Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

#7 Post by Asceai » Sun Jun 29, 2014 1:56 am

Arowana wrote:Sorry to double post, but I've run into a problem using TransitionConditionSwitch with side sprites. I think it might have to do with the way the "say" screen updates?
Quite right. The 'say' screen is hidden and shown for every text block. This has the effect of resetting both timebases. TransitionConditionSwitch's behaviour is to just remain on the last frame of its transitionanimation until the variable changes; however, with the timebases being reset all the time, the same animation keeps playing over and over again.

The problem is also that per_interact is called a ton of times - so I can't make the assumption that each interact means a new text block and I can overwrite old_d with current_d - in fact, doing that results in no animation happening at all because per_interact is called many times.

You could perhaps redo the side image code to work on a different screen, one that doesn't get hidden and reshown all the time (only when necessary).

EDIT: Here's a bit of a nasty hack. I'm not sure whether I want to replace the proper TransitionConditionSwitch with this or not:

Code: Select all

init python:
    class TransitionConditionSwitch(renpy.Displayable):
        def __init__(self, transition, *args, **kwargs):
            super(TransitionConditionSwitch, self).__init__(**kwargs)
            self.transition = transition
            self.d = zip(args[0::2], args[1::2])
            self.time_reset = True
            self.old_d = None
            self.current_d = None
            self.ta = None
            self.old_st = 0
        def render(self, width, height, st, at):
            if self.time_reset:
                self.time_reset = False
                self.st = st
                self.at = at
                self.old_st = 0
            if st < self.old_st:
              self.st, self.at, st, at = 0, 0, 1000000.0, 1000000.0
            self.old_st = st
            return renpy.render(self.ta, width, height, st-self.st, at-self.at)
        def per_interact(self):
            for name, d in self.d:
                if eval(name):
                    change_to = d
                    break
            if change_to is not self.current_d:
                self.time_reset = True
                self.old_d = self.current_d
                self.current_d = change_to
                if self.old_d is None:
                    self.old_d = self.current_d
                self.ta = anim.TransitionAnimation(self.old_d, 0.00, self.transition, self.current_d)
                renpy.redraw(self, 0)
        def visit(self):
            return [ self.ta ]
Basically, it detects a timebase rewind and sets both time bases to 1 million seconds (longer than any effect will be). A timebase rewind should only happen in hide/show cases like this- it should continue functioning normally otherwise.

User avatar
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch and TransitionConditionSwitch

#8 Post by Arowana » Sun Jun 29, 2014 2:36 am

Oh wow, that's pretty clever. Once again, I must thank you and salute your programming prowess! :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
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch and TransitionConditionSwitch

#9 Post by Arowana » Mon Jun 30, 2014 12:38 am

Sorry to ask yet another question (hopefully this the last one! :oops: ), but I've run into a second issue with this code that's got me rather puzzled.

If I have two images with the same tag, one of which is using TransitionConditionSwitch, then I have problems trying to apply even simple transforms. For example, say my images are:

Code: Select all

image girl awake = TransitionConditionSwitch(Dissolve(0.5, alpha=True),
    "face == 'normal' ", "girl_normal.png",
    "face == 'sad' ", "girl_sad.png")

image girl asleep = "girl_asleep.png"
Now if I run:

Code: Select all

$ face = "sad"
show girl awake:
    xpos 0.5
"I'm tired, so I'm going to bed."
show girl asleep
the game crashes and I get an exception on the line

Code: Select all

return renpy.render(self.ta, width, height, st-self.st, at-self.at)
with Attribute Error: 'NoneType' object has no attribute 'style'.

If I take out the "xpos" transform, then the code runs fine. Any idea why it won't work when I try to use the transform?
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

Re: TransitionShowingSwitch and TransitionConditionSwitch

#10 Post by Asceai » Mon Jun 30, 2014 1:00 am

Doesn't do that for me.

Here's my testing code:

Code: Select all

init python:
    class TransitionConditionSwitch(renpy.Displayable):
        def __init__(self, transition, *args, **kwargs):
            super(TransitionConditionSwitch, self).__init__(**kwargs)
            self.transition = transition
            self.d = zip(args[0::2], args[1::2])
            self.time_reset = True
            self.old_d = None
            self.current_d = None
            self.ta = None
            self.old_st = 0
        def render(self, width, height, st, at):
            if self.time_reset:
                self.time_reset = False
                self.st = st
                self.at = at
                self.old_st = 0
            if st < self.old_st:
              self.st, self.at, st, at = 0, 0, 1000000.0, 1000000.0
            self.old_st = st
            return renpy.render(self.ta, width, height, st-self.st, at-self.at)
        def per_interact(self):
            for name, d in self.d:
                if eval(name):
                    change_to = d
                    break
            if change_to is not self.current_d:
                self.time_reset = True
                self.old_d = self.current_d
                self.current_d = change_to
                if self.old_d is None:
                    self.old_d = self.current_d
                self.ta = anim.TransitionAnimation(self.old_d, 0.00, self.transition, self.current_d)
                renpy.redraw(self, 0)
        def visit(self):
            return [ self.ta ]

image girl awake = TransitionConditionSwitch(Dissolve(0.5, alpha=True),
    "face == 'normal' ", "girl_normal.png",
    "face == 'sad' ", "girl_sad.png")

image girl asleep = "girl_asleep.png"

label start:
  $ face = "sad"
  show girl awake:
      xpos 0.5
  "I'm tired, so I'm going to bed."
  show girl asleep
  "test end"
  return

User avatar
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch and TransitionConditionSwitch

#11 Post by Arowana » Mon Jun 30, 2014 1:23 am

Oops, sorry, this might only happen in reverse showing order. See if this will give you an error (it does for me):

Code: Select all

label start:
  $ face = "sad"
  show girl asleep:
      xpos 0.5
  "I don't want to wake up, but I have to."
  show girl awake
  "test end"
  return
Alternatively, if both images are using TransitionConditionSwitch, then the same error occurs regardless of showing order. E.g.:

Code: Select all

image girl awake = TransitionConditionSwitch(Dissolve(0.5, alpha=True),
    "face == 'normal' ", "girl_normal.png",
    "face == 'sad' ", "girl_sad.png")

image girl asleep = TransitionConditionSwitch(Dissolve(0.5, alpha=True),
    "face == 'normal' ", "girl_asleep_normal.png",
    "face == 'sad' ", "girl_asleep_sad.png")

label start:
  $ face = "sad"
  show girl awake:
      xpos 0.5
  "I'm tired, so I'm going to bed."
  show girl asleep
  "test end"
  return
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

User avatar
Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

Re: TransitionShowingSwitch and TransitionConditionSwitch

#12 Post by Asceai » Mon Jun 30, 2014 1:39 am

Huh. Looks like in that case it gets rendered before per_interact is called.

Here's another hack:

Code: Select all

init python:
    class TransitionConditionSwitch(renpy.Displayable):
        def __init__(self, transition, *args, **kwargs):
            super(TransitionConditionSwitch, self).__init__(**kwargs)
            self.transition = transition
            self.d = zip(args[0::2], args[1::2])
            self.time_reset = True
            self.old_d = None
            self.current_d = None
            self.ta = None
            self.old_st = 0
        def render(self, width, height, st, at):
            if self.ta is None:
              self.per_interact()
            if self.time_reset:
                self.time_reset = False
                self.st = st
                self.at = at
                self.old_st = 0
            if st < self.old_st:
              self.st, self.at, st, at = 0, 0, 1000000.0, 1000000.0
            self.old_st = st
            return renpy.render(self.ta, width, height, st-self.st, at-self.at)
        def per_interact(self):
            for name, d in self.d:
                if eval(name):
                    change_to = d
                    break
            if change_to is not self.current_d:
                self.time_reset = True
                self.old_d = self.current_d
                self.current_d = change_to
                if self.old_d is None:
                    self.old_d = self.current_d
                self.ta = anim.TransitionAnimation(self.old_d, 0.00, self.transition, self.current_d)
                renpy.redraw(self, 0)
        def visit(self):

User avatar
Arowana
Miko-Class Veteran
Posts: 531
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: TransitionShowingSwitch and TransitionConditionSwitch

#13 Post by Arowana » Mon Jun 30, 2014 1:54 am

That indeed does the trick! Thanks once again for your speedy and insightful reply. :D
Complete: a2 ~a due~ (music, language, love)
In progress: The Pirate Mermaid (fairytale otome)
On hold: AXIOM.01 (girl detective game)

Image

Post Reply

Who is online

Users browsing this forum: No registered users