mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
157 lines
4.7 KiB
Rust
157 lines
4.7 KiB
Rust
use core_types::gpoll::GPoll;
|
|
use core_types::list::List;
|
|
use core_types::transform::Footprint;
|
|
use core_types::{CacheHash, Color, Context, Ctx, DeriveCtx, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime};
|
|
use glam::{DAffine2, DVec2};
|
|
use graphic_types::vector_types::Gradient;
|
|
use graphic_types::{Artboard, Graphic, Vector};
|
|
use raster_types::{CPU, GPU, Raster};
|
|
|
|
const DAY: f64 = 1000. * 3600. * 24.;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, dyn_any::DynAny, Default, Hash, CacheHash, node_macro::ChoiceType)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub enum RealTimeMode {
|
|
#[label("UTC")]
|
|
Utc,
|
|
Year,
|
|
Hour,
|
|
Minute,
|
|
#[default]
|
|
Second,
|
|
Millisecond,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum AnimationTimeMode {
|
|
AnimationTime,
|
|
FrameNumber,
|
|
}
|
|
|
|
/// Produces a chosen representation of the current real time and date (in UTC) based on the system clock.
|
|
#[node_macro::node(category("Animation"))]
|
|
fn real_time(
|
|
ctx: impl Ctx + ExtractRealTime,
|
|
_primary: (),
|
|
/// The time and date component to be produced as a number.
|
|
component: RealTimeMode,
|
|
) -> f64 {
|
|
let real_time = ctx.try_real_time().unwrap_or_default();
|
|
|
|
// TODO: Implement proper conversion using and existing time implementation
|
|
match component {
|
|
RealTimeMode::Utc => real_time,
|
|
RealTimeMode::Year => (real_time / DAY / 365.25).floor() + 1970., // TODO: Factor in a chosen timezone
|
|
RealTimeMode::Hour => (real_time / 1000. / 3600.).floor() % 24., // TODO: Factor in a chosen timezone
|
|
RealTimeMode::Minute => (real_time / 1000. / 60.).floor() % 60., // TODO: Factor in a chosen timezone
|
|
RealTimeMode::Second => (real_time / 1000.).floor() % 60.,
|
|
RealTimeMode::Millisecond => real_time % 1000.,
|
|
}
|
|
}
|
|
|
|
/// Produces the time, in seconds on the timeline, since the beginning of animation playback.
|
|
#[node_macro::node(category("Animation"))]
|
|
fn animation_time(
|
|
ctx: impl Ctx + ExtractAnimationTime,
|
|
_primary: (),
|
|
#[default(1)]
|
|
#[unit("/sec")]
|
|
rate: f64,
|
|
) -> f64 {
|
|
ctx.try_animation_time().unwrap_or_default() * rate
|
|
}
|
|
|
|
#[node_macro::node(category("Debug"))]
|
|
fn quantize_real_time<T>(
|
|
ctx: impl Ctx + ExtractRealTime + DeriveCtx,
|
|
#[implementations(
|
|
Context -> bool,
|
|
Context -> u32,
|
|
Context -> u64,
|
|
Context -> f32,
|
|
Context -> f64,
|
|
Context -> String,
|
|
Context -> DAffine2,
|
|
Context -> Footprint,
|
|
Context -> DVec2,
|
|
Context -> List<Vector>,
|
|
Context -> List<Graphic>,
|
|
Context -> List<Raster<CPU>>,
|
|
Context -> List<Raster<GPU>>,
|
|
Context -> List<Color>,
|
|
Context -> List<Artboard>,
|
|
Context -> List<Gradient>,
|
|
Context -> List<String>,
|
|
Context -> List<f64>,
|
|
Context -> (),
|
|
)]
|
|
value: impl Node<Context<'_>, Output = T>,
|
|
#[default(1)]
|
|
#[unit("sec")]
|
|
quantum: f64,
|
|
) -> GPoll<T> {
|
|
let time = ctx.try_real_time().unwrap_or_default();
|
|
let time = time / 1000.;
|
|
let mut quantized_time = (time * quantum.recip()).round() / quantum.recip();
|
|
if !quantized_time.is_finite() {
|
|
quantized_time = time;
|
|
}
|
|
let quantized_time = quantized_time * 1000.;
|
|
let scope = ctx.scope().with_real_time(Some(quantized_time));
|
|
value.eval(&ctx.with_scope(&scope))
|
|
}
|
|
|
|
#[node_macro::node(category("Debug"))]
|
|
fn quantize_animation_time<T>(
|
|
ctx: impl Ctx + ExtractAnimationTime + DeriveCtx,
|
|
#[implementations(
|
|
Context -> bool,
|
|
Context -> u32,
|
|
Context -> u64,
|
|
Context -> f32,
|
|
Context -> f64,
|
|
Context -> String,
|
|
Context -> DAffine2,
|
|
Context -> Footprint,
|
|
Context -> DVec2,
|
|
Context -> List<Vector>,
|
|
Context -> List<Graphic>,
|
|
Context -> List<Raster<CPU>>,
|
|
Context -> List<Raster<GPU>>,
|
|
Context -> List<Color>,
|
|
Context -> List<Artboard>,
|
|
Context -> List<Gradient>,
|
|
Context -> List<String>,
|
|
Context -> List<f64>,
|
|
Context -> (),
|
|
)]
|
|
value: impl Node<Context<'_>, Output = T>,
|
|
#[default(1)]
|
|
#[unit("sec")]
|
|
quantum: f64,
|
|
) -> GPoll<T> {
|
|
let time = ctx.try_animation_time().unwrap_or_default();
|
|
let mut quantized_time = (time * quantum.recip()).round() / quantum.recip();
|
|
if !quantized_time.is_finite() {
|
|
quantized_time = time;
|
|
}
|
|
let scope = ctx.scope().with_animation_time(Some(quantized_time));
|
|
value.eval(&ctx.with_scope(&scope))
|
|
}
|
|
|
|
/// Produces the current position of the user's pointer within the document canvas.
|
|
#[node_macro::node(category("Animation"))]
|
|
fn pointer_position(ctx: impl Ctx + ExtractPointerPosition) -> DVec2 {
|
|
ctx.try_pointer_position().unwrap_or_default()
|
|
}
|
|
|
|
// TODO: These nodes require more sophisticated algorithms for giving the correct result
|
|
// #[node_macro::node(category("Animation"))]
|
|
// fn month(ctx: impl Ctx + ExtractRealTime) -> f64 {
|
|
// ((ctx.try_real_time().unwrap_or_default() / DAY / 365.25 % 1.) * 12.).floor()
|
|
// }
|
|
// #[node_macro::node(category("Animation"))]
|
|
// fn day(ctx: impl Ctx + ExtractRealTime) -> f64 {
|
|
// (ctx.try_real_time().unwrap_or_default() / DAY
|
|
// }
|