mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 17:48:11 +08:00
Experimental animation support (#2443)
* Implement experimental time routing to the node graph * Allow toggling live preview with SHIFT + SPACE * Add animation message handler * Fix hotkeys * Fix milisecond node * Adevertize set frame index action * Fix frame index * Fix year calculation * Add comment for why month and day are not exposed * Combine animation nodes and fix animation time implementation * Fix animation time interaction with playback * Add set animation time mode message * Captalize UTC * Fix compiling * Fix crash and add text nodes --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
b98711dbdb
commit
44694ff8d6
@@ -2086,7 +2086,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Text",
|
||||
category: "Vector",
|
||||
category: "Text",
|
||||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
implementation: DocumentNodeImplementation::proto("graphene_std::text::TextNode"),
|
||||
|
||||
@@ -20,6 +20,7 @@ use graphene_core::raster::{
|
||||
use graphene_core::text::Font;
|
||||
use graphene_core::vector::misc::CentroidType;
|
||||
use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
|
||||
use graphene_std::animation::RealTimeMode;
|
||||
use graphene_std::application_io::TextureFrameTable;
|
||||
use graphene_std::transform::Footprint;
|
||||
use graphene_std::vector::VectorDataTable;
|
||||
@@ -165,6 +166,7 @@ pub(crate) fn property_from_type(
|
||||
last.clone()
|
||||
}
|
||||
Some(x) if x == TypeId::of::<BlendMode>() => blend_mode(document_node, node_id, index, name, true),
|
||||
Some(x) if x == TypeId::of::<RealTimeMode>() => real_time_mode(document_node, node_id, index, name, true),
|
||||
Some(x) if x == TypeId::of::<RedGreenBlue>() => color_channel(document_node, node_id, index, name, true),
|
||||
Some(x) if x == TypeId::of::<RedGreenBlueAlpha>() => rgba_channel(document_node, node_id, index, name, true),
|
||||
Some(x) if x == TypeId::of::<NoiseType>() => noise_type(document_node, node_id, index, name, true),
|
||||
@@ -778,6 +780,40 @@ pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Color Channel")
|
||||
}
|
||||
|
||||
pub fn real_time_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
let Some(input) = document_node.inputs.get(index) else {
|
||||
log::warn!("A widget failed to be built because its node's input index is invalid.");
|
||||
return LayoutGroup::Row { widgets: vec![] };
|
||||
};
|
||||
if let Some(&TaggedValue::RealTimeMode(mode)) = input.as_non_exposed_value() {
|
||||
let calculation_modes = [
|
||||
RealTimeMode::Utc,
|
||||
RealTimeMode::Year,
|
||||
RealTimeMode::Hour,
|
||||
RealTimeMode::Minute,
|
||||
RealTimeMode::Second,
|
||||
RealTimeMode::Millisecond,
|
||||
];
|
||||
let mut entries = Vec::with_capacity(calculation_modes.len());
|
||||
for method in calculation_modes {
|
||||
entries.push(
|
||||
MenuListEntry::new(format!("{method:?}"))
|
||||
.label(method.to_string())
|
||||
.on_update(update_value(move |_| TaggedValue::RealTimeMode(method), node_id, index))
|
||||
.on_commit(commit_value),
|
||||
);
|
||||
}
|
||||
let entries = vec![entries];
|
||||
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder(),
|
||||
]);
|
||||
}
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Real Time Mode")
|
||||
}
|
||||
|
||||
pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
let Some(input) = document_node.inputs.get(index) else {
|
||||
|
||||
@@ -115,6 +115,7 @@ pub enum PortfolioMessage {
|
||||
bounds: ExportBounds,
|
||||
transparent_background: bool,
|
||||
},
|
||||
SubmitActiveGraphRender,
|
||||
SubmitGraphRender {
|
||||
document_id: DocumentId,
|
||||
ignore_hash: bool,
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::spreadsheet::SpreadsheetMessageHandler;
|
||||
use super::utility_types::{PanelType, PersistentData};
|
||||
use crate::application::generate_uuid;
|
||||
use crate::consts::DEFAULT_DOCUMENT_NAME;
|
||||
use crate::messages::animation::TimingInformation;
|
||||
use crate::messages::debug::utility_types::MessageLoggingVerbosity;
|
||||
use crate::messages::dialog::simple_dialogs;
|
||||
use crate::messages::frontend::utility_types::FrontendDocumentDetails;
|
||||
@@ -32,6 +33,7 @@ pub struct PortfolioMessageData<'a> {
|
||||
pub preferences: &'a PreferencesMessageHandler,
|
||||
pub current_tool: &'a ToolType,
|
||||
pub message_logging_verbosity: MessageLoggingVerbosity,
|
||||
pub timing_information: TimingInformation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -56,6 +58,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
preferences,
|
||||
current_tool,
|
||||
message_logging_verbosity,
|
||||
timing_information,
|
||||
} = data;
|
||||
|
||||
match message {
|
||||
@@ -306,6 +309,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
let _ = self.executor.submit_node_graph_evaluation(
|
||||
self.documents.get_mut(document_id).expect("Tried to render non-existent document"),
|
||||
ipp.viewport_bounds.size().as_uvec2(),
|
||||
timing_information,
|
||||
inspect_node,
|
||||
true,
|
||||
);
|
||||
@@ -1072,11 +1076,17 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
});
|
||||
}
|
||||
}
|
||||
PortfolioMessage::SubmitActiveGraphRender => {
|
||||
if let Some(document_id) = self.active_document_id {
|
||||
responses.add(PortfolioMessage::SubmitGraphRender { document_id, ignore_hash: false });
|
||||
}
|
||||
}
|
||||
PortfolioMessage::SubmitGraphRender { document_id, ignore_hash } => {
|
||||
let inspect_node = self.inspect_node_id();
|
||||
let result = self.executor.submit_node_graph_evaluation(
|
||||
self.documents.get_mut(&document_id).expect("Tried to render non-existent document"),
|
||||
ipp.viewport_bounds.size().as_uvec2(),
|
||||
timing_information,
|
||||
inspect_node,
|
||||
ignore_hash,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user