mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-09-14 16:55:01 +00:00
Hook up layer tree structure with frontend (#372)
* Hook up layer tree structure with frontend (decoding and Vue are WIP) * Fix off by one error * Avoid leaking memory * Parse layer structure into list of layers * Fix thumbnail updates * Correctly popagate deletions * Fix selection state in layer tree * Respect expansion during root serialization * Allow expanding of subfolders * Fix arrow direction Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
parent
c5f44a8c1d
commit
225b46300d
19 changed files with 15777 additions and 336 deletions
|
@ -18,8 +18,7 @@ export enum ResponseType {
|
|||
ExportDocument = "ExportDocument",
|
||||
SaveDocument = "SaveDocument",
|
||||
OpenDocumentBrowse = "OpenDocumentBrowse",
|
||||
ExpandFolder = "ExpandFolder",
|
||||
CollapseFolder = "CollapseFolder",
|
||||
DisplayFolderTreeStructure = "DisplayFolderTreeStructure",
|
||||
UpdateLayer = "UpdateLayer",
|
||||
SetActiveTool = "SetActiveTool",
|
||||
SetActiveDocument = "SetActiveDocument",
|
||||
|
@ -56,10 +55,8 @@ function parseResponse(responseType: string, data: any): Response {
|
|||
switch (responseType) {
|
||||
case "DocumentChanged":
|
||||
return newDocumentChanged(data.DocumentChanged);
|
||||
case "CollapseFolder":
|
||||
return newCollapseFolder(data.CollapseFolder);
|
||||
case "ExpandFolder":
|
||||
return newExpandFolder(data.ExpandFolder);
|
||||
case "DisplayFolderTreeStructure":
|
||||
return newDisplayFolderTreeStructure(data.DisplayFolderTreeStructure);
|
||||
case "SetActiveTool":
|
||||
return newSetActiveTool(data.SetActiveTool);
|
||||
case "SetActiveDocument":
|
||||
|
@ -97,7 +94,7 @@ function parseResponse(responseType: string, data: any): Response {
|
|||
}
|
||||
}
|
||||
|
||||
export type Response = SetActiveTool | UpdateCanvas | UpdateScrollbars | DocumentChanged | CollapseFolder | ExpandFolder | UpdateWorkingColors | SetCanvasZoom | SetCanvasRotation;
|
||||
export type Response = SetActiveTool | UpdateCanvas | UpdateScrollbars | UpdateLayer | DocumentChanged | DisplayFolderTreeStructure | UpdateWorkingColors | SetCanvasZoom | SetCanvasRotation;
|
||||
|
||||
export interface UpdateOpenDocumentsList {
|
||||
open_documents: Array<string>;
|
||||
|
@ -239,13 +236,61 @@ function newDocumentChanged(_: any): DocumentChanged {
|
|||
return {};
|
||||
}
|
||||
|
||||
export interface CollapseFolder {
|
||||
path: BigUint64Array;
|
||||
export interface DisplayFolderTreeStructure {
|
||||
layerId: BigInt;
|
||||
children: DisplayFolderTreeStructure[];
|
||||
}
|
||||
function newCollapseFolder(input: any): CollapseFolder {
|
||||
return {
|
||||
path: newPath(input.path),
|
||||
};
|
||||
function newDisplayFolderTreeStructure(input: any): DisplayFolderTreeStructure {
|
||||
const { ptr, len } = input.data_buffer;
|
||||
const wasmMemoryBuffer = (window as any).wasmMemory().buffer;
|
||||
|
||||
// Decode the folder structure encoding
|
||||
const encoding = new DataView(wasmMemoryBuffer, ptr, len);
|
||||
|
||||
// The structure section indicates how to read through the upcoming layer list and assign depths to each layer
|
||||
const structureSectionLength = Number(encoding.getBigUint64(0, true));
|
||||
const structureSectionMsbSigned = new DataView(wasmMemoryBuffer, ptr + 8, structureSectionLength * 8);
|
||||
|
||||
// The layer IDs section lists each layer ID sequentially in the tree, as it will show up in the panel
|
||||
const layerIdsSection = new DataView(wasmMemoryBuffer, ptr + 8 + structureSectionLength * 8);
|
||||
|
||||
let layersEncountered = 0;
|
||||
let currentFolder: DisplayFolderTreeStructure = { layerId: BigInt(-1), children: [] };
|
||||
const currentFolderStack = [currentFolder];
|
||||
|
||||
for (let i = 0; i < structureSectionLength; i += 1) {
|
||||
const msbSigned = structureSectionMsbSigned.getBigUint64(i * 8, true);
|
||||
const msbMask = BigInt(1) << BigInt(63);
|
||||
|
||||
// Set the MSB to 0 to clear the sign and then read the number as usual
|
||||
const numberOfLayersAtThisDepth = msbSigned & ~msbMask;
|
||||
|
||||
// Store child folders in the current folder (until we are interrupted by an indent)
|
||||
for (let j = 0; j < numberOfLayersAtThisDepth; j += 1) {
|
||||
const layerId = layerIdsSection.getBigUint64(layersEncountered * 8, true);
|
||||
layersEncountered += 1;
|
||||
|
||||
const childLayer = { layerId, children: [] };
|
||||
currentFolder.children.push(childLayer);
|
||||
}
|
||||
|
||||
// Check the sign of the MSB, where a 1 is a negative (outward) indent
|
||||
const subsequentDirectionOfDepthChange = (msbSigned & msbMask) === BigInt(0);
|
||||
// debugger;
|
||||
// Inward
|
||||
if (subsequentDirectionOfDepthChange) {
|
||||
currentFolderStack.push(currentFolder);
|
||||
currentFolder = currentFolder.children[currentFolder.children.length - 1];
|
||||
}
|
||||
// Outward
|
||||
else {
|
||||
const popped = currentFolderStack.pop();
|
||||
if (!popped) throw Error("Too many negative indents in the folder structure");
|
||||
if (popped) currentFolder = popped;
|
||||
}
|
||||
}
|
||||
|
||||
return currentFolder;
|
||||
}
|
||||
|
||||
export interface UpdateLayer {
|
||||
|
@ -259,17 +304,6 @@ function newUpdateLayer(input: any): UpdateLayer {
|
|||
};
|
||||
}
|
||||
|
||||
export interface ExpandFolder {
|
||||
path: BigUint64Array;
|
||||
children: Array<LayerPanelEntry>;
|
||||
}
|
||||
function newExpandFolder(input: any): ExpandFolder {
|
||||
return {
|
||||
path: newPath(input.path),
|
||||
children: input.children.map((child: any) => newLayerPanelEntry(child)),
|
||||
};
|
||||
}
|
||||
|
||||
export interface SetCanvasZoom {
|
||||
new_zoom: number;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue