mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 19:08:05 +08:00
Transform API (#301)
* Enforce cache dirtification * Turn all shapes into one struct * Remove working folder * Remove old shapes * Major restructuring * Refactor Ellipse, Rectangle and ShapeTool * Simplify bounding box calculation for folder * Fix panic in select tool * Refactorselect tool * Refactor Align * Refactor flipping layers * Zoom to fit all * Refactor tools to avoid state keeping * Refactor more tools to use state that is passed along * Fix whitespace + change selection box style * Set viewbox of svg export based on the contents
This commit is contained in:
@@ -117,7 +117,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import { ResponseType, registerResponseHandler, Response, BlendMode, ExpandFolder, LayerPanelEntry } from "@/utilities/response-handler";
|
||||
import { ResponseType, registerResponseHandler, Response, BlendMode, ExpandFolder, UpdateLayer, LayerPanelEntry } from "@/utilities/response-handler";
|
||||
import { SeparatorType } from "@/components/widgets/widgets";
|
||||
|
||||
import LayoutRow from "@/components/layout/LayoutRow.vue";
|
||||
@@ -324,6 +324,22 @@ export default defineComponent({
|
||||
registerResponseHandler(ResponseType.CollapseFolder, (responseData) => {
|
||||
console.log("CollapseFolder: ", responseData);
|
||||
});
|
||||
registerResponseHandler(ResponseType.UpdateLayer, (responseData) => {
|
||||
const updateData = responseData as UpdateLayer;
|
||||
if (updateData) {
|
||||
const responsePath = updateData.path;
|
||||
const responseLayer = updateData.data;
|
||||
|
||||
const index = this.layers.findIndex((layer: LayerPanelEntry) => {
|
||||
const pathLengthsEqual = responsePath.length === layer.path.length;
|
||||
return pathLengthsEqual && responsePath.every((layer_id, i) => layer_id === layer.path[i]);
|
||||
});
|
||||
if (index >= 0) this.layers[index] = responseLayer;
|
||||
|
||||
this.setBlendModeForSelectedLayers();
|
||||
this.setOpacityForSelectedLayers();
|
||||
}
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -20,6 +20,7 @@ export enum ResponseType {
|
||||
SetActiveDocument = "SetActiveDocument",
|
||||
UpdateOpenDocumentsList = "UpdateOpenDocumentsList",
|
||||
UpdateWorkingColors = "UpdateWorkingColors",
|
||||
UpdateLayer = "UpdateLayer",
|
||||
SetCanvasZoom = "SetCanvasZoom",
|
||||
SetCanvasRotation = "SetCanvasRotation",
|
||||
DisplayConfirmationToCloseDocument = "DisplayConfirmationToCloseDocument",
|
||||
@@ -61,6 +62,8 @@ function parseResponse(responseType: string, data: any): Response {
|
||||
return newUpdateOpenDocumentsList(data.UpdateOpenDocumentsList);
|
||||
case "UpdateCanvas":
|
||||
return newUpdateCanvas(data.UpdateCanvas);
|
||||
case "UpdateLayer":
|
||||
return newUpdateLayer(data.UpdateLayer);
|
||||
case "SetCanvasZoom":
|
||||
return newSetCanvasZoom(data.SetCanvasZoom);
|
||||
case "SetCanvasRotation":
|
||||
@@ -168,7 +171,18 @@ export interface CollapseFolder {
|
||||
}
|
||||
function newCollapseFolder(input: any): CollapseFolder {
|
||||
return {
|
||||
path: new BigUint64Array(input.path.map((n: number) => BigInt(n))),
|
||||
path: newPath(input.path),
|
||||
};
|
||||
}
|
||||
|
||||
export interface UpdateLayer {
|
||||
path: BigUint64Array;
|
||||
data: LayerPanelEntry;
|
||||
}
|
||||
function newUpdateLayer(input: any): UpdateLayer {
|
||||
return {
|
||||
path: newPath(input.data.path),
|
||||
data: newLayerPanelEntry(input.data),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -178,7 +192,7 @@ export interface ExpandFolder {
|
||||
}
|
||||
function newExpandFolder(input: any): ExpandFolder {
|
||||
return {
|
||||
path: new BigUint64Array(input.path.map((n: number) => BigInt(n))),
|
||||
path: newPath(input.path),
|
||||
children: input.children.map((child: any) => newLayerPanelEntry(child)),
|
||||
};
|
||||
}
|
||||
@@ -201,6 +215,12 @@ function newSetCanvasRotation(input: any): SetCanvasRotation {
|
||||
};
|
||||
}
|
||||
|
||||
function newPath(input: any): BigUint64Array {
|
||||
// eslint-disable-next-line
|
||||
const u32CombinedPairs = input.map((n: Array<bigint>) => BigInt((BigInt(n[0]) << BigInt(32)) | BigInt(n[1])));
|
||||
return new BigUint64Array(u32CombinedPairs);
|
||||
}
|
||||
|
||||
export enum BlendMode {
|
||||
Normal = "normal",
|
||||
Multiply = "multiply",
|
||||
@@ -266,7 +286,7 @@ function newLayerPanelEntry(input: any): LayerPanelEntry {
|
||||
opacity: newOpacity(input.opacity),
|
||||
layer_type: newLayerType(input.layer_type),
|
||||
layer_data: newLayerData(input.layer_data),
|
||||
path: new BigUint64Array(input.path.map((n: number) => BigInt(n))),
|
||||
path: newPath(input.path),
|
||||
thumbnail: input.thumbnail,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,10 +7,7 @@ use editor_core::input::mouse::ScrollDelta;
|
||||
use editor_core::message_prelude::*;
|
||||
use editor_core::misc::EditorError;
|
||||
use editor_core::tool::{tool_options::ToolOptions, tools, ToolType};
|
||||
use editor_core::{
|
||||
input::mouse::{MouseState, ViewportPosition},
|
||||
LayerId,
|
||||
};
|
||||
use editor_core::{input::mouse::MouseState, LayerId};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
fn convert_error(err: editor_core::EditorError) -> JsValue {
|
||||
@@ -59,44 +56,44 @@ pub fn send_tool_message(tool: String, message: &JsValue) -> Result<(), JsValue>
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn select_document(document: usize) -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::SelectDocument(document)).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::SelectDocument(document)).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_open_documents_list() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::GetOpenDocumentsList).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::GetOpenDocumentsList).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn new_document() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::NewDocument).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::NewDocument).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_document(document: usize) -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseDocument(document)).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::CloseDocument(document)).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_all_documents() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseAllDocuments).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::CloseAllDocuments).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_active_document_with_confirmation() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseActiveDocumentWithConfirmation).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::CloseActiveDocumentWithConfirmation).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_all_documents_with_confirmation() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseAllDocumentsWithConfirmation).map_err(convert_error))
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentsMessage::CloseAllDocumentsWithConfirmation).map_err(convert_error))
|
||||
}
|
||||
|
||||
// TODO: Call event when the panels are resized
|
||||
/// Viewport resized
|
||||
#[wasm_bindgen]
|
||||
pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> {
|
||||
let ev = InputPreprocessorMessage::ViewportResize(ViewportPosition { x: new_width, y: new_height });
|
||||
let ev = InputPreprocessorMessage::ViewportResize((new_width, new_height).into());
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
@@ -106,7 +103,7 @@ pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> {
|
||||
pub fn on_mouse_move(x: u32, y: u32, modifiers: u8) -> Result<(), JsValue> {
|
||||
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
|
||||
// TODO: Convert these screenspace viewport coordinates to canvas coordinates based on the current zoom and pan
|
||||
let ev = InputPreprocessorMessage::MouseMove(ViewportPosition { x, y }, mods);
|
||||
let ev = InputPreprocessorMessage::MouseMove((x, y).into(), mods);
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
@@ -122,18 +119,16 @@ pub fn on_mouse_scroll(delta_x: i32, delta_y: i32, delta_z: i32, modifiers: u8)
|
||||
/// A mouse button depressed within screenspace the bounds of the viewport
|
||||
#[wasm_bindgen]
|
||||
pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
|
||||
let pos = ViewportPosition { x, y };
|
||||
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
|
||||
let ev = InputPreprocessorMessage::MouseDown(MouseState::from_u8_pos(mouse_keys, pos), mods);
|
||||
let ev = InputPreprocessorMessage::MouseDown(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods);
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
/// A mouse button released
|
||||
#[wasm_bindgen]
|
||||
pub fn on_mouse_up(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> {
|
||||
let pos = ViewportPosition { x, y };
|
||||
let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys");
|
||||
let ev = InputPreprocessorMessage::MouseUp(MouseState::from_u8_pos(mouse_keys, pos), mods);
|
||||
let ev = InputPreprocessorMessage::MouseUp(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods);
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
@@ -259,14 +254,14 @@ pub fn export_document() -> Result<(), JsValue> {
|
||||
/// Sets the zoom to the value
|
||||
#[wasm_bindgen]
|
||||
pub fn set_zoom(new_zoom: f64) -> Result<(), JsValue> {
|
||||
let ev = DocumentMessage::SetCanvasZoom(new_zoom);
|
||||
let ev = MovementMessage::SetCanvasZoom(new_zoom);
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
/// Sets the rotation to the new value (in radians)
|
||||
#[wasm_bindgen]
|
||||
pub fn set_rotation(new_radians: f64) -> Result<(), JsValue> {
|
||||
let ev = DocumentMessage::SetCanvasRotation(new_radians);
|
||||
let ev = MovementMessage::SetCanvasRotation(new_radians);
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user