File: scene.py

package info (click to toggle)
python-asciimatics 1.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,488 kB
  • sloc: python: 15,713; sh: 8; makefile: 2
file content (129 lines) | stat: -rw-r--r-- 4,389 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""
This module defines Scene objects for animation purposes.  For more details, see
http://asciimatics.readthedocs.io/en/latest/animation.html
"""


class Scene():
    """
    Class to store the details of a single scene to be displayed.  This is
    made up of a set of :py:obj:`.Effect` objects.  See the documentation for
    Effect to understand the interaction between the two classes and
    http://asciimatics.readthedocs.io/en/latest/animation.html for how to use them together.
    """

    def __init__(self, effects, duration=0, clear=True, name=None):
        """
        :param effects: The list of effects to apply to this scene.
        :param duration: The number of frames in this Scene.  A value of 0 means that the Scene
            should query the Effects to find the duration.  A value of -1 means don't stop.
        :param clear: Whether to clear the Screen at the start of the Scene.
        :param name: Optional name to identify the scene.
        """
        self._effects = []
        for effect in effects:
            self.add_effect(effect, reset=False)
        self._duration = duration
        if duration == 0:
            self._duration = max(x.stop_frame for x in effects)
        self._clear = clear
        self._name = name

    def reset(self, old_scene=None, screen=None):
        """
        Reset the scene ready for playing.

        :param old_scene: The previous version of this Scene that was running before the
            application reset - e.g. due to a screen resize.
        :param screen: New screen to use if old_scene is not None.
        """
        # Always reset all the effects.
        for effect in self._effects:
            effect.reset()

        # If we have an old Scene to recreate, get the data out of that and
        # apply it where possible by cloning objects where appropriate.
        if old_scene:
            for old_effect in old_scene.effects:
                # catching AttributeErrors here has hidden bugs, so explicitly
                # check for the cloning interface before calling it.
                if hasattr(old_effect, "clone"):
                    old_effect.clone(screen, self)

    def exit(self):
        """
        Handle any tidy up required on the exit of the Scene.
        """
        # Save off any persistent state for each effect.
        for effect in self._effects:
            if hasattr(effect, "save"):
                effect.save()

    def add_effect(self, effect, reset=True):
        """
        Add an effect to the Scene.

        This method can be called at any time - even when playing the Scene.  The default logic
        assumes that the Effect needs to be reset before being displayed.  This can be overridden
        using the `reset` parameter.

        :param effect: The Effect to be added.
        :param reset: Whether to reset the Effect that has just been added.
        """
        # Reset the effect in case this is in the middle of a Scene.
        if reset:
            effect.reset()
        effect.register_scene(self)
        self._effects.append(effect)

    def remove_effect(self, effect):
        """
        Remove an effect from the scene.

        :param effect: The effect to remove.
        """
        self._effects.remove(effect)

    def process_event(self, event):
        """
        Process a new input event.

        This method will pass the event on to any Effects in reverse Z order so that the
        top-most Effect has priority.

        :param event: The Event that has been triggered.
        :returns: None if the Scene processed the event, else the original event.
        """
        for effect in reversed(self._effects):
            event = effect.process_event(event)
            if event is None:
                break
        return event

    @property
    def name(self):
        """
        :return: The name of this Scene.  May be None.
        """
        return self._name

    @property
    def effects(self):
        """
        :return: The list of Effects in this Scene.
        """
        return self._effects

    @property
    def duration(self):
        """
        :return: The length of the scene in frames.
        """
        return self._duration

    @property
    def clear(self):
        """
        :return: Whether the Scene should clear at the start.
        """
        return self._clear