Compare commits

...

18 Commits

Author SHA1 Message Date
cd7a054cf1 chore(version): bump to 4.8.1 (#102) 2023-01-01 19:27:53 +01:00
1ff2330ff2 fix(convert): correctly quote paths when using ffmpeg on Windows
With the current version of ffmpeg on Windows, the list file must enclosed by single quotes.
2023-01-01 19:12:45 +01:00
1e150bbb84 [pre-commit.ci] pre-commit autoupdate (#100)
updates:
- [github.com/pycqa/isort: v5.11.3 → 5.11.4](https://github.com/pycqa/isort/compare/v5.11.3...5.11.4)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-27 08:47:36 +01:00
13f19649aa [pre-commit.ci] pre-commit autoupdate (#99)
updates:
- [github.com/pycqa/isort: 5.11.0 → v5.11.3](https://github.com/pycqa/isort/compare/5.11.0...v5.11.3)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-20 11:09:07 +01:00
4c97bdd3a3 [pre-commit.ci] pre-commit autoupdate (#97)
updates:
- [github.com/pycqa/isort: 5.10.1 → 5.11.0](https://github.com/pycqa/isort/compare/5.10.1...5.11.0)
- [github.com/psf/black: 22.10.0 → 22.12.0](https://github.com/psf/black/compare/22.10.0...22.12.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-14 08:51:54 +01:00
777ff444a3 chore(cli): clean debug print 2022-12-09 09:48:36 +01:00
9cb1c35f00 chore(ci): move mypy config to pyproject.toml (#94) 2022-12-08 11:53:56 +01:00
1fed193cb3 chore(ci): move black config to pyproject.toml (#93)
* chore(ci): move black config to pyproject.toml

* chore(deps): update target version
2022-12-08 11:34:20 +01:00
9f227936f7 chore(lib): add link for audio blocking 2022-12-08 11:19:47 +01:00
2fe6139d18 chore(ci): move isort config to pyproject.toml (#92)
* chore(ci): move isort config to pyproject.toml

* fix(ci): typo in config
2022-12-08 11:16:54 +01:00
54f2c60c4e chore(deps): use carret version requirements (#91) 2022-12-08 10:25:16 +01:00
9810425ff2 chore(version): update version 2022-12-07 17:19:19 +01:00
3dc543e3a6 chore(docs): update README and fix typo 2022-12-07 17:17:07 +01:00
c0c73ad4d4 feat(cli): feally featured RevealJS template (#80)
* feat(cli): feally featured RevealJS template

This adds an option for every possible RevealJS option. Error messages are also improved.

RevealJS version is bumped to latest (4.4.0).

* feat(cli): add primitive support for arbitrary JS functions

* fix(cli): some typos / issues in template

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

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

* fix(lib): pickling issue

* fix(lib): ignore typing error due to __reduce_ex__

* feat(cli): add template selection, fixes first slide bug, and rm stuff

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-07 16:27:23 +01:00
a82ca81dc5 chore(deps): add dependency groups (#89)
This uses poetry's dependency groups to be more rigorous about modules version.
2022-12-06 14:56:18 +01:00
a68a4e1517 feat(cli): speedup scaling with painter scaling (#88)
As suggested by PySide6's documentation, we avoid using pixmap.scaled() on every frame, but use scaled content to resize the image. This seems to ignore ratio, explaining why we need a new option flag.
2022-12-06 12:06:35 +01:00
519dd47ac6 chore(version): update version 2022-12-05 22:15:03 +01:00
0565a99639 chore(version): fixing all CI tests (#76)
* fix(ci): add Ubuntu dep and change pip install

* fix(ci): typo

* fix(ci): add missing deps for Ubuntu

* fix(ci): typo in pkg name

* fix(ci): trying to install manimpango

* fix(ci): append bin to path on MacOS

* fix(ci): install Python setup tool

* try(ci): trying some stuff

* fix(ci): remove useless pkgs

* fix(ci): check manimpango and remove pyopengl

* try(ci): try fix

* try(ci): cleaner workflow

* fix(ci): missing dollar

* try(ci): minimal platform

* try(ci): test

* fix(ci): reset offscreen option

* fix(ci): add opengl dep

* fix(ci): xvfb for pyglet

* fix(ci): correctly set env var

* try(ci): set DISPLAY env var at the beginning

* test(ci): switch minimal to offscreen

* test(ci): remove QT debug env var

* try(ci): fixing manimgl issue

* Revert "try(ci): fixing manimgl issue"

This reverts commit f76c05897013bd804810c7153953bde4c8715af7.

* try(ci): manimgl to manim-render

* try(ci): verbose

* fix(ci): update linux deps

* fix(ci): typo

* fix(ci): typo in deps

* fix(ci): typo

* fix(ci): test other deps

* test(ci): install manimpango

* try(ci): test

* test(ci): print help

* test(ci): reset verbose mode

* fix(ci): typo

* chore(setup): use poetry

* chore(setup): cache installs

* fix(ci): swap order

* fix(ci): poetry install

* chore(setup): add manim/manimgl to dev-deps

* try(ci): some test

* try(ci): import two maybe conflicting packages

* fix(ci): typo in cmd

* fix(ci): only check if manimgl

* fix(ci): remove useless check
2022-12-05 22:13:44 +01:00
13 changed files with 3256 additions and 318 deletions

View File

@ -30,10 +30,13 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Poetry
run: pipx install poetry
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.9'
cache: 'poetry'
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Install Linux Dependencies
@ -41,11 +44,11 @@ jobs:
- name: Install Python dependencies
run: pip install manim sphinx sphinx_click furo
- name: Install local Python package
run: pip install -e .
run: poetry install --with docs
- name: Build animation and convert it into HTML slides
run: |
manim example.py ConvertExample
manim-slides convert ConvertExample docs/source/_static/slides.html -cembedded=true -ccontrols=true
poetry run manim example.py ConvertExample
poetry run manim-slides convert ConvertExample docs/source/_static/slides.html -ccontrols=true
- name: Build docs
run: cd docs && make html
- name: Upload artifact

View File

@ -2,6 +2,7 @@ on:
pull_request:
paths:
- '**.py'
- '.github/workflows/test_examples.yml'
workflow_dispatch:
name: Test Examples
@ -9,6 +10,8 @@ name: Test Examples
env:
QT_QPA_PLATFORM: offscreen
MANIM_SLIDES_VERBOSITY: debug
PYTHONFAULTHANDLER: 1
DISPLAY: ":99"
jobs:
build-examples:
@ -24,9 +27,6 @@ jobs:
# Your graphics drivers do not support OpenGL 2.0.
- os: windows-latest
manim: manimgl
# manimgl seems to have problems with Python 3.11
- manim: manimgl
pyversion: '3.11'
# We only test Python 3.11 on Windows and MacOS
- os: windows-latest
pyversion: '3.8'
@ -46,64 +46,72 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Poetry
run: pipx install poetry
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.pyversion }}
- name: Append to Path on MacOS and Ubuntu
if: matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest'
cache: 'poetry'
# Path related stuff
- name: Append to Path on MacOS
if: matrix.os == 'macos-latest'
run: |
echo "${HOME}/.local/bin" >> $GITHUB_PATH
echo "/Users/runner/Library/Python/${{ matrix.pyversion }}/bin" >> $GITHUB_PATH
- name: Append to Path on Ubuntu
if: matrix.os == 'ubuntu-latest'
run: echo "${HOME}/.local/bin" >> $GITHUB_PATH
- name: Append to Path on Windows
if: matrix.os == 'windows-latest'
run: echo "${HOME}/.local/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install MacOS dependencies (manim only)
# OS depedencies
- name: Install manim dependencies on MacOs
if: matrix.os == 'macos-latest' && matrix.manim == 'manim'
run: brew install py3cairo
- name: Install MacOS dependencies
if: matrix.os == 'macos-latest'
run: brew install ffmpeg py3cairo
- name: Install manimgl dependencies on MacOS
if: matrix.os == 'macos-latest' && matrix.manim == 'manimgl'
run: brew install ffmpeg
- name: Install Ubuntu dependencies
if: matrix.os == 'ubuntu-latest'
run: sudo apt install libcairo2-dev libpango1.0-dev ffmpeg freeglut3-dev xvfb
- name: Install manim dependencies on Ubuntu
if: matrix.os == 'ubuntu-latest' && matrix.manim == 'manim'
run: |
sudo apt-get install libcairo2-dev libpango1.0-dev ffmpeg freeglut3-dev
- name: Install manimgl dependencies on Ubuntu
if: matrix.os == 'ubuntu-latest' && matrix.manim == 'manimgl'
run: |
sudo apt-get install libpango1.0-dev ffmpeg freeglut3-dev
- name: Install xvfb on Ubuntu
if: matrix.os == 'ubuntu-latest' && matrix.manim == 'manimgl'
run: |
sudo apt-get install xvfb
nohup Xvfb $DISPLAY &
- name: Install Windows dependencies
if: matrix.os == 'windows-latest'
run: choco install ffmpeg
- name: Install manim on MacOs
if: matrix.manim == 'manim' && matrix.os == 'macos-latest'
run: pip3 install --user manim
- name: Install manim on Ubuntu and Windows
if: matrix.manim == 'manim' && (matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest')
run: python -m pip install --user manim
- name: Install manimgl on MacOs
if: matrix.manim == 'manimgl' && matrix.os == 'macos-latest'
run: pip3 install --user manimgl
- name: Install manimgl on Ubuntu and Windows
if: matrix.manim == 'manimgl' && matrix.os != 'macos-latest'
run: python -m pip install --user manimgl
- name: Install manim-slides on MacOS
if: matrix.os == 'macos-latest'
run: pip3 install --user .
- name: Install manim-slides on Ubuntu
if: matrix.os == 'ubuntu-latest'
run: xvfb-run -a -s "-screen 0 1400x900x24" python -m pip install --user .
- name: Install manim-slides on Windows
if: matrix.os == 'windows-latest'
run: pip3 install -e .
- name: Build slides with manim
# Install Manim Slides
- name: Install Manim Slides
run: |
poetry config experimental.new-installer false
poetry install --with test
# Render slides
- name: Render slides
if: matrix.manim == 'manim'
run: python -m manim -ql example.py Example ThreeDExample ConvertExample
- name: Build slides with manimgl on Ubuntu
if: matrix.manim == 'manimgl' && matrix.os == 'ubuntu-latest'
run: xvfb-run -a -s "-screen 0 1400x900x24" manim-render -l example.py Example ThreeDExample
- name: Build slides with manimgl on MacOS or Windows
if: matrix.manim == 'manimgl' && (matrix.os == 'macos-latest' || matrix.os == 'windows-latest')
run: manimgl -l example.py Example ThreeDExample
- name: Test slides on Ubuntu
if: matrix.os == 'ubuntu-latest'
run: xvfb-run -a -s "-screen 0 1400x900x24" manim-slides Example ThreeDExample --skip-all
- name: Test slides on MacOS or Windows
if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
run: manim-slides Example ThreeDExample --skip-all
run: poetry run manim -ql example.py Example ThreeDExample
- name: Render slides
if: matrix.manim == 'manimgl'
run: poetry run -v manimgl -l example.py Example ThreeDExample
# Play slides
- name: Test slides
run: poetry run manim-slides Example ThreeDExample --skip-all
# Test slides to html
- name: Test convert on Ubuntu
if: matrix.os == 'ubuntu-latest' && matrix.manim == 'manim'
run: manim-slides convert --to=html ConvertExample index.html
run: |
poetry run manim -ql example.py ConvertExample
poetry run manim-slides convert --to=html ConvertExample index.html

4
.gitignore vendored
View File

@ -23,3 +23,7 @@ docs/build/
docs/source/_static/slides_assets/
docs/source/_static/slides.html
slides_assets/
slides.html

View File

@ -6,16 +6,14 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.11.4
hooks:
- id: isort
name: isort (python)
args: ["--python-version", "37", "--profile", "black"]
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 22.12.0
hooks:
- id: black
args: ["--target-version", "py37"]
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
@ -30,30 +28,3 @@ repos:
hooks:
- id: mypy
additional_dependencies: [types-requests, types-setuptools]
args:
- --install-types
- --non-interactive
- --ignore-missing-imports
# Disallow dynamic typing
- --disallow-any-generics
- --disallow-subclassing-any
# Disallow untyped definitions and calls
- --disallow-untyped-defs
- --disallow-incomplete-defs
- --check-untyped-defs
# None and optional handling
- --no-implicit-optional
# Configuring warnings
- --warn-unused-ignores
- --warn-no-return
- --no-warn-return-any
- --warn-redundant-casts
# Strict equality
- --strict-equality
# Config file
- --warn-unused-configs

View File

@ -16,8 +16,9 @@ Tool for live presentations using either [Manim (community edition)](https://www
- [Usage](#usage)
* [Basic Example](#basic-example)
* [Key Bindings](#key-bindings)
* [Interactive Tutorial](#interactive-tutorial)
* [Other Examples](#other-examples)
- [Features and Comparison with Original manim-presentation](#features-and-comparison-with-original-manim-presentation)
- [Comparison with Similar Tools](#comparison-with-similar-tools)
- [F.A.Q](#faq)
* [How to increase quality on Windows](#how-to-increase-quality-on-windows)
- [Contributing](#contributing)
@ -134,6 +135,12 @@ manim-slides init
> **_NOTE:_** `manim-slides` uses key codes, which are platform dependent. Using the configuration wizard is therefore highly recommended.
## Interactive Tutorial
Click on the image to watch a slides presentation that explains you how to use Manim Slides.
[![Manim Slides Docs](https://raw.githubusercontent.com/jeertmans/manim-slides/main/static/docs.png)](https://eertmans.be/manim-slides/)
## Other Examples
Other examples are available in the [`example.py`](https://github.com/jeertmans/manim-slides/blob/main/example.py) file, if you downloaded the git repository.
@ -143,27 +150,21 @@ Below is a small recording of me playing with the slides back and forth.
![](https://raw.githubusercontent.com/jeertmans/manim-slides/main/static/example.gif)
## Features and Comparison with original manim-presentation
## Comparison with Similar Tools
Below is a non-exhaustive list of features:
There exists are variety of tools that allows to create slides presentations containing Manim animations.
| Feature | `manim-slides` | `manim-presentation` |
|:--------|:--------------:|:--------------------:|
| Support for Manim | :heavy_check_mark: | :heavy_check_mark: |
| Support for ManimGL | :heavy_check_mark: | :heavy_multiplication_x: |
| Configurable key bindings | :heavy_check_mark: | :heavy_check_mark: |
| Configurable paths | :heavy_check_mark: | :heavy_multiplication_x: |
| Play / Pause slides | :heavy_check_mark: | :heavy_check_mark: |
| Next / Previous slide | :heavy_check_mark: | :heavy_check_mark: |
| Replay slide | :heavy_check_mark: | :heavy_check_mark: |
| Reverse slide | :heavy_check_mark: | :heavy_multiplication_x: |
| Multiple key per actions | :heavy_check_mark: | :heavy_multiplication_x: |
| One command line tool | :heavy_check_mark: | :heavy_multiplication_x: |
| Robust config file parsing | :heavy_check_mark: | :heavy_multiplication_x: |
| Support for 3D Scenes | :heavy_check_mark: | :heavy_multiplication_x: |
| Documented code | :heavy_check_mark: | :heavy_multiplication_x: |
| Tested on Unix, macOS, and Windows | :heavy_check_mark: | :heavy_multiplication_x: |
| Hide mouse cursor | :heavy_check_mark: | :heavy_multiplication_x: |
Below is a comparison of the most used ones with Manim Slides:
| Project name | Manim Slides | Manim Presentation | Manim Editor | Jupyter Notebooks |
|:------------:|:------------:|:------------------:|:------------:|:-----------------:|
| Link | [![GitHub Repo stars](https://img.shields.io/github/stars/jeertmans/manim-slides?style=social)](https://github.com/jeertmans/manim-slides) | [![GitHub Repo stars](https://img.shields.io/github/stars/galatolofederico/manim-presentation?style=social)](https://github.com/galatolofederico/manim-presentation) | [![GitHub Repo stars](https://img.shields.io/github/stars/ManimCommunity/manim_editor?style=social)](https://github.com/ManimCommunity/manim_editor) | [![GitHub Repo stars](https://img.shields.io/github/stars/jupyter/notebook?style=social)](https://github.com/jupyter/notebook) |
| Activity | [![GitHub Repo stars](https://img.shields.io/github/last-commit/jeertmans/manim-slides?style=social)](https://github.com/jeertmans/manim-slides) | [![GitHub Repo stars](https://img.shields.io/github/last-commit/galatolofederico/manim-presentation?style=social)](https://github.com/galatolofederico/manim-presentation) | [![GitHub Repo stars](https://img.shields.io/github/last-commit/ManimCommunity/manim_editor?style=social)](https://github.com/ManimCommunity/manim_editor) | [![GitHub Repo stars](https://img.shields.io/github/last-commit/jupyter/notebook?style=social)](https://github.com/jupyter/notebook) |
| Usage | Command-line | Command-line | Web Browser | Notebook |
| Note | Requires minimal modif. in scenes files | Requires minimal modif. in scenes files | Requires the usage of sections, and configuration through graphical interface | Relies on `nbconvert` to create slides from a Notebook |
| Support for ManimGL | Yes | No | No | No |
| Web Browser presentations | Yes | No | Yes | No |
| Offline presentations | Yes, with Qt | Yes, with OpenCV | No | No
## F.A.Q

View File

@ -1 +1 @@
__version__ = "4.7.0"
__version__ = "4.8.1"

View File

@ -206,7 +206,7 @@ class PresentationConfig(BaseModel): # type: ignore
dest_path = merge_basenames(files)
f = tempfile.NamedTemporaryFile(mode="w", delete=False)
f.writelines(f"file {os.path.abspath(path)}\n" for path in files)
f.writelines(f"file '{os.path.abspath(path)}'\n" for path in files)
f.close()
command = [

View File

@ -1,12 +1,12 @@
import os
import webbrowser
from enum import Enum
from typing import Any, Callable, Dict, Generator, List, Type
from typing import Any, Callable, Dict, Generator, List, Optional, Type, Union
import click
import pkg_resources
from click import Context, Parameter
from pydantic import BaseModel
from pydantic import BaseModel, PositiveInt, ValidationError
from .commons import folder_path_option, verbosity_option
from .config import PresentationConfig
@ -34,14 +34,21 @@ def validate_config_option(
class Converter(BaseModel): # type: ignore
presentation_configs: List[PresentationConfig] = []
assets_dir: str = "{basename}_assets"
template: Optional[str] = None
def convert_to(self, dest: str) -> None:
"""Converts self, i.e., a list of presentations, into a given format."""
raise NotImplementedError
def load_template(self) -> str:
"""Returns the template as a string.
An empty string is returned if no template is used."""
return ""
def open(self, file: str) -> bool:
"""Opens a file, generated with converter, using appropriate application."""
return webbrowser.open(file)
raise NotImplementedError
@classmethod
def from_string(cls, s: str) -> Type["Converter"]:
@ -51,11 +58,126 @@ class Converter(BaseModel): # type: ignore
}[s]
class JSBool(str, Enum):
class Str(str):
"""A simple string, but quoted when needed."""
# This fixes pickling issue on Python 3.8
__reduce_ex__ = str.__reduce_ex__
def __str__(self) -> str:
"""Ensures that the string is correctly quoted."""
if self in ["true", "false", "null"]:
return super().__str__()
else:
return f"'{super().__str__()}'"
Function = str # Basically, anything
class JsTrue(str, Enum):
true = "true"
class JsFalse(str, Enum):
false = "false"
class JsBool(Str, Enum): # type: ignore
true = "true"
false = "false"
class JsNull(Str, Enum): # type: ignore
null = "null"
class ControlsLayout(Str, Enum): # type: ignore
edges = "edges"
bottom_right = "bottom-right"
class ControlsBackArrows(Str, Enum): # type: ignore
faded = "faded"
hidden = "hidden"
visibly = "visibly"
class SlideNumber(Str, Enum): # type: ignore
true = "true"
false = "false"
hdotv = "h.v"
handv = "h/v"
c = "c"
candt = "c/t"
class ShowSlideNumber(Str, Enum): # type: ignore
all = "all"
print = "print"
speaker = "speaker"
class KeyboardCondition(Str, Enum): # type: ignore
null = "null"
focused = "focused"
class NavigationMode(Str, Enum): # type: ignore
default = "default"
linear = "linear"
grid = "grid"
class AutoPlayMedia(Str, Enum): # type: ignore
null = "null"
true = "true"
false = "false"
PreloadIframes = AutoPlayMedia
class AutoAnimateMatcher(Str, Enum): # type: ignore
null = "null"
class AutoAnimateEasing(Str, Enum): # type: ignore
ease = "ease"
AutoSlide = Union[PositiveInt, JsFalse]
class AutoSlideMethod(Str, Enum): # type: ignore
null = "null"
MouseWheel = Union[JsNull, float]
class Transition(Str, Enum): # type: ignore
none = "none"
fade = "fade"
slide = "slide"
convex = "convex"
concave = "concave"
zoom = "zoom"
class TransitionSpeed(Str, Enum): # type: ignore
default = "default"
fast = "fast"
slow = "slow"
BackgroundTransition = Transition
class Display(Str, Enum): # type: ignore
block = "block"
class RevealTheme(str, Enum):
black = "black"
white = "white"
@ -71,21 +193,90 @@ class RevealTheme(str, Enum):
class RevealJS(Converter):
background_color: str = "black"
controls: JSBool = JSBool.false
embedded: JSBool = JSBool.false
fragments: JSBool = JSBool.false
height: str = "100%"
loop: JSBool = JSBool.false
progress: JSBool = JSBool.false
reveal_version: str = "3.7.0"
# Presentation size options from RevealJS
width: Union[Str, int] = Str("100%")
height: Union[Str, int] = Str("100%")
margin: float = 0.04
min_scale: float = 0.2
max_scale: float = 2.0
# Configuration options from RevealJS
controls: JsBool = JsBool.false
controls_tutorial: JsBool = JsBool.true
controls_layout: ControlsLayout = ControlsLayout.bottom_right
controls_back_arrows: ControlsBackArrows = ControlsBackArrows.faded
progress: JsBool = JsBool.false
slide_number: SlideNumber = SlideNumber.false
show_slide_number: Union[ShowSlideNumber, Function] = ShowSlideNumber.all
hash_one_based_index: JsBool = JsBool.false
hash: JsBool = JsBool.false
respond_to_hash_changes: JsBool = JsBool.false
history: JsBool = JsBool.false
keyboard: JsBool = JsBool.true
keyboard_condition: Union[KeyboardCondition, Function] = KeyboardCondition.null
disable_layout: JsBool = JsBool.false
overview: JsBool = JsBool.true
center: JsBool = JsBool.true
touch: JsBool = JsBool.true
loop: JsBool = JsBool.false
rtl: JsBool = JsBool.false
navigation_mode: NavigationMode = NavigationMode.default
shuffle: JsBool = JsBool.false
fragments: JsBool = JsBool.true
fragment_in_url: JsBool = JsBool.true
embedded: JsBool = JsBool.false
help: JsBool = JsBool.true
pause: JsBool = JsBool.true
show_notes: JsBool = JsBool.false
auto_play_media: AutoPlayMedia = AutoPlayMedia.null
preload_iframes: PreloadIframes = PreloadIframes.null
auto_animate: JsBool = JsBool.true
auto_animate_matcher: Union[AutoAnimateMatcher, Function] = AutoAnimateMatcher.null
auto_animate_easing: AutoAnimateEasing = AutoAnimateEasing.ease
auto_animate_duration: float = 1.0
auto_animate_unmatched: JsBool = JsBool.true
auto_animate_styles: List[str] = [
"opacity",
"color",
"background-color",
"padding",
"font-size",
"line-height",
"letter-spacing",
"border-width",
"border-color",
"border-radius",
"outline",
"outline-offset",
]
auto_slide: AutoSlide = 0
auto_slide_stoppable: JsBool = JsBool.true
auto_slide_method: Union[AutoSlideMethod, Function] = AutoSlideMethod.null
default_timing: Union[JsNull, int] = JsNull.null
mouse_wheel: JsBool = JsBool.false
preview_links: JsBool = JsBool.false
post_message: JsBool = JsBool.true
post_message_events: JsBool = JsBool.false
focus_body_on_page_visibility_change: JsBool = JsBool.true
transition: Transition = Transition.none
transition_speed: TransitionSpeed = TransitionSpeed.default
background_transition: BackgroundTransition = BackgroundTransition.none
pdf_max_pages_per_slide: Union[int, str] = "Number.POSITIVE_INFINITY"
pdf_separate_fragments: JsBool = JsBool.true
pdf_page_height_offset: int = -1
view_distance: int = 3
mobile_view_distance: int = 2
display: Display = Display.block
hide_inactive_cursor: JsBool = JsBool.true
hide_cursor_time: int = 5000
# Add. options
background_color: str = "black" # TODO: use pydantic.color.Color
reveal_version: str = "4.4.0"
reveal_theme: RevealTheme = RevealTheme.black
shuffle: JSBool = JSBool.false
title: str = "Manim Slides"
width: str = "100%"
class Config:
use_enum_values = True
extra = "forbid"
def get_sections_iter(self) -> Generator[str, None, None]:
"""Generates a sequence of sections, one per slide, that will be included into the html template."""
@ -94,17 +285,29 @@ class RevealJS(Converter):
file = presentation_config.files[slide_config.start_animation]
file = os.path.join(self.assets_dir, os.path.basename(file))
# TODO: document this
# Videos are muted because, otherwise, the first slide never plays correctly.
# This is due to a restriction in playing audio without the user doing anything.
# Later, this might be useful to only mute the first video, or to make it optional.
# Read more about this:
# https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_and_autoplay_blocking
if slide_config.is_loop():
yield f'<section data-background-video="{file}" data-background-video-loop></section>'
yield f'<section data-background-video="{file}" data-background-video-muted data-background-video-loop></section>'
else:
yield f'<section data-background-video="{file}"></section>'
yield f'<section data-background-video="{file}" data-background-video-muted></section>'
def load_template(self) -> str:
"""Returns the RevealJS HTML template as a string."""
if isinstance(self.template, str):
with open(self.template, "r") as f:
return f.read()
return pkg_resources.resource_string(
__name__, "data/revealjs_template.html"
).decode()
def open(self, file: str) -> bool:
return webbrowser.open(file)
def convert_to(self, dest: str) -> None:
"""Converts this configuration into a RevealJS HTML presentation, saved to DEST."""
dirname = os.path.dirname(dest)
@ -138,19 +341,13 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
if not value or ctx.resilient_parsing:
return
to = ctx.params.get("to")
to = ctx.params.get("to", "html")
if to:
converter = Converter.from_string(to)(scenes=[])
for key, value in converter.dict().items():
click.echo(f"{key}: {repr(value)}")
converter = Converter.from_string(to)(presentation_configs=[])
for key, value in converter.dict().items():
click.echo(f"{key}: {repr(value)}")
ctx.exit()
else:
raise click.UsageError(
"Using --show-config option requires to first specify --to option."
)
ctx.exit()
return click.option(
"--show-config",
@ -163,6 +360,35 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
)(function)
def show_template_option(function: Callable[..., Any]) -> Callable[..., Any]:
"""Wraps a function to add a `--show-template` option."""
def callback(ctx: Context, param: Parameter, value: bool) -> None:
if not value or ctx.resilient_parsing:
return
to = ctx.params.get("to", "html")
template = ctx.params.get("template", None)
converter = Converter.from_string(to)(
presentation_configs=[], template=template
)
click.echo(converter.load_template())
ctx.exit()
return click.option(
"--show-template",
is_flag=True,
help="Show the template (currently) used for a given conversion format and exit.",
default=None,
expose_value=False,
show_envvar=True,
callback=callback,
)(function)
@click.command()
@click.argument("scenes", nargs=-1)
@folder_path_option
@ -187,8 +413,16 @@ def show_config_options(function: Callable[..., Any]) -> Callable[..., Any]:
"config_options",
multiple=True,
callback=validate_config_option,
help="Configuration options passed to the converter. E.g., pass `-cbackground_color=red` to set the background color to red (if supported).",
help="Configuration options passed to the converter. E.g., pass `-cslide_number=true` to display slide numbers.",
)
@click.option(
"--use-template",
"template",
metavar="FILE",
type=click.Path(exists=True, dir_okay=False),
help="Use the template given by FILE instead of default one. To echo the default template, use `--show-template`.",
)
@show_template_option
@show_config_options
@verbosity_option
def convert(
@ -199,6 +433,7 @@ def convert(
open_result: bool,
force: bool,
config_options: Dict[str, str],
template: Optional[str],
) -> None:
"""
Convert SCENE(s) into a given format and writes the result in DEST.
@ -206,11 +441,29 @@ def convert(
presentation_configs = get_scenes_presentation_config(scenes, folder)
converter = Converter.from_string(to)(
presentation_configs=presentation_configs, **config_options
)
try:
converter = Converter.from_string(to)(
presentation_configs=presentation_configs,
template=template,
**config_options,
)
converter.convert_to(dest)
converter.convert_to(dest)
if open_result:
converter.open(dest)
if open_result:
converter.open(dest)
except ValidationError as e:
errors = e.errors()
msg = [
f"{len(errors)} error(s) occured with configuration options for '{to}', see below."
]
for error in errors:
option = error["loc"][0]
_msg = error["msg"]
msg.append(f"Option '{option}': {_msg}")
raise click.UsageError("\n".join(msg))

View File

@ -1,185 +1,291 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{title}</title>
<title>{title}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/reveal.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/theme/{reveal_theme}.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/theme/{reveal_theme}.min.css">
<!-- Theme used for syntax highlighting of code -->
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
<!-- Theme used for syntax highlighting of code -->
<!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/zenburn.min.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/print/pdf.css' : 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<!-- <link rel="stylesheet" href="index.css"> -->
</head>
<!-- <link rel="stylesheet" href="index.css"> -->
</head>
<body>
<div class="reveal">
<div class="slides">
{sections}
</div>
</div>
<body>
<div class="reveal">
<div class="slides">
{sections}
</div>
</div>
<!--<script src="lib/js/head.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/npm/headjs@1.0.3/dist/1.0.0/head.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/js/reveal.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{reveal_version}/reveal.min.js"></script>
<!-- <script src="index.js"></script> -->
<script>
// More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({{
// Display controls in the bottom right corner
controls: {controls},
<!-- To include plugins, see: https://revealjs.com/plugins/ -->
width: '{width}',
height: '{height}',
<!-- <script src="index.js"></script> -->
<script>
Reveal.initialize({{
// Display a presentation progress bar
progress: {progress},
// 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.
width: {width},
height: {height},
// Set default timing of 2 minutes per slide
defaultTiming: 120,
// Factor of the display size that should remain empty around
// the content
margin: {margin},
// Display the page number of the current slide
slideNumber: true,
// Bounds for smallest/largest possible scale to apply to content
minScale: {min_scale},
maxScale: {max_scale},
// Push each slide change to the browser history
history: false,
// Display presentation control arrows
controls: {controls},
// Enable keyboard shortcuts for navigation
keyboard: true,
// Help the user learn the controls by providing hints, for example by
// bouncing the down arrow when they first encounter a vertical slide
controlsTutorial: {controls_tutorial},
// Enable the slide overview mode
overview: true,
// Determines where controls appear, "edges" or "bottom-right"
controlsLayout: {controls_layout},
// Vertical centering of slides
center: true,
// Visibility rule for backwards navigation arrows; "faded", "hidden"
// or "visible"
controlsBackArrows: {controls_back_arrows},
// Enables touch navigation on devices with touch input
touch: true,
// Display a presentation progress bar
progress: {progress},
// Loop the presentation
loop: {loop},
// Display the page number of the current slide
// - true: Show slide number
// - false: Hide slide number
//
// Can optionally be set as a string that specifies the number formatting:
// - "h.v": Horizontal . vertical slide number (default)
// - "h/v": Horizontal / vertical slide number
// - "c": Flattened slide number
// - "c/t": Flattened slide number / total slides
//
// Alternatively, you can provide a function that returns the slide
// number for the current slide. The function should take in a slide
// object and return an array with one string [slideNumber] or
// three strings [n1,delimiter,n2]. See #formatSlideNumber().
slideNumber: {slide_number},
// Change the presentation direction to be RTL
rtl: false,
// Can be used to limit the contexts in which the slide number appears
// - "all": Always show the slide number
// - "print": Only when printing to PDF
// - "speaker": Only in the speaker view
showSlideNumber: {show_slide_number},
// Randomizes the order of slides each time the presentation loads
shuffle: {shuffle},
// Use 1 based indexing for # links to match slide number (default is zero
// based)
hashOneBasedIndex: {hash_one_based_index},
// Turns fragments on and off globally
fragments: {fragments},
// Add the current slide number to the URL hash so that reloading the
// page/copying the URL will return you to the same slide
hash: {hash},
// Flags if the presentation is running in an embedded mode,
// i.e. contained within a limited portion of the screen
embedded: {embedded},
// Flags if we should monitor the hash and change slides accordingly
respondToHashChanges: {respond_to_hash_changes},
// Flags if we should show a help overlay when the questionmark
// key is pressed
help: true,
// Push each slide change to the browser history. Implies `hash: true`
history: {history},
// Flags if speaker notes should be visible to all viewers
showNotes: false,
// Enable keyboard shortcuts for navigation
keyboard: {keyboard},
// Global override for autolaying embedded media (video/audio/iframe)
// - null: Media will only autoplay if data-autoplay is present
// - true: All media will autoplay, regardless of individual setting
// - false: No media will autoplay, regardless of individual setting
autoPlayMedia: null,
// Optional function that blocks keyboard events when retuning false
//
// If you set this to 'focused', we will only capture keyboard events
// for embedded decks when they are in focus
keyboardCondition: {keyboard_condition},
// Number of milliseconds between automatically proceeding to the
// next slide, disabled when set to 0, this value can be overwritten
// by using a data-autoslide attribute on your slides
autoSlide: 0,
// Disables the default reveal.js slide layout (scaling and centering)
// so that you can use custom CSS layout
disableLayout: {disable_layout},
// Stop auto-sliding after user input
autoSlideStoppable: true,
// Enable the slide overview mode
overview: {overview},
// Use this method for navigation when auto-sliding
autoSlideMethod: Reveal.navigateNext,
// Vertical centering of slides
center: {center},
// Enable slide navigation via mouse wheel
mouseWheel: false,
// Enables touch navigation on devices with touch input
touch: {touch},
// Hides the address bar on mobile devices
hideAddressBar: true,
// Loop the presentation
loop: {loop},
// Opens links in an iframe preview overlay
previewLinks: true,
// Change the presentation direction to be RTL
rtl: {rtl},
// Transition style
transition: 'none', // none/fade/slide/convex/concave/zoom
// Changes the behavior of our navigation directions.
//
// "default"
// Left/right arrow keys step between horizontal slides, up/down
// arrow keys step between vertical slides. Space key steps through
// all slides (both horizontal and vertical).
//
// "linear"
// Removes the up/down arrows. Left/right arrows step through all
// slides (both horizontal and vertical).
//
// "grid"
// When this is enabled, stepping left/right from a vertical stack
// to an adjacent vertical stack will land you at the same vertical
// index.
//
// Consider a deck with six slides ordered in two vertical stacks:
// 1.1 2.1
// 1.2 2.2
// 1.3 2.3
//
// If you're on slide 1.3 and navigate right, you will normally move
// from 1.3 -> 2.1. If "grid" is used, the same navigation takes you
// from 1.3 -> 2.3.
navigationMode: {navigation_mode},
// Transition speed
transitionSpeed: 'default', // default/fast/slow
// Randomizes the order of slides each time the presentation loads
shuffle: {shuffle},
// Transition style for full page slide backgrounds
backgroundTransition: 'none', // none/fade/slide/convex/concave/zoom
// Turns fragments on and off globally
fragments: {fragments},
// Number of slides away from the current that are visible
viewDistance: 3,
// Flags whether to include the current fragment in the URL,
// so that reloading brings you to the same fragment position
fragmentInURL: {fragment_in_url},
// Parallax background image
parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
// Flags if the presentation is running in an embedded mode,
// i.e. contained within a limited portion of the screen
embedded: {embedded},
// Parallax background size
parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px"
// Flags if we should show a help overlay when the question-mark
// key is pressed
help: {help},
// Number of pixels to move the parallax background per slide
// - Calculated automatically unless specified
// - Set to 0 to disable movement along an axis
parallaxBackgroundHorizontal: null,
parallaxBackgroundVertical: null,
// Flags if it should be possible to pause the presentation (blackout)
pause: {pause},
// Flags if speaker notes should be visible to all viewers
showNotes: {show_notes},
// Global override for autolaying embedded media (video/audio/iframe)
// - null: Media will only autoplay if data-autoplay is present
// - true: All media will autoplay, regardless of individual setting
// - false: No media will autoplay, regardless of individual setting
autoPlayMedia: {auto_play_media},
// Global override for preloading lazy-loaded iframes
// - null: Iframes with data-src AND data-preload will be loaded when within
// the viewDistance, iframes with only data-src will be loaded when visible
// - true: All iframes with data-src will be loaded when within the viewDistance
// - false: All iframes with data-src will be loaded only when visible
preloadIframes: {preload_iframes},
// Can be used to globally disable auto-animation
autoAnimate: {auto_animate},
// Optionally provide a custom element matcher that will be
// used to dictate which elements we can animate between.
autoAnimateMatcher: {auto_animate_matcher},
// Default settings for our auto-animate transitions, can be
// overridden per-slide or per-element via data arguments
autoAnimateEasing: {auto_animate_easing},
autoAnimateDuration: {auto_animate_duration},
autoAnimateUnmatched: {auto_animate_unmatched},
// CSS properties that can be auto-animated. Position & scale
// is matched separately so there's no need to include styles
// like top/right/bottom/left, width/height or margin.
autoAnimateStyles: {auto_animate_styles},
// Controls automatic progression to the next slide
// - 0: Auto-sliding only happens if the data-autoslide HTML attribute
// is present on the current slide or fragment
// - 1+: All slides will progress automatically at the given interval
// - false: No auto-sliding, even if data-autoslide is present
autoSlide: {auto_slide},
// Stop auto-sliding after user input
autoSlideStoppable: {auto_slide_stoppable},
// Use this method for navigation when auto-sliding (defaults to navigateNext)
autoSlideMethod: {auto_slide_method},
// Specify the average time in seconds that you think you will spend
// presenting each slide. This is used to show a pacing timer in the
// speaker view
defaultTiming: {default_timing},
// Enable slide navigation via mouse wheel
mouseWheel: {mouse_wheel},
// Opens links in an iframe preview overlay
// Add `data-preview-link` and `data-preview-link="false"` to customise each link
// individually
previewLinks: {preview_links},
// Exposes the reveal.js API through window.postMessage
postMessage: {post_message},
// Dispatches all reveal.js events to the parent window through postMessage
postMessageEvents: {post_message_events},
// Focuses body when page changes visibility to ensure keyboard shortcuts work
focusBodyOnPageVisibilityChange: {focus_body_on_page_visibility_change},
// Transition style
transition: {transition}, // none/fade/slide/convex/concave/zoom
// Transition speed
transitionSpeed: {transition_speed}, // default/fast/slow
// Transition style for full page slide backgrounds
backgroundTransition: {background_transition}, // none/fade/slide/convex/concave/zoom
// The maximum number of pages a single slide can expand onto when printing
// to PDF, unlimited by default
pdfMaxPagesPerSlide: {pdf_max_pages_per_slide},
// Prints each fragment on a separate slide
pdfSeparateFragments: {pdf_separate_fragments},
// Offset used to reduce the height of content within exported PDF pages.
// This exists to account for environment differences based on how you
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
// on precisely the total height of the document whereas in-browser
// printing has to end one pixel before.
pdfPageHeightOffset: {pdf_page_height_offset},
// Number of slides away from the current that are visible
viewDistance: {view_distance},
// Number of slides away from the current that are visible on mobile
// devices. It is advisable to set this to a lower number than
// viewDistance in order to save resources.
mobileViewDistance: {mobile_view_distance},
// The display mode that will be used to show slides
display: {display},
// Hide cursor if inactive
hideInactiveCursor: {hide_inactive_cursor},
// Time before the cursor is hidden (in ms)
hideCursorTime: {hide_cursor_time}
// The display mode that will be used to show slides
display: 'block',
/*
multiplex: {{
// Example values. To generate your own, see the socket.io server instructions.
secret: '13652805320794272084', // Obtained from the socket.io server. Gives this (the master) control of the presentation
id: '1ea875674b17ca76', // Obtained from socket.io server
url: 'https://reveal-js-multiplex-ccjbegmaii.now.sh' // Location of socket.io server
}},
*/
dependencies: [
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/markdown/marked.js' }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/markdown/markdown.js' }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/notes/notes.js', async: true }},
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/highlight/highlight.js', async: true, callback: function () {{ hljs.initHighlightingOnLoad(); }} }},
//{{ src: '//cdn.socket.io/socket.io-1.3.5.js', async: true }},
//{{ src: 'plugin/multiplex/master.js', async: true }},
// and if you want speaker notes
{{ src: 'https://cdn.jsdelivr.net/npm/reveal.js@{reveal_version}/plugin/notes-server/client.js', async: true }}
],
markdown: {{
// renderer: myrenderer,
smartypants: true
}}
}});
Reveal.configure({{
// PDF Configurations
pdfMaxPagesPerSlide: 1
}});
</script>
</body>
}});
</script>
</body>
</html>

View File

@ -2,7 +2,7 @@ import os
import platform
import sys
import time
from enum import IntEnum, auto, unique
from enum import Enum, IntEnum, auto, unique
from typing import Any, Dict, List, Optional, Tuple, Union
import click
@ -28,9 +28,17 @@ WINDOW_NAME = "Manim Slides"
WINDOW_INFO_NAME = f"{WINDOW_NAME}: Info"
WINDOWS = platform.system() == "Windows"
class AspectRatio(Enum):
ignore = Qt.IgnoreAspectRatio
keep = Qt.KeepAspectRatio
auto = "auto"
ASPECT_RATIO_MODES = {
"ignore": Qt.IgnoreAspectRatio,
"keep": Qt.KeepAspectRatio,
"ignore": AspectRatio.ignore,
"keep": AspectRatio.keep,
"auto": AspectRatio.auto,
}
RESIZE_MODES = {
@ -514,7 +522,7 @@ class App(QWidget): # type: ignore
fullscreen: bool = False,
resolution: Tuple[int, int] = (1980, 1080),
hide_mouse: bool = False,
aspect_ratio: Qt.AspectRatioMode = Qt.IgnoreAspectRatio,
aspect_ratio: AspectRatio = AspectRatio.auto,
resize_mode: Qt.TransformationMode = Qt.SmoothTransformation,
background_color: str = "black",
**kwargs: Any,
@ -533,6 +541,9 @@ class App(QWidget): # type: ignore
self.setCursor(Qt.BlankCursor)
self.label = QLabel(self)
if self.aspect_ratio == AspectRatio.auto:
self.label.setScaledContents(True)
self.label.setAlignment(Qt.AlignCenter)
self.label.resize(self.display_width, self.display_height)
self.label.setStyleSheet(f"background-color: {background_color}")
@ -584,10 +595,11 @@ class App(QWidget): # type: ignore
self.deleteLater()
def resizeEvent(self, event: QResizeEvent) -> None:
self.pixmap = self.pixmap.scaled(
self.width(), self.height(), self.aspect_ratio, self.resize_mode
)
self.label.setPixmap(self.pixmap)
if not self.label.hasScaledContents():
self.pixmap = self.pixmap.scaled(
self.width(), self.height(), self.aspect_ratio.value, self.resize_mode
)
self.label.setPixmap(self.pixmap)
self.label.resize(self.width(), self.height())
def closeEvent(self, event: QCloseEvent) -> None:
@ -601,9 +613,11 @@ class App(QWidget): # type: ignore
bytes_per_line = ch * w
qt_img = QImage(cv_img.data, w, h, bytes_per_line, QImage.Format_BGR888)
if w != self.width() or h != self.height():
if not self.label.hasScaledContents() and (
w != self.width() or h != self.height()
):
qt_img = qt_img.scaled(
self.width(), self.height(), self.aspect_ratio, self.resize_mode
self.width(), self.height(), self.aspect_ratio.value, self.resize_mode
)
self.label.setPixmap(QPixmap.fromImage(qt_img))
@ -755,8 +769,8 @@ def get_scenes_presentation_config(
@click.option(
"--aspect-ratio",
type=click.Choice(ASPECT_RATIO_MODES.keys(), case_sensitive=False),
default="ignore",
help="Set the aspect ratio mode to be used when rescaling video.",
default="auto",
help="Set the aspect ratio mode to be used when rescaling video. `'auto'` option is equivalent to `'ignore'`, but can be much faster due to not calling `scaled()` method on every frame.",
show_default=True,
)
@click.option(
@ -845,4 +859,3 @@ def present(
)
a.show()
sys.exit(app.exec_())
logger.debug("After")

2526
poetry.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,15 @@
[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"
[project]
[tool.poetry]
name = "manim-slides"
description = "Tool for live presentations using manim"
authors = [
{ name = "Jérome Eertmans", email = "jeertmans@icloud.com" }
"Jérome Eertmans <jeertmans@icloud.com>"
]
version = "4.7.0"
license = {file = "LICENSE.md"}
version = "4.8.1"
license = "GPL-3.0-only"
readme = "README.md"
requires-python = ">=3.8"
homepage = "https://github.com/jeertmans/manim-slides"
documentation = "https://eertmans.be/manim-slides"
repository = "https://github.com/jeertmans/manim-slides"
keywords = ["manim", "slides", "plugin", "manimgl"]
@ -28,24 +26,79 @@ classifiers = [
"Topic :: Scientific/Engineering",
]
dependencies = [
"click>=8.0",
"click-default-group>=1.2",
"numpy>=1.19.3",
"opencv-python>=4.6",
"pydantic>=1.9.1",
"pyside6>=6",
"requests>=2.26.0",
"tqdm>=4.62.3",
exclude = ["docs/","static/"]
packages = [
{ include = "manim_slides" },
]
[tool.setuptools]
packages = ["manim_slides"]
[project.urls]
homepage = "https://github.com/jeertmans/manim-slides"
documentation = "https://eertmans.be/manim-slides"
repository = "https://github.com/jeertmans/manim-slides"
[tool.poetry.dependencies]
python = ">=3.8.1,<3.12"
click = "^8.1.3"
click-default-group = "^1.2.2"
numpy = "^1.19"
opencv-python = "^4.6.0.66"
pydantic = "^1.10.2"
pyside6 = "^6.4.1"
requests = "^2.28.1"
tqdm = "^4.64.1"
[project.scripts]
[tool.poetry.group.docs.dependencies]
manim = "^0.17.0"
sphinx = "^5.3.0"
sphinx-click = "^4.4.0"
furo = "^2022.9.29"
[tool.poetry.group.dev.dependencies]
black = "^22.10.0"
mypy = "^0.991"
isort = "^5.10.1"
flake8 = "^6.0.0"
[tool.poetry.group.test.dependencies]
manim = "^0.17.0"
manimgl = "^1.6.1"
[build-system]
requires = ["setuptools","poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.isort]
profile = "black"
py_version = 38
[tool.black]
target-version = ["py38"]
[tool.mypy]
python_version = "3.8"
install-types = true
non-interactive = true
ignore-missing-imports = true
# Disallow dynamic typing
disallow-any-generics = true
disallow-subclassing-any = true
# Disallow untyped definitions and calls
disallow-untyped-defs = true
disallow-incomplete-defs = true
check-untyped-defs = true
# None and optional handling
no-implicit-optional = true
# Configuring warnings
warn-unused-ignores = true
warn-no-return = true
no-warn-return-any = true
warn-redundant-casts = true
# Strict equality
strict-equality = true
# Config file
warn-unused-configs = true
[tool.poetry.plugins]
[tool.poetry.plugins."console_scripts"]
manim-slides = "manim_slides.__main__:cli"

BIN
static/docs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB