mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-26 04:38:11 +08:00
Update Tauri to v2 and execute only the node graph in native (#2362)
* Migrate tauri app to v2 * Move flake files to sub directory * Remove unused plugins * Backport some of the tauri code * Implement async node graph execution Only move node runtime to native code * Always use gpu feature for tauri * Fix serialization * Add logging filters * Enable native window rendering with vello * Cleanup * Remove unused editor instance * Remove changes from vite config * Remove warnings * Remove unused files * Fix most tests * Cleanup * Apply frontend lint * Readd flake.nix * Fix tests using --all-features * Code review * Enable all backends * Fix monitor node downcast types * Change debug log to a warning * Disable shader passthrough * Cleanup unused imports * Remove warning * Update project setup instructions --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
29479f6e3e
commit
9b23c7e2db
@@ -1,37 +1,16 @@
|
||||
#![cfg_attr(all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows")]
|
||||
|
||||
use graphite_editor::application::Editor;
|
||||
use graphite_editor::messages::prelude::*;
|
||||
|
||||
// use axum::body::StreamBody;
|
||||
// use axum::extract::Path;
|
||||
// use axum::http;
|
||||
// use axum::response::IntoResponse;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use fern::colors::{Color, ColoredLevelConfig};
|
||||
// use http::{Response, StatusCode};
|
||||
use std::cell::RefCell;
|
||||
// use std::collections::HashMap;
|
||||
// use std::sync::Arc;
|
||||
// use std::sync::Mutex;
|
||||
use graphite_editor::application::Editor;
|
||||
use graphite_editor::messages::prelude::*;
|
||||
use graphite_editor::node_graph_executor::GraphRuntimeRequest;
|
||||
use graphite_editor::node_graph_executor::NODE_RUNTIME;
|
||||
use graphite_editor::node_graph_executor::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
thread_local! {
|
||||
static EDITOR: RefCell<Option<Editor>> = const { RefCell::new(None) };
|
||||
}
|
||||
|
||||
// async fn respond_to(id: Path<String>) -> impl IntoResponse {
|
||||
// let builder = Response::builder().header("Access-Control-Allow-Origin", "*").status(StatusCode::OK);
|
||||
|
||||
// let guard = IMAGES.lock().unwrap();
|
||||
// let images = guard;
|
||||
// let image = images.as_ref().unwrap().get(&id.0).unwrap();
|
||||
|
||||
// println!("image: {:#?}", image.path);
|
||||
// let result: Result<Vec<u8>, &str> = Ok((*image.image_data).clone());
|
||||
// let stream = futures::stream::once(async move { result });
|
||||
// builder.body(StreamBody::new(stream)).unwrap()
|
||||
// }
|
||||
static NODE_RUNTIME_IO: Mutex<Option<NodeRuntimeIO>> = const { Mutex::new(None) };
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@@ -42,63 +21,68 @@ async fn main() {
|
||||
fern::Dispatch::new()
|
||||
.chain(std::io::stdout())
|
||||
.level(log::LevelFilter::Trace)
|
||||
.level_for("naga", log::LevelFilter::Error)
|
||||
.level_for("wgpu-hal", log::LevelFilter::Error)
|
||||
.level_for("wgpu_hal", log::LevelFilter::Error)
|
||||
.level_for("wgpu_core", log::LevelFilter::Error)
|
||||
.format(move |out, message, record| {
|
||||
out.finish(format_args!(
|
||||
"[{}]{} {}",
|
||||
"[{}]{} {} {}",
|
||||
// This will color the log level only, not the whole line. Just a touch.
|
||||
colors.color(record.level()),
|
||||
chrono::Utc::now().format("[%Y-%m-%d %H:%M:%S]"),
|
||||
message
|
||||
message,
|
||||
record.module_path().unwrap_or("")
|
||||
))
|
||||
})
|
||||
.apply()
|
||||
.unwrap();
|
||||
|
||||
// *(IMAGES.lock().unwrap()) = Some(HashMap::new());
|
||||
std::thread::spawn(|| loop {
|
||||
futures::executor::block_on(graphite_editor::node_graph_executor::run_node_graph());
|
||||
std::thread::sleep(std::time::Duration::from_millis(16))
|
||||
});
|
||||
graphite_editor::application::set_uuid_seed(0);
|
||||
EDITOR.with(|editor| editor.borrow_mut().replace(Editor::new()));
|
||||
let app = Router::new().route("/", get(|| async { "Hello, World!" }))/*.route("/image/:id", get(respond_to))*/;
|
||||
|
||||
// run it with hyper on localhost:3000
|
||||
let mut runtime_lock = NODE_RUNTIME_IO.lock().unwrap();
|
||||
*runtime_lock = Some(NodeRuntimeIO::new());
|
||||
drop(runtime_lock);
|
||||
|
||||
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
||||
|
||||
// Run it with hyper on localhost:3000
|
||||
tauri::async_runtime::spawn(async {
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
});
|
||||
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![set_random_seed, handle_message])
|
||||
.plugin(tauri_plugin_http::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![poll_node_graph, runtime_message])
|
||||
.setup(|_app| {
|
||||
use tauri::Manager;
|
||||
_app.get_window("main").unwrap().open_devtools();
|
||||
_app.get_webview_window("main").unwrap().open_devtools();
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
#[tauri::command]
|
||||
fn set_random_seed(seed: f64) {
|
||||
graphite_editor::application::set_uuid_seed(seed as u64);
|
||||
fn poll_node_graph() -> String {
|
||||
let vec: Vec<_> = NODE_RUNTIME_IO.lock().as_mut().unwrap().as_mut().unwrap().receive().collect();
|
||||
ron::to_string(&vec).unwrap()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn handle_message(message: String) -> String {
|
||||
let Ok(message) = ron::from_str::<graphite_editor::messages::message::Message>(&message) else {
|
||||
panic!("Error parsing message: {message}")
|
||||
};
|
||||
let responses = EDITOR.with(|editor| {
|
||||
let mut editor = editor.borrow_mut();
|
||||
editor.as_mut().unwrap().handle_message(message)
|
||||
});
|
||||
|
||||
for response in &responses {
|
||||
let serialized = ron::to_string(&response.clone()).unwrap();
|
||||
if let Err(error) = ron::from_str::<FrontendMessage>(&serialized) {
|
||||
log::error!("Error deserializing message: {error}");
|
||||
fn runtime_message(message: String) -> Result<(), String> {
|
||||
let message = match ron::from_str(&message) {
|
||||
Ok(message) => message,
|
||||
Err(e) => {
|
||||
log::error!("Failed to deserialize message: {}\nwith error: {}", message, e);
|
||||
return Err("Failed to deserialize message".into());
|
||||
}
|
||||
}
|
||||
|
||||
// Process any `FrontendMessage` responses resulting from the backend processing the dispatched message
|
||||
let result: Vec<_> = responses.into_iter().collect();
|
||||
|
||||
ron::to_string(&result).expect("Failed to serialize FrontendMessage")
|
||||
};
|
||||
let response = NODE_RUNTIME_IO.lock().as_ref().unwrap().as_ref().unwrap().send(message);
|
||||
response
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user