Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion editor/src/messages/animation/animation_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl AnimationMessageHandler {
AnimationTimeMode::TimeBased => Duration::from_millis(animation_time as u64),
AnimationTimeMode::FrameBased => Duration::from_secs((self.frame_index / self.fps) as u64),
};
TimingInformation { time: self.timestamp, animation_time }
TimingInformation { time: self.timestamp, animation_time, frame_number: self.frame_index as u64 }
}

pub(crate) fn animation_start(&self) -> f64 {
Expand Down
1 change: 1 addition & 0 deletions node-graph/graphene-cli/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub async fn export_gif(
time: TimingInformation {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: PR title enforcement

PR title for a new node does not follow the required dedicated format. For new nodes, the rule mandates New node: 'Node Name' (single quotes, Title Case). The current title "Add Frame Number node" should be updated to New node: 'Frame Number'.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At node-graph/graphene-cli/src/export.rs, line 190:

<comment>PR title for a new node does not follow the required dedicated format. For new nodes, the rule mandates `New node: 'Node Name'` (single quotes, Title Case). The current title "Add Frame Number node" should be updated to `New node: 'Frame Number'`.</comment>

<file context>
@@ -187,6 +187,7 @@ pub async fn export_gif(
 			time: TimingInformation {
 				time: animation_time.as_secs_f64(),
 				animation_time,
+				frame_number: frame_idx as u64,
 			},
 			..Default::default()
</file context>

time: animation_time.as_secs_f64(),
animation_time,
frame_number: frame_idx as u64,
},
..Default::default()
};
Expand Down
2 changes: 1 addition & 1 deletion node-graph/interpreted-executor/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<PlatformE
context_features: graphene_std::ContextDependencies {
// We add the extract index annotation here to force the compiler to add a context nullification node before this node so the render context is properly nullified so the render cache node can do its's work
extract: ContextFeatures::INDEX,
inject: ContextFeatures::REAL_TIME | ContextFeatures::ANIMATION_TIME | ContextFeatures::POINTER_POSITION | ContextFeatures::FOOTPRINT | ContextFeatures::VARARGS,
inject: ContextFeatures::REAL_TIME | ContextFeatures::ANIMATION_TIME | ContextFeatures::FRAME_NUMBER | ContextFeatures::POINTER_POSITION | ContextFeatures::FOOTPRINT | ContextFeatures::VARARGS,
},
..Default::default()
},
Expand Down
1 change: 1 addition & 0 deletions node-graph/libraries/application-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub enum ExportFormat {
pub struct TimingInformation {
pub time: f64,
pub animation_time: Duration,
pub frame_number: u64,
}

#[derive(Debug, Default, Clone, Copy, PartialEq, DynAny)]
Expand Down
40 changes: 40 additions & 0 deletions node-graph/libraries/core-types/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub trait ExtractRealTime {
pub trait ExtractAnimationTime {
fn try_animation_time(&self) -> Option<f64>;
}
pub trait ExtractFrameNumber {
fn try_frame_number(&self) -> Option<u64>;
}
pub trait ExtractPointerPosition {
fn try_pointer_position(&self) -> Option<DVec2>;
}
Expand Down Expand Up @@ -60,6 +63,7 @@ pub trait CloneVarArgs: ExtractVarArgs {
pub trait InjectFootprint {}
pub trait InjectRealTime {}
pub trait InjectAnimationTime {}
pub trait InjectFrameNumber {}
pub trait InjectPointerPosition {}
pub trait InjectPosition {}
pub trait InjectIndex {}
Expand All @@ -74,6 +78,7 @@ pub trait ExtractAll:
ExtractFootprint +
ExtractRealTime +
ExtractAnimationTime +
ExtractFrameNumber +
ExtractPointerPosition +
ExtractPosition +
ExtractIndex +
Expand All @@ -84,6 +89,7 @@ impl<
+ ExtractFootprint
+ ExtractRealTime
+ ExtractAnimationTime
+ ExtractFrameNumber
+ ExtractPointerPosition
+ ExtractPosition
+ ExtractIndex
Expand All @@ -99,6 +105,7 @@ impl<
impl<T: Ctx> InjectFootprint for T {}
impl<T: Ctx> InjectRealTime for T {}
impl<T: Ctx> InjectAnimationTime for T {}
impl<T: Ctx> InjectFrameNumber for T {}
impl<T: Ctx> InjectPointerPosition for T {}
impl<T: Ctx> InjectPosition for T {}
impl<T: Ctx> InjectIndex for T {}
Expand All @@ -112,6 +119,7 @@ impl<T: Ctx> InjectVarArgs for T {}
pub trait ModifyFootprint: ExtractFootprint + InjectFootprint {}
pub trait ModifyRealTime: ExtractRealTime + InjectRealTime {}
pub trait ModifyAnimationTime: ExtractAnimationTime + InjectAnimationTime {}
pub trait ModifyFrameNumber: ExtractFrameNumber + InjectFrameNumber {}
pub trait ModifyPointerPosition: ExtractPointerPosition + InjectPointerPosition {}
pub trait ModifyPosition: ExtractPosition + InjectPosition {}
pub trait ModifyIndex: ExtractIndex + InjectIndex {}
Expand All @@ -120,6 +128,7 @@ pub trait ModifyVarArgs: ExtractVarArgs + InjectVarArgs {}
impl<T: Ctx + InjectFootprint + ExtractFootprint> ModifyFootprint for T {}
impl<T: Ctx + InjectRealTime + ExtractRealTime> ModifyRealTime for T {}
impl<T: Ctx + InjectAnimationTime + ExtractAnimationTime> ModifyAnimationTime for T {}
impl<T: Ctx + InjectFrameNumber + ExtractFrameNumber> ModifyFrameNumber for T {}
impl<T: Ctx + InjectPointerPosition + ExtractPointerPosition> ModifyPointerPosition for T {}
impl<T: Ctx + InjectPosition + ExtractPosition> ModifyPosition for T {}
impl<T: Ctx + InjectIndex + ExtractIndex> ModifyIndex for T {}
Expand All @@ -136,13 +145,15 @@ pub enum ContextFeature {
ExtractFootprint,
ExtractRealTime,
ExtractAnimationTime,
ExtractFrameNumber,
ExtractPointerPosition,
ExtractPosition,
ExtractIndex,
ExtractVarArgs,
InjectFootprint,
InjectRealTime,
InjectAnimationTime,
InjectFrameNumber,
InjectPointerPosition,
InjectPosition,
InjectIndex,
Expand All @@ -162,6 +173,7 @@ bitflags! {
const POSITION = 1 << 4;
const INDEX = 1 << 5;
const VARARGS = 1 << 6;
const FRAME_NUMBER = 1 << 7;
}
}

Expand All @@ -177,6 +189,7 @@ impl ContextFeatures {
ContextFeatures::FOOTPRINT => "Footprint",
ContextFeatures::REAL_TIME => "RealTime",
ContextFeatures::ANIMATION_TIME => "AnimationTime",
ContextFeatures::FRAME_NUMBER => "FrameNumber",
ContextFeatures::POINTER_POSITION => "PointerPosition",
ContextFeatures::POSITION => "Position",
ContextFeatures::INDEX => "Index",
Expand Down Expand Up @@ -206,6 +219,7 @@ impl From<&[ContextFeature]> for ContextDependencies {
ContextFeature::ExtractFootprint => ContextFeatures::FOOTPRINT,
ContextFeature::ExtractRealTime => ContextFeatures::REAL_TIME,
ContextFeature::ExtractAnimationTime => ContextFeatures::ANIMATION_TIME,
ContextFeature::ExtractFrameNumber => ContextFeatures::FRAME_NUMBER,
ContextFeature::ExtractPointerPosition => ContextFeatures::POINTER_POSITION,
ContextFeature::ExtractPosition => ContextFeatures::POSITION,
ContextFeature::ExtractIndex => ContextFeatures::INDEX,
Expand All @@ -216,6 +230,7 @@ impl From<&[ContextFeature]> for ContextDependencies {
ContextFeature::InjectFootprint => ContextFeatures::FOOTPRINT,
ContextFeature::InjectRealTime => ContextFeatures::REAL_TIME,
ContextFeature::InjectAnimationTime => ContextFeatures::ANIMATION_TIME,
ContextFeature::InjectFrameNumber => ContextFeatures::FRAME_NUMBER,
ContextFeature::InjectPointerPosition => ContextFeatures::POINTER_POSITION,
ContextFeature::InjectPosition => ContextFeatures::POSITION,
ContextFeature::InjectIndex => ContextFeatures::INDEX,
Expand Down Expand Up @@ -253,6 +268,11 @@ impl<T: ExtractAnimationTime + Sync> ExtractAnimationTime for Option<T> {
self.as_ref().and_then(|x| x.try_animation_time())
}
}
impl<T: ExtractFrameNumber + Sync> ExtractFrameNumber for Option<T> {
fn try_frame_number(&self) -> Option<u64> {
self.as_ref().and_then(|x| x.try_frame_number())
}
}
impl<T: ExtractPointerPosition + Sync> ExtractPointerPosition for Option<T> {
fn try_pointer_position(&self) -> Option<DVec2> {
self.as_ref().and_then(|x| x.try_pointer_position())
Expand Down Expand Up @@ -311,6 +331,11 @@ impl<T: ExtractAnimationTime + Sync> ExtractAnimationTime for Arc<T> {
(**self).try_animation_time()
}
}
impl<T: ExtractFrameNumber + Sync> ExtractFrameNumber for Arc<T> {
fn try_frame_number(&self) -> Option<u64> {
(**self).try_frame_number()
}
}
impl<T: ExtractPointerPosition + Sync> ExtractPointerPosition for Arc<T> {
fn try_pointer_position(&self) -> Option<DVec2> {
(**self).try_pointer_position()
Expand Down Expand Up @@ -446,6 +471,11 @@ impl ExtractAnimationTime for OwnedContextImpl {
self.animation_time
}
}
impl ExtractFrameNumber for OwnedContextImpl {
fn try_frame_number(&self) -> Option<u64> {
self.frame_number
}
}
impl ExtractPointerPosition for OwnedContextImpl {
fn try_pointer_position(&self) -> Option<DVec2> {
self.pointer_position
Expand Down Expand Up @@ -517,6 +547,7 @@ pub struct OwnedContextImpl {
footprint: Option<Footprint>,
real_time: Option<f64>,
animation_time: Option<f64>,
frame_number: Option<u64>,
pointer_position: Option<DVec2>,
position: Option<Vec<DVec2>>,
// This could be converted into a single enum to save extra bytes
Expand All @@ -531,6 +562,7 @@ impl std::fmt::Debug for OwnedContextImpl {
.field("footprint", &self.footprint)
.field("real_time", &self.real_time)
.field("animation_time", &self.animation_time)
.field("frame_number", &self.frame_number)
.field("pointer_position", &self.pointer_position)
.field("index", &self.index)
.field("varargs_len", &self.varargs.as_ref().map(|x| x.len()))
Expand All @@ -550,6 +582,7 @@ impl graphene_hash::CacheHash for OwnedContextImpl {
self.footprint.cache_hash(state);
self.real_time.cache_hash(state);
self.animation_time.cache_hash(state);
self.frame_number.cache_hash(state);
self.pointer_position.cache_hash(state);
self.position.cache_hash(state);
self.index.cache_hash(state);
Expand All @@ -575,6 +608,7 @@ impl OwnedContextImpl {
let footprint = bitflags.contains(ContextFeatures::FOOTPRINT).then(|| value.try_footprint().copied()).flatten();
let real_time = bitflags.contains(ContextFeatures::REAL_TIME).then(|| value.try_real_time()).flatten();
let animation_time = bitflags.contains(ContextFeatures::ANIMATION_TIME).then(|| value.try_animation_time()).flatten();
let frame_number = bitflags.contains(ContextFeatures::FRAME_NUMBER).then(|| value.try_frame_number()).flatten();
let pointer_position = bitflags.contains(ContextFeatures::POINTER_POSITION).then(|| value.try_pointer_position()).flatten();
let position = bitflags.contains(ContextFeatures::POSITION).then(|| value.try_position()).flatten().map(|x| x.collect());
let index = bitflags.contains(ContextFeatures::INDEX).then(|| value.try_index()).flatten().map(|x| x.collect());
Expand All @@ -584,6 +618,7 @@ impl OwnedContextImpl {
footprint,
real_time,
animation_time,
frame_number,
pointer_position,
position,
index,
Expand All @@ -597,6 +632,7 @@ impl OwnedContextImpl {
footprint: None,
real_time: None,
animation_time: None,
frame_number: None,
pointer_position: None,
position: None,
index: None,
Expand Down Expand Up @@ -646,6 +682,10 @@ impl OwnedContextImpl {
self.animation_time = Some(animation_time);
self
}
pub fn with_frame_number(mut self, frame_number: u64) -> Self {
self.frame_number = Some(frame_number);
self
}
pub fn with_pointer_position(mut self, pointer_position: DVec2) -> Self {
self.pointer_position = Some(pointer_position);
self
Expand Down
2 changes: 2 additions & 0 deletions node-graph/node-macro/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,15 @@ fn parse_context_feature_idents(ty: &Type) -> Vec<Ident> {
"ExtractFootprint"
| "ExtractRealTime"
| "ExtractAnimationTime"
| "ExtractFrameNumber"
| "ExtractPointerPosition"
| "ExtractPosition"
| "ExtractIndex"
| "ExtractVarArgs"
| "InjectFootprint"
| "InjectRealTime"
| "InjectAnimationTime"
| "InjectFrameNumber"
| "InjectPointerPosition"
| "InjectPosition"
| "InjectIndex"
Expand Down
11 changes: 10 additions & 1 deletion node-graph/nodes/gcore/src/animation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core_types::list::List;
use core_types::transform::Footprint;
use core_types::{CacheHash, CloneVarArgs, Color, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
use core_types::{CacheHash, CloneVarArgs, Color, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractFrameNumber, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
use glam::{DAffine2, DVec2};
use graphic_types::vector_types::GradientStops;
use graphic_types::{Artboard, Graphic, Vector};
Expand Down Expand Up @@ -48,6 +48,15 @@ fn real_time(
}
}

/// Produces the number of the current frame, where 0 is the first frame.
#[node_macro::node(category("Animation"))]
fn frame_number(
ctx: impl Ctx + ExtractFrameNumber,
_primary: (),
) -> f64 {
ctx.try_frame_number().unwrap_or_default() as f64
}

/// Produces the time, in seconds on the timeline, since the beginning of animation playback.
#[node_macro::node(category("Animation"))]
fn animation_time(
Expand Down
8 changes: 6 additions & 2 deletions node-graph/nodes/gstd/src/render_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use core_types::math::bbox::AxisAlignedBbox;
use core_types::transform::{Footprint, RenderQuality, Transform};
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractAnimationTime, ExtractFrameNumber, ExtractPointerPosition, ExtractRealTime, OwnedContextImpl};
use glam::{DAffine2, DVec2, IVec2, UVec2};
use graph_craft::application_io::PlatformEditorApi;
use graph_craft::document::value::RenderOutput;
Expand Down Expand Up @@ -48,6 +48,7 @@ pub struct CacheKey {
pub override_paint_order: bool,
pub animation_time_ms: i64,
pub real_time_ms: i64,
pub frame_number: u64,
pub pointer: [u8; 16],
}

Expand All @@ -66,6 +67,7 @@ impl CacheKey {
override_paint_order: bool,
animation_time: f64,
real_time: f64,
frame_number: u64,
pointer: Option<DVec2>,
) -> Self {
let pointer_bytes = pointer
Expand All @@ -92,6 +94,7 @@ impl CacheKey {
override_paint_order,
animation_time_ms: (animation_time * 1000.0).round() as i64,
real_time_ms: (real_time * 1000.0).round() as i64,
frame_number,
pointer: pointer_bytes,
}
}
Expand Down Expand Up @@ -326,7 +329,7 @@ fn flood_fill(start: &TileCoord, tile_set: &HashSet<TileCoord>, visited: &mut Ha

#[node_macro::node(category(""))]
pub async fn render_output_cache<'a: 'n>(
ctx: impl Ctx + ExtractAll + CloneVarArgs + ExtractRealTime + ExtractAnimationTime + ExtractPointerPosition + Sync,
ctx: impl Ctx + ExtractAll + CloneVarArgs + ExtractRealTime + ExtractAnimationTime + ExtractFrameNumber + ExtractPointerPosition + Sync,
editor_api: &'a PlatformEditorApi,
data: impl Node<Context<'static>, Output = RenderOutput> + Send + Sync,
#[data] tile_cache: TileCache,
Expand Down Expand Up @@ -371,6 +374,7 @@ pub async fn render_output_cache<'a: 'n>(
render_params.override_paint_order,
ctx.try_animation_time().unwrap_or(0.0),
ctx.try_real_time().unwrap_or(0.0),
ctx.try_frame_number().unwrap_or(0),
ctx.try_pointer_position(),
);

Expand Down
1 change: 1 addition & 0 deletions node-graph/nodes/gstd/src/render_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ async fn create_context<'a: 'n>(
.with_footprint(footprint)
.with_real_time(render_config.time.time)
.with_animation_time(render_config.time.animation_time.as_secs_f64())
.with_frame_number(render_config.time.frame_number)
.with_pointer_position(render_config.pointer)
.with_vararg(Box::new(render_params))
.into_context();
Expand Down