Okay I think I've got a solution that allows me to use Transforms even inside a screen. The original problem was that after the first transform, the ST value being passed kept increasing freely. So when the screen redraws, even a newly added transform thinks it's already been running for 14 seconds. Hence it instantly completing instead of slowly fading in.
So I made a custom displayable that accepts a transform in the constructor. The first render it sets the st_offset to -1 * ST. Thus if the ST begins at 14 seconds the offset will be -14, making the transform start at time zero.
Things to be aware of: The transform must remain in its original state. My constructor makes a deep copy before using it, but if some outside code runs the transform it could muck up the state and you start seeing the original bug again. Even if you return to the main menu it'll remain broken.
Next: Leaving the screen and returning to it resets the ST to zero. If you're caching images like I am, you have to dump the cache and recreate it. Otherwise, if an old image has st_offset == -14, and now ST is at 0 again, your displayable will re-transform after 14 seconds brings you back to time zero. I think image caching like this isn't typical though, I just want it so when hover events redraw the screen my transforms aren't lost. My screen just pulls the images out of a list, and the list gets rebuilt only when necessary.
Alright enough of that, here's the code:
Code: Select all
# This is how you use the displayable/transform wrapper
# What's important is providing the xpos, ypos, and trans (the transform you want)
# SuperTile is just a replacement for LiveTile that implements the bug fix found here:
# https://github.com/renpy/renpy/commit/13ee355
# Any other Displayable would work fine though
DisplayTransformer(SuperTile("redline.png", area= (linkX, linkY, linkDist, 7)) , xpos= linkX, ypos= linkY, trans=ttfadein)
#........ Now the actual class itself ..........
init python:
import math
class DisplayTransformer(renpy.Displayable):
def __init__(self, child, trans, **kwargs):
# Pass additional properties on to the renpy.Displayable
# constructor.
super(DisplayTransformer, self).__init__(**kwargs)
# The child.
self.child = renpy.displayable(child)
# Claim our transform and impregnate it with our displayable
# Also make a copy of it first, otherwise we'll junk up
# the state of the original copy
self.trans = trans.copy()
self.trans.set_child(self.child)
# Is this our first render? oh the excitement
self.firstupdate = True
def render(self, width, height, st, at):
# If this is our first time running this transform
# Renpy might tell us we're starting at 4.5 seconds
# So let's offset by -4.5 seconds so we actually
# begin at step 0 like we should
if self.firstupdate == True:
self.trans.at_offset = -1 * at
self.trans.st_offset = -1 * st
# We want to progress beyond time zero so stop this from ever happening again
self.firstupdate = False
# Create a render from the child.
child_render = renpy.render(self.trans, width, height, st, at)
# Get the size of the child.
childWidth, childHeight = child_render.get_size()
# Create the render we will return.
render = renpy.Render(childWidth, childHeight)
# Blit (draw) the child's render to our render.
render.blit(child_render, (0, 0))
# Return the render.
return render