Skip to content

Commit 3060cd1

Browse files
committed
Code review, refactoring, and test fixes
1 parent c18ca4c commit 3060cd1

9 files changed

Lines changed: 83 additions & 84 deletions

File tree

desktop/src/app.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,11 @@ pub(crate) struct App {
4747
}
4848

4949
impl App {
50-
pub(crate) fn init(wgpu_context: &WgpuContext) {
51-
DesktopWrapper::init(wgpu_context, rand::rng().random());
50+
pub(crate) fn init() {
5251
Window::init();
5352
}
5453

55-
pub(crate) fn new(
54+
pub(crate) fn create(
5655
cef_context: Box<dyn cef::CefContext>,
5756
cef_view_info_sender: Sender<cef::ViewInfoUpdate>,
5857
wgpu_context: WgpuContext,
@@ -80,6 +79,8 @@ impl App {
8079
let mut persistent_data = PersistentData::default();
8180
persistent_data.load_from_disk();
8281

82+
let desktop_wrapper = DesktopWrapper::create(&wgpu_context.clone(), rand::rng().random());
83+
8384
Self {
8485
render_state: None,
8586
wgpu_context,
@@ -93,7 +94,7 @@ impl App {
9394
ui_scale: 1.,
9495
app_event_receiver,
9596
app_event_scheduler,
96-
desktop_wrapper: DesktopWrapper::new(),
97+
desktop_wrapper,
9798
last_ui_update: Instant::now(),
9899
cef_context,
99100
cef_schedule: Some(Instant::now()),

desktop/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,16 @@ pub fn start() {
6666
}
6767
};
6868

69-
let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context());
70-
71-
App::init(&wgpu_context);
69+
// Must be called before event loop initialization or native window integrations will break
70+
App::init();
7271

7372
let event_loop = EventLoop::new().unwrap();
7473
let (app_event_sender, app_event_receiver) = std::sync::mpsc::channel();
7574
let app_event_scheduler = event_loop.create_app_event_scheduler(app_event_sender);
7675

7776
let (cef_view_info_sender, cef_view_info_receiver) = std::sync::mpsc::channel();
7877

78+
let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context());
7979
let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), cef_view_info_receiver);
8080
let cef_context = match cef_context_builder.initialize(cef_handler, cli.disable_ui_acceleration) {
8181
Ok(context) => {
@@ -100,7 +100,7 @@ pub fn start() {
100100
}
101101
};
102102

103-
let mut app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files);
103+
let mut app = App::create(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli.files);
104104

105105
event_loop.run_app(&mut app).unwrap();
106106

desktop/wrapper/src/lib.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,21 @@ pub struct DesktopWrapper {
2727
}
2828

2929
impl DesktopWrapper {
30-
pub fn init(wgpu_context: &WgpuContext, uuid_random_seed: u64) {
30+
pub fn create(wgpu_context: &WgpuContext, uuid_random_seed: u64) -> Self {
31+
let application_io = WasmApplicationIo::new_with_context(wgpu_context.clone());
32+
futures::executor::block_on(graphite_editor::node_graph_executor::replace_application_io(application_io));
33+
3134
#[cfg(target_os = "windows")]
3235
let host = Host::Windows;
3336
#[cfg(target_os = "macos")]
3437
let host = Host::Mac;
3538
#[cfg(target_os = "linux")]
3639
let host = Host::Linux;
3740
let env = Environment { platform: Platform::Desktop, host };
38-
Editor::init(env, uuid_random_seed);
3941

40-
let application_io = WasmApplicationIo::new_with_context(wgpu_context.clone());
41-
futures::executor::block_on(graphite_editor::node_graph_executor::replace_application_io(application_io));
42-
}
43-
44-
pub fn new() -> Self {
45-
Self { editor: Editor::new() }
42+
Self {
43+
editor: Editor::create(env, uuid_random_seed),
44+
}
4645
}
4746

4847
pub fn dispatch(&mut self, message: DesktopWrapperMessage) -> Vec<DesktopFrontendMessage> {
@@ -60,12 +59,6 @@ impl DesktopWrapper {
6059
}
6160
}
6261

63-
impl Default for DesktopWrapper {
64-
fn default() -> Self {
65-
Self::new()
66-
}
67-
}
68-
6962
pub enum NodeGraphExecutionResult {
7063
HasRun(Option<wgpu::Texture>),
7164
NotRun,

editor/src/application.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,24 @@ pub struct Editor {
88
}
99

1010
impl Editor {
11-
pub fn init(environment: Environment, uuid_random_seed: u64) {
11+
pub fn create(environment: Environment, uuid_random_seed: u64) -> Self {
1212
ENVIRONMENT.set(environment).expect("Editor shoud only be initialized once");
13-
graphene_std::uuid::init_rng(uuid_random_seed);
14-
}
13+
graphene_std::uuid::set_uuid_seed(uuid_random_seed);
1514

16-
/// `Editor::init` must be called before this function
17-
pub fn new() -> Self {
1815
Self { dispatcher: Dispatcher::new() }
1916
}
2017

2118
#[cfg(test)]
2219
pub(crate) fn new_local_executor() -> (Self, crate::node_graph_executor::NodeRuntime) {
20+
let _ = ENVIRONMENT.set(*Editor::environment());
21+
graphene_std::uuid::set_uuid_seed(0);
22+
2323
let (runtime, executor) = crate::node_graph_executor::NodeGraphExecutor::new_with_local_runtime();
24-
let dispatcher = Dispatcher::with_executor(executor);
25-
(Self { dispatcher }, runtime)
24+
let editor = Self {
25+
dispatcher: Dispatcher::with_executor(executor),
26+
};
27+
28+
(editor, runtime)
2629
}
2730

2831
pub fn handle_message<T: Into<Message>>(&mut self, message: T) -> Vec<FrontendMessage> {
@@ -35,17 +38,21 @@ impl Editor {
3538
self.dispatcher.poll_node_graph_evaluation(responses)
3639
}
3740
}
38-
impl Default for Editor {
39-
fn default() -> Self {
40-
Self::new()
41-
}
42-
}
4341

4442
static ENVIRONMENT: OnceLock<Environment> = OnceLock::new();
4543
impl Editor {
44+
#[cfg(not(test))]
4645
pub fn environment() -> &'static Environment {
4746
ENVIRONMENT.get().expect("Editor environment accessed before initialization")
4847
}
48+
49+
#[cfg(test)]
50+
pub fn environment() -> &'static Environment {
51+
&Environment {
52+
platform: Platform::Desktop,
53+
host: Host::Linux,
54+
}
55+
}
4956
}
5057

5158
#[derive(Clone, Copy, Debug)]

editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ impl InputPreprocessorMessageHandler {
187187
mod test {
188188
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
189189
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta};
190-
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
191190
use crate::messages::prelude::*;
192191

193192
#[test]

editor/src/test_utils.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use crate::application::Editor;
2-
use crate::application::set_uuid_seed;
32
use crate::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
43
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta, ViewportPosition};
54
use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier;
6-
use crate::messages::portfolio::utility_types::Platform;
75
use crate::messages::prelude::*;
86
use crate::messages::tool::tool_messages::tool_prelude::Key;
97
use crate::messages::tool::utility_types::ToolType;
@@ -25,15 +23,11 @@ pub struct EditorTestUtils {
2523
impl EditorTestUtils {
2624
pub fn create() -> Self {
2725
let _ = env_logger::builder().is_test(true).try_init();
28-
set_uuid_seed(0);
2926

3027
let (mut editor, runtime) = Editor::new_local_executor();
3128

32-
// We have to set this directly instead of using `GlobalsMessage::SetPlatform` because race conditions with multiple tests can cause that message handler to set it more than once, which is a failure.
33-
// It isn't sufficient to guard the message dispatch here with a check if the once_cell is empty, because that isn't atomic and the time between checking and handling the dispatch can let multiple through.
34-
let _ = GLOBAL_PLATFORM.set(Platform::Windows).is_ok();
35-
3629
editor.handle_message(PortfolioMessage::Init);
30+
3731
Self { editor, runtime }
3832
}
3933

frontend/src/editor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// import { panicProxy } from "@graphite/utility-functions/panic-proxy";
22

3-
import type { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
4-
import init, { wasmMemory, receiveNativeMessage, constructEditor } from "@graphite/../wasm/pkg/graphite_wasm";
3+
import { EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
4+
import init, { wasmMemory, receiveNativeMessage } from "@graphite/../wasm/pkg/graphite_wasm";
55
import { type JsMessageType } from "@graphite/messages";
66
import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/subscription-router";
77
import { operatingSystem } from "@graphite/utility-functions/platform";
@@ -45,14 +45,14 @@ export function createEditor(): Editor {
4545
const randomSeed = BigInt(randomSeedFloat);
4646

4747
// Handle: object containing many functions from `editor_api.rs` that are part of the `EditorHandle` struct (generated by wasm-bindgen)
48-
const handle: EditorHandle = constructEditor(operatingSystem(), randomSeed, (messageType: JsMessageType, messageData: Record<string, unknown>) => {
48+
const handle = EditorHandle.create(operatingSystem(), randomSeed, (messageType: JsMessageType, messageData: Record<string, unknown>) => {
4949
// This callback is called by Wasm when a FrontendMessage is received from the Wasm wrapper `EditorHandle`
5050
// We pass along the first two arguments then add our own `raw` and `handle` context for the last two arguments
5151
subscriptions.handleJsMessage(messageType, messageData, raw, handle);
5252
});
5353

5454
// Subscriptions: allows subscribing to messages in JS that are sent from the Wasm backend
55-
const subscriptions: SubscriptionRouter = createSubscriptionRouter();
55+
const subscriptions = createSubscriptionRouter();
5656

5757
// Check if the URL hash fragment has any demo artwork to be loaded
5858
(async () => {

frontend/wasm/src/editor_api.rs

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -79,45 +79,42 @@ impl EditorHandle {
7979
}
8080
}
8181

82-
#[cfg(not(feature = "native"))]
83-
#[wasm_bindgen(js_name = constructEditor)]
84-
pub fn construct_editor(platform: String, uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
85-
Editor::init(
86-
Environment {
87-
platform: Platform::Web,
88-
host: match platform.as_str() {
89-
"Linux" => Host::Linux,
90-
"Mac" => Host::Mac,
91-
"Windows" => Host::Windows,
92-
_ => unreachable!(),
82+
#[wasm_bindgen]
83+
impl EditorHandle {
84+
#[cfg(not(feature = "native"))]
85+
pub fn create(platform: String, uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
86+
let editor = Editor::create(
87+
Environment {
88+
platform: Platform::Web,
89+
host: match platform.as_str() {
90+
"Linux" => Host::Linux,
91+
"Mac" => Host::Mac,
92+
"Windows" => Host::Windows,
93+
_ => unreachable!(),
94+
},
9395
},
94-
},
95-
uuid_random_seed,
96-
);
96+
uuid_random_seed,
97+
);
9798

98-
let editor = Editor::new();
99-
let editor_handle = EditorHandle { frontend_message_handler_callback };
100-
if EDITOR.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor))).is_none() {
101-
log::error!("Attempted to initialize the editor more than once");
102-
}
103-
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
104-
log::error!("Attempted to initialize the editor handle more than once");
99+
let editor_handle = EditorHandle { frontend_message_handler_callback };
100+
if EDITOR.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor))).is_none() {
101+
log::error!("Attempted to initialize the editor more than once");
102+
}
103+
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
104+
log::error!("Attempted to initialize the editor handle more than once");
105+
}
106+
editor_handle
105107
}
106-
editor_handle
107-
}
108108

109-
#[cfg(feature = "native")]
110-
#[wasm_bindgen(js_name = constructEditor)]
111-
pub fn construct_editor(_platform: String, _uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
112-
let editor_handle = EditorHandle { frontend_message_handler_callback };
113-
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
114-
log::error!("Attempted to initialize the editor handle more than once");
109+
#[cfg(feature = "native")]
110+
pub fn create(_platform: String, _uuid_random_seed: u64, frontend_message_handler_callback: js_sys::Function) -> EditorHandle {
111+
let editor_handle = EditorHandle { frontend_message_handler_callback };
112+
if EDITOR_HANDLE.with(|handle| handle.lock().ok().map(|mut guard| *guard = Some(editor_handle.clone()))).is_none() {
113+
log::error!("Attempted to initialize the editor handle more than once");
114+
}
115+
editor_handle
115116
}
116-
editor_handle
117-
}
118117

119-
#[wasm_bindgen]
120-
impl EditorHandle {
121118
// Sends a message to the dispatcher in the Editor Backend
122119
#[cfg(not(feature = "native"))]
123120
fn dispatch<T: Into<Message>>(&self, message: T) {

node-graph/libraries/core-types/src/uuid.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,27 @@ mod u64_string {
4545
mod uuid_generation {
4646
use rand_chacha::ChaCha20Rng;
4747
use rand_chacha::rand_core::{RngCore, SeedableRng};
48+
use std::cell::Cell;
4849
use std::sync::Mutex;
4950

5051
static RNG: Mutex<Option<ChaCha20Rng>> = Mutex::new(None);
52+
thread_local! {
53+
pub static UUID_SEED: Cell<Option<u64>> = const { Cell::new(None) };
54+
}
5155

52-
pub fn init_rng(random_seed: u64) {
53-
let mut lock = RNG.lock().expect("UUID mutex poisoned");
54-
*lock = Some(ChaCha20Rng::seed_from_u64(random_seed));
56+
pub fn set_uuid_seed(random_seed: u64) {
57+
UUID_SEED.with(|seed| seed.set(Some(random_seed)))
5558
}
5659

5760
pub fn generate_uuid() -> u64 {
5861
let Ok(mut lock) = RNG.lock() else { panic!("UUID mutex poisoned") };
59-
let rng = lock.as_mut().expect("UUID generator not initialized. Forgot to call `init_rng`?");
60-
rng.next_u64()
62+
if lock.is_none() {
63+
UUID_SEED.with(|seed| {
64+
let random_seed = seed.get().unwrap_or(42);
65+
*lock = Some(ChaCha20Rng::seed_from_u64(random_seed));
66+
})
67+
}
68+
lock.as_mut().map(ChaCha20Rng::next_u64).expect("UUID mutex poisoned")
6169
}
6270
}
6371

0 commit comments

Comments
 (0)