Skip to content

Commit

Permalink
feat(lib): add support for presenter notes (#322)
Browse files Browse the repository at this point in the history
* feat(lib): add support for presenter notes

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(test): typo

* Update test_slide.py

* Update convert.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
jeertmans and pre-commit-ci[bot] authored Nov 23, 2023
1 parent b09a000 commit f898dd3
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added the `playback-rate` and `reversed-playback-rate` options
to slide config.
[#320](https://github.com/jeertmans/manim-slides/pull/320)
- Added the speaker notes option.
[#322](https://github.com/jeertmans/manim-slides/pull/322)

(v5.1-modified)=
### Modified
Expand Down
1 change: 1 addition & 0 deletions manim_slides/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class BaseSlideConfig(BaseModel): # type: ignore
auto_next: bool = False
playback_rate: float = 1.0
reversed_playback_rate: float = 1.0
notes: str = ""

@classmethod
def wrapper(cls, arg_name: str) -> Callable[..., Any]:
Expand Down
7 changes: 7 additions & 0 deletions manim_slides/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,16 @@ def convert_to(self, dest: Path) -> None:
options = self.dict()
options["assets_dir"] = assets_dir

has_notes = any(
slide_config.notes != ""
for presentation_config in self.presentation_configs
for slide_config in presentation_config.slides
)

content = revealjs_template.render(
file_to_data_uri=file_to_data_uri,
get_duration_ms=get_duration_ms,
has_notes=has_notes,
**options,
)

Expand Down
27 changes: 18 additions & 9 deletions manim_slides/present/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from PySide6.QtGui import QCloseEvent, QIcon, QKeyEvent, QScreen
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import QDialog, QGridLayout, QLabel, QMainWindow
from PySide6.QtWidgets import QDialog, QGridLayout, QLabel, QMainWindow, QVBoxLayout

from ..config import Config, PresentationConfig, SlideConfig
from ..logger import logger
Expand All @@ -18,17 +18,25 @@ class Info(QDialog): # type: ignore[misc]
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)

layout = QGridLayout()
main_layout = QVBoxLayout()
labels_layout = QGridLayout()
notes_layout = QVBoxLayout()
self.scene_label = QLabel()
self.slide_label = QLabel()
self.slide_notes = QLabel("")
self.slide_notes.setWordWrap(True)

layout.addWidget(QLabel("Scene:"), 1, 1)
layout.addWidget(QLabel("Slide:"), 2, 1)
layout.addWidget(self.scene_label, 1, 2)
layout.addWidget(self.slide_label, 2, 2)
self.setLayout(layout)
self.setFixedWidth(150)
self.setFixedHeight(80)
labels_layout.addWidget(QLabel("Scene:"), 1, 1)
labels_layout.addWidget(QLabel("Slide:"), 2, 1)
labels_layout.addWidget(self.scene_label, 1, 2)
labels_layout.addWidget(self.slide_label, 2, 2)

notes_layout.addWidget(self.slide_notes)

main_layout.addLayout(labels_layout)
main_layout.addLayout(notes_layout)

self.setLayout(main_layout)

if parent := self.parent():
self.closeEvent = parent.closeEvent
Expand Down Expand Up @@ -312,6 +320,7 @@ def slide_changed_callback(self) -> None:
index = self.current_slide_index
count = self.current_slides_count
self.info.slide_label.setText(f"{index+1:4d}/{count:4<d}")
self.info.slide_notes.setText(self.current_slide_config.notes)

def show(self) -> None:
super().show()
Expand Down
28 changes: 28 additions & 0 deletions manim_slides/slide/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ def next_slide(
Playback rate at which the reversed video is played.
Note that this is only supported by ``manim-slides present``.
:param notes:
Presenter notes, in HTML format.
Note that this is only supported by ``manim-slides present``
and ``manim-slides convert --to=html``.
:param kwargs:
Keyword arguments to be passed to
:meth:`Scene.next_section<manim.scene.scene.Scene.next_section>`,
Expand Down Expand Up @@ -372,6 +377,29 @@ def construct(self):
self.next_slide()
self.wipe(square)
The following contains speaker notes. On the webbrowser,
the speaker view can be triggered by pressing :kbd:`S`.
.. manim-slides:: SpeakerNotesExample
from manim import *
from manim_slides import Slide
class SpeakerNotesExample(Slide):
def construct(self):
self.next_slide(notes="Some introduction")
square = Square(color=GREEN, side_length=2)
self.play(GrowFromCenter(square))
self.next_slide(notes="We now rotate the slide")
self.play(Rotate(square, PI / 2))
self.next_slide(notes="Bye bye")
self.zoom(square)
"""
if self._current_animation > self._start_animation:
if self.wait_time_between_slides > 0.0:
Expand Down
10 changes: 10 additions & 0 deletions manim_slides/templates/revealjs.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
{% if slide_config.auto_next -%}
data-autoslide="{{ get_duration_ms(slide_config.file) }}"
{%- endif -%}>
{% if slide_config.notes != "" -%}
<aside class="notes">{{ slide_config.notes }}</aside>
{%- endif %}
</section>
{%- endfor -%}
{%- endfor -%}
Expand All @@ -50,9 +53,16 @@

<!-- To include plugins, see: https://revealjs.com/plugins/ -->

{% if has_notes -%}
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{{ reveal_version }}/plugin/notes/notes.min.js"></script>
{%- endif -%}

<!-- <script src="index.js"></script> -->
<script>
Reveal.initialize({
{% if has_notes -%}
plugins: [ RevealNotes ],
{%- endif %}
// The "normal" size of the presentation, aspect ratio will
// be preserved when the presentation is scaled to fit different
// resolutions. Can be specified using percentage units.
Expand Down
28 changes: 28 additions & 0 deletions tests/test_slide.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,34 @@ def construct(self) -> None:

assert self._base_slide_config.playback_rate == 2.0

@assert_constructs
class TestReversedPlaybackRate(Slide):
def construct(self) -> None:
text = Text("Some text")

self.add(text)

assert self._base_slide_config.reversed_playback_rate == 1.0

self.next_slide(reversed_playback_rate=2.0)
self.play(text.animate.scale(2))

assert self._base_slide_config.reversed_playback_rate == 2.0

@assert_constructs
class TestNotes(Slide):
def construct(self) -> None:
text = Text("Some text")

self.add(text)

assert self._base_slide_config.notes == ""

self.next_slide(notes="test")
self.play(text.animate.scale(2))

assert self._base_slide_config.notes == "test"

@assert_constructs
class TestWipe(Slide):
def construct(self) -> None:
Expand Down

0 comments on commit f898dd3

Please sign in to comment.