scal_core/lib.rs
1#![warn(missing_docs)]
2#![warn(clippy::pedantic)]
3#![warn(clippy::nursery)]
4//! ### Easy animation system focused on code.
5//!
6//! # Example
7//! start by creating a new rust app and import 3 crates:
8//! ``` toml
9//! # /Cargol.toml
10//! [dependencies]
11//! # contains functions and types for defining animations
12//! # that will be sent to the scal-runtime for rendering/preview.
13//! scal-core = "..."
14//! # used for communicating with the scal runtime. you only use ``#[scal_ipc::main]`` from it
15//! scal-ipc = "..."
16//! # `glam` is a simple and fast linear algebra library for games and graphics.
17//! glam = "0.33.2"
18//! ```
19//! define the animation with:
20//! ```
21//! /// /src/main.rs
22//! use glam::{Vec2, vec2};
23//! use scal_core::prelude::*;
24//! // Size of the virtual canvas not the output resolution - configured by Config.toml
25//! const WINDOW: Vec2 = vec2(1920., 1080.);
26//! // This handles all the ipc communication with the scal runtime
27//! #[scal_ipc::main]
28//! fn main() -> Project {
29//! // https://github.com/tinted-theming/schemes
30//! let theme = Theme::from_base16(Base16::from_hex([
31//! 0x11121d, 0x1A1B2A, 0x212234, 0x282c34, 0x4a5057, 0xa0a8cd, 0xa0a8cd, 0xa0a8cd, 0xee6d85,
32//! 0xf6955b, 0xd7a65f, 0x95c561, 0x38a89d, 0x7199ee, 0xa485dd, 0x773440,
33//! ]));
34//!
35//! const CW_WIDTH: f32 = 800.;
36//! const CW_HEIGHT: f32 = 600.;
37//!
38//! // Simple objects that handles most needs for animating code.
39//! let cw = code_window()
40//! .source("fn main() {\n println!(\"Hello, world!\");\n}\n")
41//! .font_family("SF Pro Display")
42//! .font_size(20.)
43//! .syntax(Syntax::Rust)
44//! .line_numbers(true)
45//! .title("fib.rs")
46//! .width(CW_WIDTH)
47//! .height(CW_HEIGHT)
48//! .title_font_size(25.)
49//! .background_color(Color::new(0.15, 0.15, 0.2, 1.))
50//! .pos(WINDOW / 2.)
51//! .build();
52//!
53//! let pointer = svg()
54//! .path("./pointer-tool.svg")
55//! .size(Vec2::new(40., 40.))
56//! .color(Color::WHITE)
57//! .stretch(StretchMode::Fit)
58//! .pos(Vec2::new(500., 500.))
59//! .z(1.)
60//! .build();
61//!
62//! Project {
63//! scene_settings: SceneSettings {
64//! background_color: Color::new(0.8, 0.8, 0.8, 0.),
65//! camera: Camera::new(Vec2::new(1920., 1080.), Vec2::ZERO, 1.),
66//! default_theme: theme,
67//! },
68//! // This is the actual animation sequence
69//! timeline: timeline![
70//! // all objects need to be instantiated(layout instantiates all children during its instantiation)
71//! cw.instantiate(),
72//! pointer.instantiate(),
73//!
74//! wait(0.5.s()),
75//! parallel![
76//! cw.add_lines()
77//! .str(
78//! r"
79//! fn fib(n: u32) -> u32 {
80//! match n {
81//! 0 => 0,
82//! 1 => 1,
83//! _ => fib(n - 1) + fib(n - 2),
84//! }
85//! }
86//! "
87//! )
88//! .over(5.s())
89//! .style(CodeAnimationStyle::TypeWriterInstantResize),
90//! ],
91//! wait(0.5.s()),
92//! pointer
93//! .transform
94//! .position()
95//! .object(cw.close_button())
96//! .to(vec2(15., 15.))
97//! .over(0.5.s())
98//! .ease(Ease::InOutCubic),
99//! cw.close_button().scale().to(Vec2::ONE * 0.8).over(0.3.s()),
100//! cw.close_button().scale().to(Vec2::ONE).over(0.3.s()),
101//! parallel![
102//! cw.transform
103//! .scale()
104//! .to(Vec2::ZERO)
105//! .over(0.5)
106//! .ease(Ease::OutCubic),
107//! cw.transform
108//! .position()
109//! .to((WINDOW - vec2(CW_WIDTH, CW_HEIGHT)) / 2.)
110//! .over(0.5)
111//! .ease(Ease::OutCubic),
112//! ],
113//! wait(0.5.s()),
114//! ],
115//! }
116//! }
117//! ```
118//! Basic animation output config.
119//! ``` toml
120//! # /Config.toml
121//! [animation]
122//! binary = "cargo run"
123//!
124//! [rendering]
125//! text_resolution_multiplier = 2.0
126//! width = 3840
127//! height = 2160
128//! fps = 60
129//!
130//! [encoding]
131//! output_path = "test.mov"
132//! codec_type = "H264Nvenc"
133//! ```
134//! make sure that you have installed required system dependencies:
135//!
136//! - Ubuntu/Debian:
137//! ``sudo apt install ffmpeg libwayland-dev libxkbcommon-dev libx11-dev libxcursor-dev libxi-dev libxrandr-dev libxcb1-dev libasound2-dev libpulse-dev``
138//!
139//! - Arch:
140//! ``sudo pacman -S ffmpeg wayland libxkbcommon libx11 libxcursor libxi libxrandr libxcb alsa-lib libpulse``
141//!
142//! - Fedora:
143//! ``sudo dnf install ffmpeg-devel wayland-devel libxkbcommon-devel libX11-devel libXcursor-devel libXi-devel libXrandr-devel libxcb-devel alsa-lib-devel pulseaudio-libs-devel``
144//!
145//! - NixOS:
146//! download flake file:
147//! ```bash
148//! wget https://raw.githubusercontent.com/Feeflak/SCAL/refs/heads/main/flake.nix
149//! ```
150//! Set-up the environment:
151//! ```bash
152//! nix develop
153//! ```
154//!
155//! And now you can just use the scal runtime to render/preview the animation.
156//! ``` bash
157//! ❯ ls
158//! Cargo.toml Config.toml pointer-tool.svg src test.mov
159//! ❯ scal render
160//! ...
161//! ❯ ffplay ./test.mov
162//! ```
163//! # Features
164//!
165//! ## High Quality Animations of Code with Ease.
166//! First party support for code modification animations, syntax highlighting, custom color schemes, and glyphs.
167//! Supports syntax highlighting for most popular languages using Tree-sitter.
168//! Use standard [Base16 color schemes](https://github.com/tinted-theming/schemes) to configure
169//! syntax highlighting.
170//!
171//! ## Hot Reloading Animation Preview
172//!
173//! Supports preview view with a timeline that automatically reloads upon animation code change.
174//! Audio waveform display support in timeline.
175//! You can click on individual animation operations or sound fx to display what type of animation
176//! they are, and where they are located in the animation source code.
177//!
178//! ## LSP
179//! Thanks to the powerful rust LSP you can read documentation from your editor.
180//!
181//! ## Examples
182//!
183//! If you want to see features of this project you can look at the example directory.
184//!
185//! ## Clear Syntax
186//! you instantly know what every function does.
187//!
188//! ```
189//! let typing = sfx()
190//! .path("./keeb.wav")
191//! .volume(5.)
192//! .pitch(1.)
193//! .skip_time(0.)
194//! .duration(5.)
195//! .pitch_variation(0.05);
196//! ```
197//!
198//! ## Fast Render Times
199//! Using FFmpeg supports hardware H264 encoding for most popular GPU brands- nvidia, intel, apple(I
200//! only have nvidia gpu-s so tests on other platforms are needed)
201//! Uses WGPU to efficiently render scenes.
202//! ## Multi-platform
203//! Works on all platforms(Linux, Mac, Windows)
204//! (I only have NixOS systems so testing on other platforms is needed)
205//!
206//! ## Audio System
207//! Uses FFmpeg for audio encoding and [cpal](https://github.com/RustAudio/cpal) for preview audio, to deliver stable audio system.
208//!
209//! # Installing Scala Runtime
210//! ## Distro Package
211//! Sadly there are no packages currently for this app, you need to compile it from source or
212//! install using cargo.
213//! ## Nix Flake
214//! You can automatically compile from source using flakes like this:
215//!{
216//! inputs.scal-runtime = {
217//! url = "github:Feeflak/scal";
218//! inputs.nixpkgs.follows = "nixpkgs";
219//! };
220//!
221//! outputs = { self, nixpkgs, scal-runtime, ... }: {
222//! nixosConfigurations.my-pc = nixpkgs.lib.nixosSystem {
223//! system = "x86_64-linux";
224//!
225//! modules = [
226//! ({ pkgs, ... }: {
227//! environment.systemPackages = [
228//! scal-runtime.packages.${pkgs.stdenv.hostPlatform.system}.default
229//! ];
230//! })
231//! ];
232//! };
233//! };
234//! }
235//! ## Compiling From Source
236//! SCAL uses Cargo to manage all Rust dependencies automatically. Only a few native libraries must be installed manually.
237//!
238//! ## 1. Install Rust
239//!
240//! If you don't already have Rust installed:
241//!
242//! ```bash
243//! curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
244//! ```
245//!
246//! Verify the installation:
247//!
248//! ```bash
249//! cargo --version
250//! rustc --version
251//! ```
252//!
253//! ---
254//!
255//! ## Linux
256//!
257//! ### Arch Linux
258//!
259//! Install the required packages:
260//!
261//! ```bash
262//! sudo pacman -S \
263//! ffmpeg \
264//! pkgconf \
265//! clang \
266//! llvm \
267//! wayland \
268//! libxkbcommon \
269//! libx11 \
270//! libxcursor \
271//! libxi \
272//! libxrandr \
273//! libxcb \
274//! alsa-lib \
275//! libpulse
276//! ```
277//!
278//!
279//! ---
280//!
281//! ### Fedora
282//!
283//! Install the required packages:
284//!
285//! ```bash
286//! sudo dnf install \
287//! ffmpeg-devel \
288//! pkgconf-pkg-config \
289//! clang \
290//! llvm-devel \
291//! wayland-devel \
292//! libxkbcommon-devel \
293//! libX11-devel \
294//! libXcursor-devel \
295//! libXi-devel \
296//! libXrandr-devel \
297//! libxcb-devel \
298//! alsa-lib-devel \
299//! pulseaudio-libs-devel
300//! ```
301//!
302//!
303//! ---
304//!
305//! ## Debian / Ubuntu
306//!
307//! Install the required packages:
308//!
309//! ```bash
310//! sudo apt update
311//!
312//! sudo apt install \
313//! pkg-config \
314//! ffmpeg \
315//! clang \
316//! libclang-dev \
317//! libwayland-dev \
318//! libxkbcommon-dev \
319//! libx11-dev \
320//! libxcursor-dev \
321//! libxi-dev \
322//! libxrandr-dev \
323//! libxcb1-dev \
324//! libasound2-dev \
325//! libpulse-dev
326//! ```
327//!
328//!
329//! ---
330//!
331//! ## NixOS
332//!
333//! The repository already contains a development shell.
334//!
335//! Enter it with:
336//!
337//! ```bash
338//! nix develop
339//! ```
340//!
341//! or
342//!
343//! ```bash
344//! nix-shell
345//! ```
346//!
347//! All required libraries are provided automatically.
348//!
349//! ---
350//!
351//! # macOS
352//!
353//! Install Homebrew if necessary.
354//!
355//! Then install the required packages:
356//!
357//! ```bash
358//! brew install \
359//! ffmpeg \
360//! llvm \
361//! pkg-config
362//! ```
363//!
364//! The remaining libraries required by SCAL are provided by macOS.
365//!
366//! ---
367//!
368//! # Windows
369//!
370//! Install:
371//!
372//! - Rust (via rustup)
373//! - Visual Studio 2022 with the **Desktop development with C++** workload
374//! - LLVM/Clang
375//! - FFmpeg
376//!
377//! Using Winget:
378//!
379//! ```powershell
380//! winget install Rustlang.Rustup
381//!
382//! winget install LLVM.LLVM
383//!
384//! winget install Gyan.FFmpeg
385//! ```
386//!
387//! After installing Visual Studio Build Tools, restart your terminal.
388//!
389//! ---
390//!
391//! # Building SCAL
392//!
393//! ```bash
394//! cargo install scal-runtime
395//! ```
396//!
397//! # Setting up a new animation project
398//! 1. Init project
399//! ```bash
400//! cargo init <Name>
401//! ````
402//! 2. Add dependencies to Cargo.toml
403//! ``` toml
404//! scal-core = "<version>"
405//! scal-ipc = "<version>"
406//! glam = "0.33.2"
407//! ```
408//! 3. basic animation output config
409//! ``` toml
410//! # /Config.toml
411//! [animation]
412//! binary = "cargo run"
413//!
414//! [rendering]
415//! text_resolution_multiplier = 2.0
416//! width = 3840
417//! height = 2160
418//! fps = 60
419//!
420//! [encoding]
421//! output_path = "test.mov"
422//! codec_type = "H264Nvenc"
423//! ```
424//! 4. setup the ipc macro
425//! ```
426//! // /scr/main.rs
427//! #[scal_ipc::main]
428//! fn main() -> Project {
429//! todo!()
430//! }
431//! ```
432//!
433//! That's it, you can start writing any animation you want
434//! simple example:
435//! ```
436//! // /scr/main.rs
437//! use glam::Vec2;
438//! use scal_core::prelude::*;
439//!
440//! #[scal_ipc::main]
441//! fn main() -> Project {
442//! let rect = rectangle()
443//! .size(Vec2::new(600., 400.))
444//! .corner_radius(40.)
445//! .color(Color::new(0., 0.2, 0.4, 1.))
446//! .pos(Vec2::new(400., 540.))
447//! .build();
448//!
449//! let circle = circle()
450//! .radius(200.)
451//! .color(Color::new(0.8, 0.2, 0.2, 1.))
452//! .pos(Vec2::new(1200., 500.))
453//! .build();
454//!
455//! let hex = polygon()
456//! .radius(180.)
457//! .sides(6)
458//! .color(Color::new(0.2, 0.7, 0.3, 1.))
459//! .pos(Vec2::new(800., 300.))
460//! .build();
461//!
462//! let triangle = polygon()
463//! .radius(150.)
464//! .sides(3)
465//! .color(Color::new(0.9, 0.6, 0.1, 1.))
466//! .pos(Vec2::new(1600., 700.))
467//! .build();
468//!
469//! Project {
470//! scene_settings: SceneSettings {
471//! background_color: Color::new(0.8, 0.8, 0.8, 1.0),
472//! camera: Camera::new(Vec2::new(1920., 1080.), Vec2::ZERO, 1.),
473//! default_theme: Theme::default(),
474//! },
475//! timeline: timeline![
476//! rect.instantiate(),
477//! circle.instantiate(),
478//! hex.instantiate(),
479//! triangle.instantiate(),
480//! wait(1.s()),
481//! parallel![
482//! triangle
483//! .transform
484//! .position()
485//! .to(Vec2::new(350., 800.))
486//! .over(1.s())
487//! .ease(Ease::OutBack),
488//! rect.transform
489//! .position()
490//! .to(Vec2::new(960., 540.))
491//! .over(1.s())
492//! .ease(Ease::InOutBack),
493//! ],
494//! ],
495//! }
496//! }
497//! ```
498//!
499//!
500
501pub mod anim;
502pub mod anim_builders;
503pub mod anim_obj;
504pub mod anim_op;
505pub mod camera;
506pub mod color;
507pub mod ease;
508pub mod highlight_specs;
509#[allow(missing_docs)]
510pub mod object_builders;
511pub mod project;
512pub mod seconds;
513pub mod settings;
514pub mod sfx;
515pub mod theme;
516pub mod transform;
517
518pub use anim_obj::{AnimObj, CodeHandle, CodeWindowHandle, StretchMode, Syntax, TextAlign};
519pub use anim_op::{AnimOP, CodeAnimationStyle, CodeHighlightAction, IntoAnimOp, SourceLoc};
520pub use camera::Camera;
521pub use color::Color;
522pub use ease::Ease;
523pub use project::{Project, SceneSettings};
524pub use scal_ipc_macros::timeline;
525pub use seconds::{DurationExt, Time};
526pub use settings::{CodecType, EncodingSettings, RenderingSettings};
527pub use sfx::{Sfx, SfxBuilder};
528pub use theme::{Base16, Theme};
529pub use transform::Transform;
530
531/// All the stuff that you need to create animations in Scal
532pub mod prelude {
533 pub use crate::anim::*;
534 pub use crate::anim_builders::*;
535 pub use crate::anim_obj::{
536 AnimObj, CodeHandle, CodeWindowHandle, StretchMode, Syntax, TextAlign,
537 };
538 pub use crate::anim_op::{AnimOP, CodeAnimationStyle, CodeHighlightAction, IntoAnimOp};
539 pub use crate::camera::Camera;
540 pub use crate::color::Color;
541 pub use crate::ease::Ease;
542 pub use crate::object_builders::*;
543 pub use crate::project::{Project, SceneSettings};
544 pub use crate::seconds::DurationExt;
545 pub use crate::sfx::{Sfx, sfx};
546 pub use crate::theme::{Base16, Theme};
547 pub use crate::transform::Transform;
548 pub use crate::{parallel, sequence, timeline};
549}