summaryrefslogtreecommitdiff
path: root/unrpyc/renpy/display/particle.py
diff options
context:
space:
mode:
Diffstat (limited to 'unrpyc/renpy/display/particle.py')
-rw-r--r--unrpyc/renpy/display/particle.py615
1 files changed, 0 insertions, 615 deletions
diff --git a/unrpyc/renpy/display/particle.py b/unrpyc/renpy/display/particle.py
deleted file mode 100644
index cf52417..0000000
--- a/unrpyc/renpy/display/particle.py
+++ /dev/null
@@ -1,615 +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 code supports sprite and particle animation.
-
-from renpy.display.render import render, BLIT
-
-import renpy.display
-import random
-
-
-class SpriteCache(renpy.object.Object):
- """
- This stores information about a displayble, including the identity
- of the displayable, and when it was first displayed. It is also
- responsible for caching the displayable surface, so it doesn't
- need to be re-rendered.
- """
-
- # Private Fields:
- #
- # child - The child displayable.
- #
- # st - The shown time when this was first displayed, or None if it hasn't
- # been rendered.
- #
- # render - The render of child.
- #
- # If true, then the render is simple enough it can just be appended to
- # the manager's render's children list.
-
-class Sprite(renpy.object.Object):
- """
- :doc: sprites class
-
- This represents a sprite that is managed by the SpriteManager. It contains
- fields that control the placement of the sprite on the screen. Sprites
- should not be created directly. Instead, they should be created by
- calling :meth:`SpriteManager.create`.
-
- The fields of a sprite object are:
-
- `x`, `y`
- The x and y coordinates of the upper-left corner of the sprite,
- relative to the SpriteManager.
-
- `zorder`
- An integer that's used to control the order of this sprite in the
- relative to the other sprites in the SpriteManager. The larger the
- number is, the closer to the viewer the sprite is.
-
- `events`
- If True, then events are passed to child. If False, the default,
- the children igore events (and hence don't spend time processing
- them).
-
- The methods of a Sprite object are:
- """
-
- # Fields:
- #
- # child - the displayable that is the child of this sprite.
- # cache - the SpriteCache of child.
- # live - True if this sprite is still alive.
- # manager - A reference to the SpriteManager.
-
- def set_child(self, d):
- """
- :doc: sprites method
-
- Changes the Displayable associated with this sprite to `d`.
- """
-
- id_d = id(d)
-
- sc = self.manager.displayable_map.get(id_d, None)
- if sc is None:
- d = renpy.easy.displayable(d)
-
- sc = SpriteCache()
- sc.render = None
- sc.child = d
- sc.st = None
-
- self.manager.displayable_map[id_d] = sc
-
- self.cache = sc
-
- def destroy(self):
- """
- :doc: sprites method
-
- Destroys this sprite, preventing it from being displayed and
- removing it from the SpriteManager.
- """
-
- self.manager.dead_child = True
- self.live = False
- self.events = False
-
-
-
-class SpriteManager(renpy.display.core.Displayable):
- """
- :doc: sprites class
-
- This displayable manages a collection of sprites, and displays
- them at the fastest speed possible.
- """
-
- def __init__(self, update=None, event=None, predict=None, ignore_time=False, **properties):
- """
- `update`
- If not None, a function that is called each time a sprite
- is rendered by this sprite manager. It is called with one
- argument, the time in seconds since this sprite manager
- was first displayed. It is expected to return the number
- of seconds until the function is called again, and the
- SpriteManager is rendered again.
-
- `event`
- If not None, a function that is called when an event occurs.
- It takes as arguments:
- * A pygame event object.
- * The x coordinate of the event.
- * The y coordinate of the event.
- * The time since the sprite manager was first shown.
- If it returns a non-None value, the interaction ends, and
- that value is returned.
-
- `predict`
- If not None, a function that returns a list of
- displayables. These displayables are predicted when the
- sprite manager is.
-
- `ignore_time`
- If True, then time is ignored when rendering displayables. This
- should be used when the sprite manager is used with a relatively
- small pool of images, and those images do not change over time.
- This should only be used with a small number of displayables, as
- it will keep all displayables used in memory for the life of the
- SpriteManager.
-
- After being rendered once (before the `update` function is called),
- SpriteManagers have the following fields:
-
- `width`, `height`
-
- The width and height of this SpriteManager, in pixels.
-
-
- SpriteManagers have the following methods:
- """
-
- super(SpriteManager, self).__init__(self, **properties)
-
- self.update_function = update
- self.event_function = event
- self.predict_function = predict
- self.ignore_time = ignore_time
-
- # A map from a displayable to the SpriteDisplayable object
- # representing that displayable.
- self.displayable_map = { }
-
- # A list of children of this displayable, in zorder. (When sorted.)
- # This is a list of Sprites.
- self.children = [ ]
-
- # True if at least one child has been killed.
- self.dead_child = False
-
- # True if at least one child responds to events.
- self.events = False
-
- # The width and height.
- self.width = None
- self.height = None
-
- def create(self, d):
- """
- :doc: sprites method
-
- Creates a new Sprite for the displayable `d`, and adds it to this
- SpriteManager.
- """
-
- id_d = id(d)
-
- sc = self.displayable_map.get(id_d, None)
- if sc is None:
- d = renpy.easy.displayable(d)
-
- sc = SpriteCache()
- sc.render = None
- sc.child = d
- sc.st = None
- self.displayable_map[id_d] = sc
-
- s = Sprite()
- s.x = 0
- s.y = 0
- s.zorder = 0
- s.cache = sc
- s.live = True
- s.manager = self
- s.events = False
-
- self.children.append(s)
-
- return s
-
- def predict_one(self):
- if self.predict_function is not None:
- for i in self.predict_function():
- renpy.display.predict.displayable(i)
-
-
- def redraw(self, delay=0):
- """
- :doc: sprite method
-
- Causes this SpriteManager to be redrawn in `delay` seconds.
- """
-
- renpy.display.render.redraw(self, delay)
-
- def render(self, width, height, st, at):
-
- self.width = width
- self.height = height
-
- if self.update_function is not None:
-
- redraw = self.update_function(st)
-
- if redraw is not None:
- renpy.display.render.redraw(self, redraw)
-
- if not self.ignore_time:
- self.displayable_map.clear()
-
- if self.dead_child:
- self.children = [ i for i in self.children if i.live ]
-
- self.children.sort(key=lambda sc:sc.zorder)
-
- caches = [ ]
-
- rv = renpy.display.render.Render(width, height)
-
- events = False
-
- for i in self.children:
-
- events |= i.events
-
- cache = i.cache
- r = i.cache.render
- if cache.render is None:
- if cache.st is None:
- cache.st = st
-
- cst = st - cache.st
-
- cache.render = r = render(cache.child, width, height, cst, cst)
- cache.fast = (r.operation == BLIT) and (r.forward is None) and (r.alpha == 1.0)
- rv.depends_on(r)
-
- caches.append(cache)
-
-
- if cache.fast:
- for child, xo, yo, _focus, _main in r.children:
- rv.children.append((child,
- xo + i.x,
- yo + i.y,
- False,
- False))
-
- else:
- rv.subpixel_blit(r, (i.x, i.y))
-
- for i in caches:
- i.render = None
-
- return rv
-
- def event(self, ev, x, y, st):
- for i in range(len(self.children) -1, -1, -1):
- s = self.children[i]
-
- if s.events:
- rv = s.cache.child.event(ev, x - s.x, y - s.y, st - s.cache.st)
- if rv is not None:
- return rv
-
- if self.event_function is not None:
- return self.event_function(ev, x, y, st)
- else:
- return None
-
- def visit(self):
- rv = [ ]
-
- try:
- if self.predict_function:
- pl = self.predict_function()
- for i in pl:
- i = renpy.easy.displayable(i)
- rv.append(i)
- except:
- pass
-
- return rv
-
- def destroy_all(self):
- self.children = [ ]
-
-
-class Particles(renpy.display.core.Displayable, renpy.python.NoRollback):
- """
- Supports particle motion, using the old API.
- """
-
- __version__ = 1
-
- nosave = [ 'particles' ]
-
- def after_upgrade(self, version):
- if version < 1:
- self.sm = SpriteManager(update=self.update_callback, predict=self.predict_callback)
-
- def after_setstate(self):
- self.particles = None
-
- def __init__(self, factory, **properties):
- """
- @param factory: A factory object.
- """
-
- super(Particles, self).__init__(**properties)
-
- self.sm = SpriteManager(update=self.update_callback, predict=self.predict_callback)
-
- self.factory = factory
- self.particles = None
-
- def update_callback(self, st):
-
- particles = self.particles
-
- if st == 0 or particles is None:
- self.sm.destroy_all()
- particles = [ ]
-
- add_parts = self.factory.create(particles, st)
-
- new_particles = [ ]
-
- for sprite, p in particles:
- update = p.update(st)
-
- if update is None:
- sprite.destroy()
- continue
-
- x, y, _t, d = update
-
- if d is not sprite.cache.child:
- sprite.set_child(d)
-
- sprite.x = x
- sprite.y = y
-
- new_particles.append((sprite, p))
-
- if add_parts:
- for p in add_parts:
- update = p.update(st)
-
- if update is None:
- continue
-
- x, y, _t, d = update
-
- if d is None:
- continue
-
- sprite = self.sm.create(d)
- sprite.x = x
- sprite.y = y
-
- new_particles.append((sprite, p))
-
- self.particles = new_particles
-
- return 0
-
- def predict_callback(self):
- return self.factory.predict()
-
- def render(self, w, h, st, at):
- return renpy.display.render.render(self.sm, w, h, st, at)
-
-class SnowBlossomFactory(renpy.python.NoRollback):
-
- rotate = False
-
- def __setstate__(self, state):
- self.start = 0
- vars(self).update(state)
- self.init()
-
- def __init__(self, image, count, xspeed, yspeed, border, start, fast, rotate=False):
- self.image = renpy.easy.displayable(image)
- self.count = count
- self.xspeed = xspeed
- self.yspeed = yspeed
- self.border = border
- self.start = start
- self.fast = fast
- self.rotate = rotate
- self.init()
-
- def init(self):
- self.starts = [ random.uniform(0, self.start) for _i in range(0, self.count) ] # W0201
- self.starts.append(self.start)
- self.starts.sort()
-
- def create(self, particles, st):
-
- def ranged(n):
- if isinstance(n, tuple):
- return random.uniform(n[0], n[1])
- else:
- return n
-
- if not particles and self.fast:
- rv = [ ]
-
- for _i in range(0, self.count):
- rv.append(SnowBlossomParticle(self.image,
- ranged(self.xspeed),
- ranged(self.yspeed),
- self.border,
- st,
- random.uniform(0, 100),
- fast=True,
- rotate=self.rotate))
- return rv
-
-
- if particles is None or len(particles) < self.count:
-
- # Check to see if we have a particle ready to start. If not,
- # don't start it.
- if particles and st < self.starts[len(particles)]:
- return None
-
- return [ SnowBlossomParticle(self.image,
- ranged(self.xspeed),
- ranged(self.yspeed),
- self.border,
- st,
- random.uniform(0, 100),
- fast=False,
- rotate=self.rotate) ]
-
- def predict(self):
- return [ self.image ]
-
-
-class SnowBlossomParticle(renpy.python.NoRollback):
-
- def __init__(self, image, xspeed, yspeed, border, start, offset, fast, rotate):
-
- # safety.
- if yspeed == 0:
- yspeed = 1
-
- self.image = image
- self.xspeed = xspeed
- self.yspeed = yspeed
- self.border = border
- self.start = start
- self.offset = offset
- self.rotate = rotate
-
-
- if not rotate:
- sh = renpy.config.screen_height
- sw = renpy.config.screen_width
- else:
- sw = renpy.config.screen_height
- sh = renpy.config.screen_width
-
-
- if self.yspeed > 0:
- self.ystart = -border
- else:
- self.ystart = sh + border
-
-
- travel_time = (2.0 * border + sh) / abs(yspeed)
-
- xdist = xspeed * travel_time
-
- x0 = min(-xdist, 0)
- x1 = max(sw + xdist, sw)
-
- self.xstart = random.uniform(x0, x1)
-
- if fast:
- self.ystart = random.uniform(-border, sh + border)
- self.xstart = random.uniform(0, sw)
-
- def update(self, st):
- to = st - self.start
-
- xpos = self.xstart + to * self.xspeed
- ypos = self.ystart + to * self.yspeed
-
- if not self.rotate:
- sh = renpy.config.screen_height
- else:
- sh = renpy.config.screen_width
-
- if ypos > sh + self.border:
- return None
-
- if ypos < -self.border:
- return None
-
- if not self.rotate:
- return int(xpos), int(ypos), to + self.offset, self.image
- else:
- return int(ypos), int(xpos), to + self.offset, self.image
-
-def SnowBlossom(d,
- count=10,
- border=50,
- xspeed=(20, 50),
- yspeed=(100, 200),
- start=0,
- fast=False,
- horizontal=False):
-
- """
- :doc: sprites_extra
-
- The snowblossom effect moves multiple instances of a sprite up,
- down, left or right on the screen. When a sprite leaves the screen, it
- is returned to the start.
-
- `d`
- The displayable to use for the sprites.
-
- `border`
- The size of the border of the screen. The sprite is considered to be
- on the screen until it clears the border, ensuring that sprites do
- not disappear abruptly.
-
- `xspeed`, `yspeed`
- The speed at which the sprites move, in the horizontal and vertical
- directions, respectively. These can be a single number or a tuple of
- two numbers. In the latter case, each particle is assigned a random
- speed between the two numbers. The speeds can be positive or negative,
- as long as the second number in a tuple is larger than the first.
-
- `start`
- The delay, in seconds, before each particle is added. This can be
- allows the particles to start at the top of the screen, while not
- looking like a "wave" effect.
-
- `fast`
- If true, particles start in the center of the screen, rather than
- only at the edges.
-
- `horizontal`
- If true, particles appear on the left or right side of the screen,
- rather than the top or bottom.
- """
-
- # If going horizontal, swap the xspeed and the yspeed.
- if horizontal:
- xspeed, yspeed = yspeed, xspeed
-
- return Particles(SnowBlossomFactory(image=d,
- count=count,
- border=border,
- xspeed=xspeed,
- yspeed=yspeed,
- start=start,
- fast=fast,
- rotate=horizontal))
-