Fix Imaginate by porting its JS roundtrip code to graph-based async execution in Rust (#1250)

* Create asynchronous rust imaginate node

* Make a first imaginate request via rust

* Implement parsing of imaginate API result image

* Stop refresh timer from affecting imaginate progress requests

* Add cargo-about clarification for rustls-webpki

* Delete imaginate.ts and all uses of its functions

* Add imaginate img2img feature

* Fix imaginate random seed button

* Fix imaginate ui inferring non-custom resolutions

* Fix the imaginate progress indicator

* Remove ImaginatePreferences from being compiled into node graph

* Regenerate imaginate only when hitting button

* Add ability to terminate imaginate requests

* Add imaginate server check feature

* Do not compile wasm_bindgen bindings in graphite_editor for tests

* Address some review suggestions

- move wasm futures dependency in editor to the future-executor crate
- guard wasm-bindgen in editor behind a `wasm` feature flag
- dont make seed number input a slider
- remove poll_server_check from process_message function beginning
- guard wasm related code behind `cfg(target_arch = "wasm32")` instead
  of `cfg(test)`
- Call the imaginate idle states "Ready" and "Done" instead of "Nothing
  to do"
- Call the imaginate uploading state "Uploading Image" instead of
  "Uploading Input Image"
- Remove the EvalSyncNode

* Fix imaginate host name being restored between graphite instances

also change the progress status texts a bit.

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
nat-rix 2023-06-09 09:03:15 +02:00 committed by Keavon Chambers
parent a1c70c4d90
commit f76b850b9c
35 changed files with 1500 additions and 1326 deletions

View file

@ -11,7 +11,7 @@ use editor::application::Editor;
use editor::consts::{FILE_SAVE_SUFFIX, GRAPHITE_DOCUMENT_VERSION};
use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys;
use editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ScrollDelta, ViewportBounds};
use editor::messages::portfolio::utility_types::{ImaginateServerStatus, Platform};
use editor::messages::portfolio::utility_types::Platform;
use editor::messages::prelude::*;
use graph_craft::document::NodeId;
use graphene_core::raster::color::Color;
@ -586,63 +586,6 @@ impl JsEditorHandle {
}
}
/// Sends the blob URL generated by JS to the Imaginate layer in the respective document
#[wasm_bindgen(js_name = setImaginateImageData)]
pub fn set_imaginate_image_data(&self, document_id: u64, layer_path: Vec<LayerId>, node_path: Vec<NodeId>, image_data: Vec<u8>, width: u32, height: u32) {
let message = PortfolioMessage::ImaginateSetImageData {
document_id,
node_path,
layer_path,
image_data,
width,
height,
};
self.dispatch(message);
}
/// Notifies the Imaginate layer of a new percentage of completion and whether or not it's currently generating
#[wasm_bindgen(js_name = setImaginateGeneratingStatus)]
pub fn set_imaginate_generating_status(&self, document_id: u64, layer_path: Vec<LayerId>, node_path: Vec<NodeId>, percent: Option<f64>, status: String) {
use graph_craft::imaginate_input::ImaginateStatus;
let status = match status.as_str() {
"Idle" => ImaginateStatus::Idle,
"Beginning" => ImaginateStatus::Beginning,
"Uploading" => ImaginateStatus::Uploading(percent.expect("Percent needs to be supplied to set ImaginateStatus::Uploading")),
"Generating" => ImaginateStatus::Generating,
"Terminating" => ImaginateStatus::Terminating,
"Terminated" => ImaginateStatus::Terminated,
_ => panic!("Invalid string from JS for ImaginateStatus, received: {}", status),
};
let percent = if matches!(status, ImaginateStatus::Uploading(_)) { None } else { percent };
let message = PortfolioMessage::ImaginateSetGeneratingStatus {
document_id,
layer_path,
node_path,
percent,
status,
};
self.dispatch(message);
}
/// Notifies the editor that the Imaginate server is available or unavailable
#[wasm_bindgen(js_name = setImaginateServerStatus)]
pub fn set_imaginate_server_status(&self, available: bool) {
let message: Message = match available {
true => PortfolioMessage::ImaginateSetServerStatus {
status: ImaginateServerStatus::Connected,
}
.into(),
false => PortfolioMessage::ImaginateSetServerStatus {
status: ImaginateServerStatus::Unavailable,
}
.into(),
};
self.dispatch(message);
}
/// Sends the blob URL generated by JS to the Imaginate layer in the respective document
#[wasm_bindgen(js_name = renderGraphUsingRasterizedRegionBelowLayer)]
pub fn render_graph_using_rasterized_region_below_layer(
@ -793,6 +736,11 @@ impl JsEditorHandle {
});
frontend_messages.unwrap().unwrap_or_default()
}
#[wasm_bindgen(js_name = injectImaginatePollServerStatus)]
pub fn inject_imaginate_poll_server_status(&self) {
self.dispatch(PortfolioMessage::ImaginatePollServerStatus);
}
}
// Needed to make JsEditorHandle functions pub to Rust.