Skip to content

Commit b785868

Browse files
authored
Merge branch 'master' into fix-min-max-macro
2 parents 9da8e64 + 4e418bb commit b785868

File tree

80 files changed

+2141
-442
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2141
-442
lines changed

editor/src/dispatcher.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct Dispatcher {
1313

1414
#[derive(Debug, Default)]
1515
pub struct DispatcherMessageHandlers {
16+
animation_message_handler: AnimationMessageHandler,
1617
broadcast_message_handler: BroadcastMessageHandler,
1718
debug_message_handler: DebugMessageHandler,
1819
dialog_message_handler: DialogMessageHandler,
@@ -50,12 +51,9 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
5051
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure),
5152
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
5253
];
53-
const DEBUG_MESSAGE_BLOCK_LIST: &[MessageDiscriminant] = &[
54-
MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(BroadcastEventDiscriminant::AnimationFrame)),
55-
MessageDiscriminant::InputPreprocessor(InputPreprocessorMessageDiscriminant::FrameTimeAdvance),
56-
];
54+
const DEBUG_MESSAGE_BLOCK_LIST: &[MessageDiscriminant] = &[MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(BroadcastEventDiscriminant::AnimationFrame))];
5755
// TODO: Find a way to combine these with the list above. We use strings for now since these are the standard variant names used by multiple messages. But having these also type-checked would be best.
58-
const DEBUG_MESSAGE_ENDING_BLOCK_LIST: &[&str] = &["PointerMove", "PointerOutsideViewport", "Overlays", "Draw"];
56+
const DEBUG_MESSAGE_ENDING_BLOCK_LIST: &[&str] = &["PointerMove", "PointerOutsideViewport", "Overlays", "Draw", "CurrentTime", "Time"];
5957

