mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 10:58:04 +08:00
Brush tool live preview (#1116)
* Disable vector preview for brush tool * Fix brush preview * Fix warping * Left and right square brackets to change size * Add linear interpolation * Modfiy existing selected brush layer * Resolve warnings --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev> Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
parent
69f6ed3a11
commit
f271964bf8
@@ -98,11 +98,13 @@ fn handle_message(message: String) -> String {
|
||||
for image in image_data {
|
||||
let path = image.path.clone();
|
||||
let mime = image.mime.clone();
|
||||
let transform = image.transform.clone();
|
||||
images.insert(format!("{:?}_{}", &image.path, document_id), image);
|
||||
stub_data.push(FrontendImageData {
|
||||
path,
|
||||
mime,
|
||||
image_data: Arc::new(Vec::new()),
|
||||
transform,
|
||||
});
|
||||
}
|
||||
FrontendMessage::UpdateImageData { document_id, image_data: stub_data }
|
||||
|
||||
@@ -529,6 +529,7 @@
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
opacity: 1;
|
||||
color: inherit;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ export function createPortfolioState(editor: Editor) {
|
||||
image.src = blobURL;
|
||||
await image.decode();
|
||||
|
||||
editor.instance.setImageBlobURL(updateImageData.documentId, element.path, blobURL, image.naturalWidth, image.naturalHeight);
|
||||
editor.instance.setImageBlobURL(updateImageData.documentId, element.path, blobURL, image.naturalWidth, image.naturalHeight, element.transform);
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerNodeGraphFrameGenerate, async (triggerNodeGraphFrameGenerate) => {
|
||||
|
||||
@@ -11,7 +11,7 @@ export type Editor = Readonly<ReturnType<typeof createEditor>>;
|
||||
let wasmImport: WasmRawInstance | undefined;
|
||||
let editorInstance: WasmEditorInstance | undefined;
|
||||
|
||||
export async function updateImage(path: BigUint64Array, mime: string, imageData: Uint8Array, documentId: bigint): Promise<void> {
|
||||
export async function updateImage(path: BigUint64Array, mime: string, imageData: Uint8Array, transform: Float64Array, documentId: bigint): Promise<void> {
|
||||
const blob = new Blob([imageData], { type: mime });
|
||||
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
@@ -21,7 +21,7 @@ export async function updateImage(path: BigUint64Array, mime: string, imageData:
|
||||
image.src = blobURL;
|
||||
await image.decode();
|
||||
|
||||
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight);
|
||||
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight,transform);
|
||||
}
|
||||
|
||||
export async function fetchImage(path: BigUint64Array, mime: string, documentId: bigint, url: string): Promise<void> {
|
||||
@@ -35,7 +35,7 @@ export async function fetchImage(path: BigUint64Array, mime: string, documentId:
|
||||
image.src = blobURL;
|
||||
await image.decode();
|
||||
|
||||
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight);
|
||||
editorInstance?.setImageBlobURL(documentId, path, blobURL, image.naturalWidth, image.naturalHeight, undefined);
|
||||
}
|
||||
|
||||
const tauri = "__TAURI_METADATA__" in window && import("@tauri-apps/api");
|
||||
|
||||
@@ -768,6 +768,8 @@ export class ImaginateImageData {
|
||||
readonly mime!: string;
|
||||
|
||||
readonly imageData!: Uint8Array;
|
||||
|
||||
readonly transform!: Float64Array ;
|
||||
}
|
||||
|
||||
export class DisplayDialogDismiss extends JsMessage {}
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn set_random_seed(seed: u64) {
|
||||
/// This avoids creating a json with a list millions of numbers long.
|
||||
#[wasm_bindgen(module = "@graphite/wasm-communication/editor")]
|
||||
extern "C" {
|
||||
fn updateImage(path: Vec<u64>, mime: String, imageData: &[u8], document_id: u64);
|
||||
fn updateImage(path: Vec<u64>, mime: String, imageData: &[u8], transform: js_sys::Float64Array, document_id: u64);
|
||||
fn fetchImage(path: Vec<u64>, mime: String, document_id: u64, identifier: String);
|
||||
//fn dispatchTauri(message: String) -> String;
|
||||
fn dispatchTauri(message: String);
|
||||
@@ -114,7 +114,16 @@ impl JsEditorHandle {
|
||||
if let FrontendMessage::UpdateImageData { document_id, image_data } = message {
|
||||
for image in image_data {
|
||||
#[cfg(not(feature = "tauri"))]
|
||||
updateImage(image.path, image.mime, &image.image_data, document_id);
|
||||
{
|
||||
let transform = if let Some(transform_val) = image.transform {
|
||||
let transform = js_sys::Float64Array::new_with_length(6);
|
||||
transform.copy_from(&transform_val);
|
||||
transform
|
||||
} else {
|
||||
js_sys::Float64Array::default()
|
||||
};
|
||||
updateImage(image.path, image.mime, &image.image_data, transform, document_id);
|
||||
}
|
||||
#[cfg(feature = "tauri")]
|
||||
fetchImage(image.path.clone(), image.mime, document_id, format!("http://localhost:3001/image/{:?}_{}", &image.path, document_id));
|
||||
}
|
||||
@@ -495,15 +504,22 @@ impl JsEditorHandle {
|
||||
|
||||
/// Sends the blob URL generated by JS to the Image layer
|
||||
#[wasm_bindgen(js_name = setImageBlobURL)]
|
||||
pub fn set_image_blob_url(&self, document_id: u64, layer_path: Vec<LayerId>, blob_url: String, width: f64, height: f64) {
|
||||
pub fn set_image_blob_url(&self, document_id: u64, layer_path: Vec<LayerId>, blob_url: String, width: f64, height: f64, transform: Option<js_sys::Float64Array>) {
|
||||
let resolution = (width, height);
|
||||
let message = PortfolioMessage::SetImageBlobUrl {
|
||||
document_id,
|
||||
layer_path,
|
||||
layer_path: layer_path.clone(),
|
||||
blob_url,
|
||||
resolution,
|
||||
};
|
||||
self.dispatch(message);
|
||||
|
||||
if let Some(array) = transform.filter(|array| array.length() == 6) {
|
||||
let mut transform: [f64; 6] = [0.; 6];
|
||||
array.copy_to(&mut transform);
|
||||
let message = document_legacy::Operation::SetLayerTransform { path: layer_path, transform };
|
||||
self.dispatch(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the blob URL generated by JS to the Imaginate layer in the respective document
|
||||
|
||||
Reference in New Issue
Block a user