Skip to content

Commit e2df340

Browse files
committed
Smooth starting animation
1 parent 7a268eb commit e2df340

3 files changed

Lines changed: 97 additions & 4 deletions

File tree

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1-
# termslides
2-
Terminal slideshow
1+
# TermSlides
2+
Script your slides in a YAML file and show it in terminal.
3+
4+
## Install
5+
`pip install termslides`
6+
7+
## Example
8+
9+
![sample.yaml](docs/termslides_sample.gif)
10+

docs/termslides_sample.gif

4.66 MB
Loading

termslides/termslides.py

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# -*- coding: utf-8 -*-
22

33
import sys
4+
from types import MethodType
45

56
import yaml
6-
from asciimatics.exceptions import ResizeScreenError
7+
from asciimatics.exceptions import NextScene, ResizeScreenError
78
from asciimatics.effects import Stars, Snow
89
from asciimatics.scene import Scene
910
from asciimatics.screen import Screen
@@ -17,6 +18,89 @@
1718
__all__ = ['termslides']
1819

1920

21+
def patch_draw_next_frame(self, repeat=True):
22+
"""
23+
Draw the next frame in the currently configured Scenes. You must call
24+
:py:meth:`.set_scenes` before using this for the first time.
25+
26+
:param repeat: Whether to repeat the Scenes once it has reached the end.
27+
Defaults to True.
28+
29+
:raises StopApplication: if the application should be terminated.
30+
"""
31+
scene = self._scenes[self._scene_index]
32+
try:
33+
# Check for an event now and remember for refresh reasons.
34+
event = self.get_event()
35+
got_event = event is not None
36+
37+
# Now process all the input events
38+
while event is not None:
39+
event = scene.process_event(event)
40+
if event is not None and self._unhandled_input is not None:
41+
self._unhandled_input(event)
42+
event = self.get_event()
43+
44+
# Only bother with a refresh if there was an event to process or
45+
# we have to refresh due to the refresh limit required for an
46+
# Effect.
47+
self._frame += 1
48+
self._idle_frame_count -= 1
49+
if got_event or self._idle_frame_count <= 0 or self._forced_update:
50+
self._forced_update = False
51+
self._idle_frame_count = 1000000
52+
for effect in scene.effects:
53+
# Update the effect and delete if needed.
54+
effect.update(self._frame)
55+
if effect.delete_count is not None:
56+
effect.delete_count -= 1
57+
if effect.delete_count <= 0:
58+
scene.remove_effect(effect)
59+
60+
# Sort out when we next _need_ to do a refresh.
61+
if effect.frame_update_count > 0:
62+
self._idle_frame_count = min(self._idle_frame_count,
63+
effect.frame_update_count)
64+
self.refresh()
65+
66+
if 0 < scene.duration <= self._frame:
67+
raise NextScene()
68+
except NextScene as e:
69+
# Tidy up the current scene.
70+
scene.exit()
71+
72+
# Find the specified next Scene
73+
if e.name is None:
74+
# Just allow next iteration of loop
75+
self._scene_index += 1
76+
if self._scene_index >= len(self._scenes):
77+
if repeat:
78+
self._scene_index = 0
79+
else:
80+
raise StopApplication("Repeat disabled")
81+
else:
82+
# Find the required scene.
83+
for i, scene in enumerate(self._scenes):
84+
if scene.name == e.name:
85+
self._scene_index = i
86+
break
87+
else:
88+
raise RuntimeError(
89+
"Could not find Scene: '{}'".format(e.name))
90+
91+
# Reset the screen if needed.
92+
scene = self._scenes[self._scene_index]
93+
scene.reset()
94+
self._frame = 0
95+
self._idle_frame_count = 0
96+
if scene.clear:
97+
self.clear()
98+
else:
99+
self._start_line = 0
100+
self._x = self._y = None
101+
self._reset()
102+
103+
20104
@group()
21105
def cli():
22106
pass
@@ -31,6 +115,7 @@ def termslides(file):
31115
def slides_show(screen, scene):
32116
scenes = []
33117
screen.set_title(slides.pop('title', 'TermSlides'))
118+
screen.draw_next_frame = MethodType(patch_draw_next_frame, screen)
34119

35120
# list view
36121
slide_view = SlideView(screen, slides)
@@ -67,7 +152,7 @@ def slides_show(screen, scene):
67152
# input handler
68153
effects.insert(0, InputHandler(screen, list_view))
69154
# add to scenes
70-
scenes.append(Scene(effects, duration, name=name))
155+
scenes.append(Scene(effects, duration, name=name, clear=(start is None)))
71156

72157
screen.play(scenes, stop_on_resize=True, start_scene=scene)
73158

0 commit comments

Comments
 (0)