6058
impl Dispatcher {
6159
pub fn new() -> Self {
@@ -177,6 +175,9 @@ impl Dispatcher {
177175
// Finish loading persistent data from the browser database
178176
queue.add(FrontendMessage::TriggerLoadRestAutoSaveDocuments);
179177
}
178+
Message::Animation(message) => {
179+
self.message_handlers.animation_message_handler.process_message(message, &mut queue, ());
180+
}
180181
Message::Batched(messages) => {
181182
messages.iter().for_each(|message| self.handle_message(message.to_owned(), false));
182183
}
@@ -232,6 +233,8 @@ impl Dispatcher {
232233
let preferences = &self.message_handlers.preferences_message_handler;
233234
let current_tool = &self.message_handlers.tool_message_handler.tool_state.tool_data.active_tool_type;
234235
let message_logging_verbosity = self.message_handlers.debug_message_handler.message_logging_verbosity;
236+
let timing_information = self.message_handlers.animation_message_handler.timing_information();
237+
let animation = &self.message_handlers.animation_message_handler;
235238

236239
self.message_handlers.portfolio_message_handler.process_message(
237240
message,
@@ -241,6 +244,8 @@ impl Dispatcher {
241244
preferences,
242245
current_tool,
243246
message_logging_verbosity,
247+
timing_information,
248+
animation,
244249
},
245250
);
246251
}
@@ -283,6 +288,7 @@ impl Dispatcher {
283288
// TODO: Reduce the number of heap allocations
284289
let mut list = Vec::new();
285290
list.extend(self.message_handlers.dialog_message_handler.actions());
291+
list.extend(self.message_handlers.animation_message_handler.actions());
286292
list.extend(self.message_handlers.input_preprocessor_message_handler.actions());
287293
list.extend(self.message_handlers.key_mapping_message_handler.actions());
288294
list.extend(self.message_handlers.debug_message_handler.actions());
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::messages::prelude::*;
2+
3+
use super::animation_message_handler::AnimationTimeMode;
4+
5+
#[impl_message(Message, Animation)]
6+
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
7+
pub enum AnimationMessage {
8+
ToggleLivePreview,
9+
EnableLivePreview,
10+
DisableLivePreview,
11+
RestartAnimation,
12+
SetFrameIndex(f64),
13+
SetTime(f64),
14+
UpdateTime,
15+
IncrementFrameCounter,
16+
SetAnimationTimeMode(AnimationTimeMode),
17+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
use std::time::Duration;
2+
3+
use crate::messages::prelude::*;
4+
5+
use super::TimingInformation;
6+
7+
#[derive(PartialEq, Clone, Default, Debug, serde::Serialize, serde::Deserialize)]
8+
pub enum AnimationTimeMode {
9+
#[default]
10+
TimeBased,
11+
FrameBased,
12+
}
13+
14+
#[derive(Default, Debug, Clone, PartialEq)]
15+
enum AnimationState {
16+
#[default]
17+
Stopped,
18+
Playing {
19+
start: f64,
20+
},
21+
Paused {
22+
start: f64,
23+
pause_time: f64,
24+
},
25+
}
26+
27+
#[derive(Default, Debug, Clone, PartialEq)]
28+
pub struct AnimationMessageHandler {
29+
/// Used to re-send the UI on the next frame after playback starts
30+
live_preview_recently_zero: bool,
31+
timestamp: f64,
32+
frame_index: f64,
33+
animation_state: AnimationState,
34+
fps: f64,
35+
animation_time_mode: AnimationTimeMode,
36+
}
37+
impl AnimationMessageHandler {
38+
pub(crate) fn timing_information(&self) -> TimingInformation {
39+
let animation_time = self.timestamp - self.animation_start();
40+
let animation_time = match self.animation_time_mode {
41+
AnimationTimeMode::TimeBased => Duration::from_millis(animation_time as u64),
42+
AnimationTimeMode::FrameBased => Duration::from_secs((self.frame_index / self.fps) as u64),
43+
};
44+
TimingInformation { time: self.timestamp, animation_time }
45+
}
46+
47+
pub(crate) fn animation_start(&self) -> f64 {
48+
match self.animation_state {
49+
AnimationState::Stopped => self.timestamp,
50+
AnimationState::Playing { start } => start,
51+
AnimationState::Paused { start, pause_time } => start + self.timestamp - pause_time,
52+
}
53+
}
54+
55+
pub fn is_playing(&self) -> bool {
56+
matches!(self.animation_state, AnimationState::Playing { .. })
57+
}
58+
}
59+
60+
impl MessageHandler<AnimationMessage, ()> for AnimationMessageHandler {
61+
fn process_message(&mut self, message: AnimationMessage, responses: &mut VecDeque<Message>, _data: ()) {
62+
match message {
63+
AnimationMessage::ToggleLivePreview => match self.animation_state {
64+
AnimationState::Stopped => responses.add(AnimationMessage::EnableLivePreview),
65+
AnimationState::Playing { .. } => responses.add(AnimationMessage::DisableLivePreview),
66+
AnimationState::Paused { .. } => responses.add(AnimationMessage::EnableLivePreview),
67+
},
68+
AnimationMessage::EnableLivePreview => {
69+
self.animation_state = AnimationState::Playing { start: self.animation_start() };
70+
71+
// Update the restart and pause/play buttons
72+
responses.add(PortfolioMessage::UpdateDocumentWidgets);
73+
}
74+
AnimationMessage::DisableLivePreview => {
75+
match self.animation_state {
76+
AnimationState::Stopped => (),
77+
AnimationState::Playing { start } => self.animation_state = AnimationState::Paused { start, pause_time: self.timestamp },
78+
AnimationState::Paused { .. } => (),
79+
}
80+
81+
// Update the restart and pause/play buttons
82+
responses.add(PortfolioMessage::UpdateDocumentWidgets);
83+
}
84+
AnimationMessage::SetFrameIndex(frame) => {
85+
self.frame_index = frame;
86+
responses.add(PortfolioMessage::SubmitActiveGraphRender);
87+
// Update the restart and pause/play buttons
88+
responses.add(PortfolioMessage::UpdateDocumentWidgets);
89+
}
90+
AnimationMessage::SetTime(time) => {
91+
self.timestamp = time;
92+
responses.add(AnimationMessage::UpdateTime);
93+
}
94+
AnimationMessage::IncrementFrameCounter => {
95+
if self.is_playing() {
96+
self.frame_index += 1.;
97+
responses.add(AnimationMessage::UpdateTime);
98+
}
99+
}
100+
AnimationMessage::UpdateTime => {
101+
if self.is_playing() {
102+
responses.add(PortfolioMessage::SubmitActiveGraphRender);
103+
104+
if self.live_preview_recently_zero {
105+
// Update the restart and pause/play buttons
106+
responses.add(PortfolioMessage::UpdateDocumentWidgets);
107+
self.live_preview_recently_zero = false;
108+
}
109+
}
110+
}
111+
AnimationMessage::RestartAnimation => {
112+
self.frame_index = 0.;
113+
self.animation_state = match self.animation_state {
114+
AnimationState::Playing { .. } => AnimationState::Playing { start: self.timestamp },
115+
_ => AnimationState::Stopped,
116+
};
117+
self.live_preview_recently_zero = true;
118+
responses.add(PortfolioMessage::SubmitActiveGraphRender);
119+
// Update the restart and pause/play buttons
120+
responses.add(PortfolioMessage::UpdateDocumentWidgets);
121+
}
122+
AnimationMessage::SetAnimationTimeMode(animation_time_mode) => {
123+
self.animation_time_mode = animation_time_mode;
124+
}
125+
}
126+
}
127+
128+
advertise_actions!(AnimationMessageDiscriminant;
129+
ToggleLivePreview,
130+
SetFrameIndex,
131+
RestartAnimation,
132+
);
133+
}

editor/src/messages/animation/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod animation_message;
2+
mod animation_message_handler;
3+
4+
#[doc(inline)]
5+
pub use animation_message::{AnimationMessage, AnimationMessageDiscriminant};
6+
#[doc(inline)]
7+
pub use animation_message_handler::AnimationMessageHandler;
8+
9+
pub use graphene_core::application_io::TimingInformation;

editor/src/messages/frontend/frontend_message.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ pub enum FrontendMessage {
150150
UpdateGraphViewOverlay {
151151
open: bool,
152152
},
153+
UpdateSpreadsheetState {
154+
open: bool,
155+
node: Option<NodeId>,
156+
},
157+
UpdateSpreadsheetLayout {
158+
#[serde(rename = "layoutTarget")]
159+
layout_target: LayoutTarget,
160+
diff: Vec<WidgetDiff>,
161+
},
153162
UpdateImportReorderIndex {
154163
#[serde(rename = "importIndex")]
155164
index: Option<usize>,

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,9 @@ pub fn input_mappings() -> Mapping {
430430
entry!(KeyDown(Digit0); modifiers=[Alt], action_dispatch=DebugMessage::MessageOff),
431431
entry!(KeyDown(Digit1); modifiers=[Alt], action_dispatch=DebugMessage::MessageNames),
432432
entry!(KeyDown(Digit2); modifiers=[Alt], action_dispatch=DebugMessage::MessageContents),
433+
// AnimationMessage
434+
entry!(KeyDown(Space); modifiers=[Shift], action_dispatch=AnimationMessage::ToggleLivePreview),
435+
entry!(KeyDown(Home); modifiers=[Shift], action_dispatch=AnimationMessage::RestartAnimation),
433436
];
434437
let (mut key_up, mut key_down, mut key_up_no_repeat, mut key_down_no_repeat, mut double_click, mut wheel_scroll, mut pointer_move) = mappings;
435438

editor/src/messages/input_mapper/utility_types/input_mouse.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,9 @@ pub struct MouseState {
8888

8989
impl MouseState {
9090
pub fn finish_transaction(&self, drag_start: DVec2, responses: &mut VecDeque<Message>) {
91-
match drag_start.distance(self.position) <= DRAG_THRESHOLD {
92-
true => responses.add(DocumentMessage::AbortTransaction),
93-
false => responses.add(DocumentMessage::EndTransaction),
94-
}
91+
let drag_too_small = drag_start.distance(self.position) <= DRAG_THRESHOLD;
92+
let response = if drag_too_small { DocumentMessage::AbortTransaction } else { DocumentMessage::EndTransaction };
93+
responses.add(response);
9594
}
9695
}
9796

editor/src/messages/input_preprocessor/input_preprocessor_message.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
22
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ViewportBounds};
33
use crate::messages::prelude::*;
4-
use core::time::Duration;
54

65
#[impl_message(Message, InputPreprocessor)]
76
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
@@ -13,6 +12,6 @@ pub enum InputPreprocessorMessage {
1312
PointerDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
1413
PointerMove { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
1514
PointerUp { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
16-
FrameTimeAdvance { timestamp: Duration },
15+
CurrentTime { timestamp: u64 },
1716
WheelScroll { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys },
1817
}

editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct InputPreprocessorMessageData {
1212
#[derive(Debug, Default)]
1313
pub struct InputPreprocessorMessageHandler {
1414
pub frame_time: FrameTimeInfo,
15+
pub time: u64,
1516
pub keyboard: KeyStates,
1617
pub mouse: MouseState,
1718
pub viewport_bounds: ViewportBounds,
@@ -93,8 +94,9 @@ impl MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageData> for
9394

9495
self.translate_mouse_event(mouse_state, false, responses);
9596
}
96-
InputPreprocessorMessage::FrameTimeAdvance { timestamp } => {
97-
self.frame_time.advance_timestamp(timestamp);
97+
InputPreprocessorMessage::CurrentTime { timestamp } => {
98+
responses.add(AnimationMessage::SetTime(timestamp as f64));
99+
self.time = timestamp;
98100
}
99101
InputPreprocessorMessage::WheelScroll { editor_mouse_state, modifier_keys } => {
100102
self.update_states_of_modifier_keys(modifier_keys, keyboard_platform, responses);

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,29 @@ impl LayoutMessageHandler {
4040
LayoutGroup::Section { layout, .. } => {
4141
stack.extend(layout.iter().enumerate().map(|(index, val)| ([widget_path.as_slice(), &[index]].concat(), val)));
4242
}
43+
44+
LayoutGroup::Table { rows } => {
45+
for (row_index, cell) in rows.iter().enumerate() {
46+
for (cell_index, entry) in cell.iter().enumerate() {
47+
// Return if this is the correct ID
48+
if entry.widget_id == widget_id {
49+
widget_path.push(row_index);
50+
widget_path.push(cell_index);
51+
return Some((entry, widget_path));
52+
}
53+
54+
if let Widget::PopoverButton(popover) = &entry.widget {
55+
stack.extend(
56+
popover
57+
.popover_layout
58+
.iter()
59+
.enumerate()
60+
.map(|(child, val)| ([widget_path.as_slice(), &[row_index, cell_index, child]].concat(), val)),
61+
);
62+
}
63+
}
64+
}
65+
}
4366
}
4467
}
4568
None
@@ -405,6 +428,7 @@ impl LayoutMessageHandler {
405428
LayoutTarget::MenuBar => unreachable!("Menu bar is not diffed"),
406429
LayoutTarget::NodeGraphControlBar => FrontendMessage::UpdateNodeGraphControlBarLayout { layout_target, diff },
407430
LayoutTarget::PropertiesSections => FrontendMessage::UpdatePropertyPanelSectionsLayout { layout_target, diff },
431+
LayoutTarget::Spreadsheet => FrontendMessage::UpdateSpreadsheetLayout { layout_target, diff },
408432
LayoutTarget::ToolOptions => FrontendMessage::UpdateToolOptionsLayout { layout_target, diff },
409433
LayoutTarget::ToolShelf => FrontendMessage::UpdateToolShelfLayout { layout_target, diff },
410434
LayoutTarget::WorkingColors => FrontendMessage::UpdateWorkingColorsLayout { layout_target, diff },

0 commit comments

Comments
 (0)