summaryrefslogtreecommitdiff
path: root/unrpyc/renpy/display/anim.py
diff options
context:
space:
mode:
Diffstat (limited to 'unrpyc/renpy/display/anim.py')
-rw-r--r--unrpyc/renpy/display/anim.py634
1 files changed, 0 insertions, 634 deletions
diff --git a/unrpyc/renpy/display/anim.py b/unrpyc/renpy/display/anim.py
deleted file mode 100644
index de1398a..0000000
--- a/unrpyc/renpy/display/anim.py
+++ /dev/null
@@ -1,634 +0,0 @@
-# Copyright 2004-2013 Tom Rothamel <pytom@bishoujo.us>
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-# This file contains support for state-machine controlled animations.
-
-import renpy.display
-import random
-
-class State(object):
- """
- This creates a state that can be used in a SMAnimation.
- """
-
-
- def __init__(self, name, image, *atlist, **properties):
- """
- @param name: A string giving the name of this state.
-
- @param image: The displayable that is shown to the user while
- we are in (entering) this state. For convenience, this can
- also be a string or tuple, which is interpreted with Image.
-
- image should be None when this State is used with motion,
- to indicate that the image will be replaced with the child of
- the motion.
-
- @param atlist: A list of functions to call on the image. (In
- general, if something can be used in an at clause, it can be
- used here as well.)
-
- If any keyword arguments are given, they are used to construct a
- Position object, that modifies the position of the image.
- """
-
- if image and not isinstance(image, renpy.display.core.Displayable):
- image = renpy.easy.displayable(image)
-
- self.name = name
- self.image = image
- self.atlist = atlist
- self.properties = properties
-
-
- def add(self, sma):
- sma.states[self.name] = self
-
- def get_image(self):
- rv = self.image
-
- for i in self.atlist:
- rv = i(rv)
-
- if self.properties:
- rv = renpy.display.layout.Position(rv, **self.properties)
-
- return rv
-
- def motion_copy(self, child):
-
- if self.image is not None:
- child = self.image
-
- return State(self.name, child, *self.atlist)
-
-
-class Edge(object):
- """
- This creates an edge that can be used with a SMAnimation.
- """
-
- def __init__(self, old, delay, new, trans=None, prob=1):
- """
- @param old: The name (a string) of the state that this transition is from.
-
- @param delay: The number of seconds that this transition takes.
-
- @param new: The name (a string) of the state that this transition is to.
-
- @param trans: The transition that will be used to show the
- image found in the new state. If None, the image is show
- immediately.
-
- When used with an SMMotion, the transition should probably be
- move.
-
- @param prob: The number of times this edge is added. This can
- be used to make a transition more probable then others. For
- example, if one transition out of a state has prob=5, and the
- other has prob=1, then the one with prob=5 will execute 5/6 of
- the time, while the one with prob=1 will only occur 1/6 of the
- time. (Don't make this too large, as memory use is proportional to
- this value.)
- """
-
- self.old = old
- self.delay = delay
- self.new = new
- self.trans = trans
- self.prob = prob
-
- def add(self, sma):
- for _i in range(0, self.prob):
- sma.edges.setdefault(self.old, []).append(self)
-
-
-class SMAnimation(renpy.display.core.Displayable):
- """
- This creates a state-machine animation. Such an animation is
- created by randomly traversing the edges between states in a
- defined state machine. Each state corresponds to an image shown to
- the user, with the edges corresponding to the amount of time an
- image is shown, and the transition it is shown with.
-
- Images are shown, perhaps with a transition, when we are
- transitioning into a state containing that image.
- """
-
- def __init__(self, initial, *args, **properties):
- """
- @param initial: The name (a string) of the initial state we
- start in.
-
- @param showold: If the keyword parameter showold is True, then
- the old image is shown instead of the new image when in an
- edge.
-
- @param anim_timebase: If True, we use the animation
- timebase. If False, we use the displayable timebase.
-
- This accepts as additional arguments the anim.State and
- anim.Edge objects that are used to make up this state
- machine.
- """
-
- if 'delay' in properties:
- self.delay = properties['delay']
- del properties['delay']
- else:
- self.delay = None
-
- if 'showold' in properties:
- self.showold = properties['showold']
- del properties['showold']
- else:
- self.showold = False
-
- if 'anim_timebase' in properties:
- self.anim_timebase = properties['anim_timebase']
- del properties['anim_timebase']
- else:
- self.anim_timebase = True
-
- super(SMAnimation, self).__init__(**properties)
-
- self.properties = properties
-
- # The initial state.
- self.initial = initial
-
- # A map from state name to State object.
- self.states = { }
-
- # A map from state name to list of Edge objects.
- self.edges = { }
-
- for i in args:
- i.add(self)
-
- # The time at which the current edge started. If None, will be
- # set to st by render.
- self.edge_start = None
-
- # A cache for what the current edge looks like when rendered.
- self.edge_cache = None
-
- # The current edge.
- self.edge = None
-
- # The state we're in.
- self.state = None
-
- def visit(self):
- return [ i.image for i in self.states.values() ]
-
- def pick_edge(self, state):
- """
- This randomly picks an edge out of the given state, if
- one exists. It updates self.edge if a transition has
- been selected, or returns None if none can be found. It also
- updates self.image to be the new image on the selected edge.
- """
-
- if state not in self.edges:
- self.edge = None
- return
-
- edges = self.edges[state]
- self.edge = random.choice(edges)
- self.state = self.edge.new
-
- def update_cache(self):
- """
- Places the correct Displayable into the edge cache, based on
- what is contained in the given edge. This takes into account
- the old and new states, and any transition that is present.
- """
-
-
- if self.edge.trans:
- im = self.edge.trans(old_widget=self.states[self.edge.old].get_image(),
- new_widget=self.states[self.edge.new].get_image())
- elif self.showold:
- im = self.states[self.edge.old].get_image()
- else:
- im = self.states[self.edge.new].get_image()
-
- self.edge_cache = im
-
- def get_placement(self):
-
- if self.edge_cache:
- return self.edge_cache.get_placement()
-
- if self.state:
- return self.states[self.state].get_image().get_placement()
-
- return super(SMAnimation, self).get_placement()
-
- def render(self, width, height, st, at):
-
- if self.anim_timebase:
- t = at
- else:
- t = st
-
- if self.edge_start is None or t < self.edge_start:
- self.edge_start = t
- self.edge_cache = None
- self.pick_edge(self.initial)
-
- while self.edge and t > self.edge_start + self.edge.delay:
- self.edge_start += self.edge.delay
- self.edge_cache = None
- self.pick_edge(self.edge.new)
-
- # If edge is None, then we have a permanent, static picture. Deal
- # with that.
-
- if not self.edge:
- im = renpy.display.render.render(self.states[self.state].get_image(),
- width, height,
- st - self.edge_start, at)
-
-
- # Otherwise, we have another edge.
-
- else:
- if not self.edge_cache:
- self.update_cache()
-
- im = renpy.display.render.render(self.edge_cache, width, height, t - self.edge_start, at)
-
- if not renpy.game.less_updates:
- renpy.display.render.redraw(self.edge_cache, self.edge.delay - (t - self.edge_start))
-
-
- iw, ih = im.get_size()
-
- rv = renpy.display.render.Render(iw, ih)
- rv.blit(im, (0, 0))
-
- return rv
-
- def __call__(self, child=None, new_widget=None, old_widget=None):
- """
- Used when this SMAnimation is used as a SMMotion. This creates
- a duplicate of the animation, with all states containing None
- as the image having that None replaced with the image that is provided here.
- """
-
- if child is None:
- child = new_widget
-
- args = [ ]
-
- for state in self.states.values():
- args.append(state.motion_copy(child))
-
- for edges in self.edges.values():
- args.extend(edges)
-
- return SMAnimation(self.initial, delay=self.delay, *args, **self.properties)
-
-
-# class Animation(renpy.display.core.Displayable):
-# """
-# A Displayable that draws an animation, which is a series of images
-# that are displayed with time delays between them.
-# """
-
-# def __init__(self, *args, **properties):
-# """
-# Odd (first, third, fifth, etc.) arguments to Animation are
-# interpreted as image filenames, while even arguments are the
-# time to delay between each image. If the number of arguments
-# is odd, the animation will stop with the last image (well,
-# actually delay for a year before looping). Otherwise, the
-# animation will restart after the final delay time.
-
-# @param anim_timebase: If True, the default, use the animation
-# timebase. Otherwise, use the displayable timebase.
-# """
-
-# properties.setdefault('style', 'animation')
-# self.anim_timebase = properties.pop('anim_timebase', True)
-
-# super(Animation, self).__init__(**properties)
-
-# self.images = [ ]
-# self.delays = [ ]
-
-# for i, arg in enumerate(args):
-
-# if i % 2 == 0:
-# self.images.append(renpy.easy.displayable(arg))
-# else:
-# self.delays.append(arg)
-
-# if len(self.images) > len(self.delays):
-# self.delays.append(365.25 * 86400.0) # One year, give or take.
-
-# def render(self, width, height, st, at):
-
-# if self.anim_timebase:
-# t = at % sum(self.delays)
-# else:
-# t = st % sum(self.delays)
-
-# for image, delay in zip(self.images, self.delays):
-# if t < delay:
-# renpy.display.render.redraw(self, delay - t)
-
-# im = renpy.display.render.render(image, width, height, t, at)
-# width, height = im.get_size()
-# rv = renpy.display.render.Render(width, height)
-# rv.blit(im, (0, 0))
-
-# return rv
-
-# else:
-# t = t - delay
-
-# def visit(self):
-# return self.images
-
-def Animation(*args, **kwargs):
- newargs = [ ]
-
- for i, a in enumerate(args):
- newargs.append(a)
- if i % 2 == 1:
- newargs.append(None)
-
- return TransitionAnimation(*newargs, **kwargs)
-
-
-class TransitionAnimation(renpy.display.core.Displayable):
- """
- A displayable that draws an animation with each frame separated
- by a transition.
- """
-
- def __init__(self, *args, **properties):
- """
- This takes arguments such that the 1st, 4th, 7th, ...
- arguments are displayables, the 2nd, 5th, 8th, ... on arguments
- are times, and the 3rd, 6th, 9th, ... are transitions.
-
- This displays the first displayable for the given time, then
- transitions to the second displayable using the given
- transition, and shows it for the given time (the time of the
- transition is taken out of the time the frame is shown), and
- so on.
-
- The last argument may be a displayable (in which case that
- displayable is used to transition back to the first frame), or
- a displayable (which is shown forever).
-
- There is one keyword argument, apart from the style properties:
-
- @param anim_timebase: If True, the default, use the animation
- timebase. Otherwise, use the displayable timebase.
- """
-
- properties.setdefault('style', 'animation')
- self.anim_timebase = properties.pop('anim_timebase', True)
-
- super(TransitionAnimation, self).__init__(**properties)
-
- images = [ ]
- delays = [ ]
- transitions = [ ]
-
- for i, arg in enumerate(args):
-
- if i % 3 == 0:
- images.append(renpy.easy.displayable(arg))
- elif i % 3 == 1:
- delays.append(arg)
- else:
- transitions.append(arg)
-
- if len(images) > len(delays):
- delays.append(365.25 * 86400.0) # One year, give or take.
- if len(images) > len(transitions):
- transitions.append(None)
-
- self.images = images
- self.prev_images = [ images[-1] ] + images[:-1]
- self.delays = delays
- self.transitions = [ transitions[-1] ] + transitions[:-1]
-
-
- def render(self, width, height, st, at):
-
- if self.anim_timebase:
- orig_t = at
- else:
- orig_t = st
-
- t = orig_t % sum(self.delays)
-
- for image, prev, delay, trans in zip(self.images, self.prev_images, self.delays, self.transitions):
- if t < delay:
- if not renpy.game.less_updates:
- renpy.display.render.redraw(self, delay - t)
-
- if trans and orig_t >= self.delays[0]:
- image = trans(old_widget=prev, new_widget=image)
-
- im = renpy.display.render.render(image, width, height, t, at)
- width, height = im.get_size()
- rv = renpy.display.render.Render(width, height)
- rv.blit(im, (0, 0))
-
- return rv
-
- else:
- t = t - delay
-
- def visit(self):
- return self.images
-
-class Blink(renpy.display.core.Displayable):
- """
- """
-
- def __init__(self, image, on=0.5, off=0.5, rise=0.5, set=0.5, #@ReservedAssignment
- high=1.0, low=0.0, offset=0.0, anim_timebase=False, **properties):
-
- """
- This takes as an argument an image or widget, and blinks that image
- by varying its alpha. The sequence of phases is
- on - set - off - rise - on - ... All times are given in seconds, all
- alphas are fractions between 0 and 1.
-
- @param image: The image or widget that will be blinked.
-
- @param on: The amount of time the widget spends on, at high alpha.
-
- @param off: The amount of time the widget spends off, at low alpha.
-
- @param rise: The amount time the widget takes to ramp from low to high alpha.
-
- @param set: The amount of time the widget takes to ram from high to low.
-
- @param high: The high alpha.
-
- @param low: The low alpha.
-
- @param offset: A time offset, in seconds. Use this to have a
- blink that does not start at the start of the on phase.
-
- @param anim_timebase: If True, use the animation timebase, if false, the displayable timebase.
- """
-
- super(Blink, self).__init__(**properties)
-
- self.image = renpy.easy.displayable(image)
- self.on = on
- self.off = off
- self.rise = rise
- self.set = set
- self.high = high
- self.low = low
- self.offset = offset
- self.anim_timebase = anim_timebase
-
- self.cycle = on + set + off + rise
-
-
- def visit(self):
- return [ self.image ]
-
- def render(self, height, width, st, at):
-
- if self.anim_timebase:
- t = at
- else:
- t = st
-
- time = (self.offset + t) % self.cycle
- alpha = self.high
-
- if 0 <= time < self.on:
- delay = self.on - time
- alpha = self.high
-
- time -= self.on
-
- if 0 <= time < self.set:
- delay = 0
- frac = time / self.set
- alpha = self.low * frac + self.high * (1.0 - frac)
-
- time -= self.set
-
- if 0 <= time < self.off:
- delay = self.off - time
- alpha = self.low
-
- time -= self.off
-
- if 0 <= time < self.rise:
- delay = 0
- frac = time / self.rise
- alpha = self.high * frac + self.low * (1.0 - frac)
-
-
- rend = renpy.display.render.render(self.image, height, width, st, at)
- w, h = rend.get_size()
- rv = renpy.display.render.Render(w, h)
-
- rv.blit(rend, (0, 0))
- rv.alpha = alpha
-
- if not renpy.game.less_updates:
- renpy.display.render.redraw(self, delay)
-
- return rv
-
-
-
-def Filmstrip(image, framesize, gridsize, delay, frames=None, loop=True, **properties):
- """
- This creates an animation from a single image. This image
- must consist of a grid of frames, with the number of columns and
- rows in the grid being taken from gridsize, and the size of each
- frame in the grid being taken from framesize. This takes frames
- and sticks them into an Animation, with the given delay between
- each frame. The frames are taken by going from left-to-right
- across the first row, left-to-right across the second row, and
- so on until all frames are consumed, or a specified number of
- frames are taken.
-
- @param image: The image that the frames must be taken from.
-
- @param framesize: A (width, height) tuple giving the size of
- each of the frames in the animation.
-
- @param gridsize: A (columns, rows) tuple giving the number of
- columns and rows in the grid.
-
- @param delay: The delay, in seconds, between frames.
-
- @param frames: The number of frames in this animation. If None,
- then this defaults to colums * rows frames, that is, taking
- every frame in the grid.
-
- @param loop: If True, loop at the end of the animation. If False,
- this performs the animation once, and then stops.
-
- Other keyword arguments are as for anim.SMAnimation.
- """
-
- width, height = framesize
- cols, rows = gridsize
-
- if frames is None:
- frames = cols * rows
-
- i = 0
-
- # Arguments to Animation
- args = [ ]
-
- for r in range(0, rows):
- for c in range(0, cols):
-
- x = c * width
- y = r * height
-
- args.append(renpy.display.im.Crop(image, x, y, width, height))
- args.append(delay)
-
- i += 1
- if i == frames:
- break
-
- if i == frames:
- break
-
- if not loop:
- args.pop()
-
- return Animation(*args, **properties)