mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-26 10:18:12 +08:00
Move node graph from panel to overlay on viewport
This commit is contained in:
@@ -20,11 +20,13 @@
|
||||
UpdateMouseCursor,
|
||||
UpdateDocumentNodeRender,
|
||||
UpdateDocumentTransform,
|
||||
TriggerGraphViewOverlay,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
|
||||
import EyedropperPreview, { ZOOM_WINDOW_DIMENSIONS } from "@graphite/components/floating-menus/EyedropperPreview.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import Graph from "@graphite/components/views/Graph.svelte";
|
||||
import CanvasRuler from "@graphite/components/widgets/metrics/CanvasRuler.svelte";
|
||||
import PersistentScrollbar from "@graphite/components/widgets/metrics/PersistentScrollbar.svelte";
|
||||
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
|
||||
@@ -38,6 +40,9 @@
|
||||
const editor = getContext<Editor>("editor");
|
||||
const document = getContext<DocumentState>("document");
|
||||
|
||||
// Graph view overlay
|
||||
let graphViewOverlayOpen = false;
|
||||
|
||||
// Interactive text editing
|
||||
let textInput: undefined | HTMLDivElement = undefined;
|
||||
let showTextInput: boolean;
|
||||
@@ -135,6 +140,7 @@
|
||||
// Replace the placeholders with the actual canvas elements
|
||||
placeholders.forEach((placeholder) => {
|
||||
const canvasName = placeholder.getAttribute("data-canvas-placeholder");
|
||||
if (!canvasName) return;
|
||||
// Get the canvas element from the global storage
|
||||
const canvas = (window as any).imageCanvases[canvasName];
|
||||
placeholder.replaceWith(canvas);
|
||||
@@ -332,6 +338,11 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Show or hide the graph view overlay
|
||||
editor.subscriptions.subscribeJsMessage(TriggerGraphViewOverlay, (triggerGraphViewOverlay) => {
|
||||
graphViewOverlayOpen = triggerGraphViewOverlay.open;
|
||||
});
|
||||
|
||||
// Update rendered SVGs
|
||||
editor.subscriptions.subscribeJsMessage(UpdateDocumentArtwork, async (data) => {
|
||||
await tick();
|
||||
@@ -425,23 +436,30 @@
|
||||
</script>
|
||||
|
||||
<LayoutCol class="document">
|
||||
<LayoutRow class="options-bar" scrollableX={true}>
|
||||
<WidgetLayout layout={$document.documentModeLayout} />
|
||||
<WidgetLayout layout={$document.toolOptionsLayout} />
|
||||
<LayoutRow class="options-bar" classes={{ "for-graph": graphViewOverlayOpen }} scrollableX={true}>
|
||||
{#if !graphViewOverlayOpen}
|
||||
<WidgetLayout layout={$document.documentModeLayout} />
|
||||
<WidgetLayout layout={$document.toolOptionsLayout} />
|
||||
|
||||
<LayoutRow class="spacer" />
|
||||
<LayoutRow class="spacer" />
|
||||
|
||||
<WidgetLayout layout={$document.documentBarLayout} />
|
||||
<WidgetLayout layout={$document.documentBarLayout} />
|
||||
{:else}
|
||||
<WidgetLayout layout={$document.nodeGraphBarLayout} />
|
||||
{/if}
|
||||
</LayoutRow>
|
||||
<LayoutRow class="shelf-and-viewport">
|
||||
<LayoutCol class="shelf">
|
||||
<LayoutCol class="tools" scrollableY={true}>
|
||||
<WidgetLayout layout={$document.toolShelfLayout} />
|
||||
</LayoutCol>
|
||||
{#if !graphViewOverlayOpen}
|
||||
<LayoutCol class="tools" scrollableY={true}>
|
||||
<WidgetLayout layout={$document.toolShelfLayout} />
|
||||
</LayoutCol>
|
||||
{/if}
|
||||
|
||||
<LayoutCol class="spacer" />
|
||||
|
||||
<LayoutCol class="working-colors">
|
||||
<LayoutCol class="widgets-below-shelf">
|
||||
<WidgetLayout layout={$document.graphViewOverlayButtonLayout} />
|
||||
<WidgetLayout layout={$document.workingColorsLayout} />
|
||||
</LayoutCol>
|
||||
</LayoutCol>
|
||||
@@ -485,6 +503,9 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="graph-view" class:open={graphViewOverlayOpen} style:--fade-artwork="80%">
|
||||
<Graph />
|
||||
</div>
|
||||
</LayoutCol>
|
||||
<LayoutCol class="bar-area right-scrollbar">
|
||||
<PersistentScrollbar
|
||||
@@ -521,6 +542,12 @@
|
||||
.spacer {
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
&.for-graph .widget-layout {
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.shelf-and-viewport {
|
||||
@@ -557,21 +584,30 @@
|
||||
|
||||
.spacer {
|
||||
flex: 1 0 auto;
|
||||
min-height: 8px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.working-colors {
|
||||
.widgets-below-shelf {
|
||||
flex: 0 0 auto;
|
||||
|
||||
.widget-row {
|
||||
min-height: 0;
|
||||
.widget-layout:first-of-type {
|
||||
height: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.swatch-pair {
|
||||
margin: 0;
|
||||
}
|
||||
.widget-layout:last-of-type {
|
||||
height: auto;
|
||||
|
||||
.icon-button {
|
||||
--widget-height: 0;
|
||||
.widget-row {
|
||||
min-height: 0;
|
||||
|
||||
.swatch-pair {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
--widget-height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -580,11 +616,6 @@
|
||||
.viewport {
|
||||
flex: 1 1 100%;
|
||||
|
||||
.canvas-area {
|
||||
flex: 1 1 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bar-area {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
@@ -602,51 +633,89 @@
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
background: var(--color-2-mildblack);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// Allows the SVG to be placed at explicit integer values of width and height to prevent non-pixel-perfect SVG scaling
|
||||
.canvas-area {
|
||||
flex: 1 1 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
// Fallback values if JS hasn't set these to integers yet
|
||||
.canvas {
|
||||
background: var(--color-2-mildblack);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// Allows dev tools to select the artwork without being blocked by the SVG containers
|
||||
pointer-events: none;
|
||||
// Allows the SVG to be placed at explicit integer values of width and height to prevent non-pixel-perfect SVG scaling
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
canvas {
|
||||
svg {
|
||||
position: absolute;
|
||||
// Fallback values if JS hasn't set these to integers yet
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// Allows dev tools to select the artwork without being blocked by the SVG containers
|
||||
pointer-events: none;
|
||||
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// Prevent inheritance from reaching the child elements
|
||||
> * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent inheritance from reaching the child elements
|
||||
> * {
|
||||
pointer-events: auto;
|
||||
.text-input div {
|
||||
cursor: text;
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
white-space: pre-wrap;
|
||||
display: inline-block;
|
||||
// Workaround to force Chrome to display the flashing text entry cursor when text is empty
|
||||
padding-left: 1px;
|
||||
margin-left: -1px;
|
||||
|
||||
&:focus {
|
||||
border: none;
|
||||
outline: none; // Ok for contenteditable element
|
||||
margin: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-input div {
|
||||
cursor: text;
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
white-space: pre-wrap;
|
||||
display: inline-block;
|
||||
// Workaround to force Chrome to display the flashing text entry cursor when text is empty
|
||||
padding-left: 1px;
|
||||
margin-left: -1px;
|
||||
.graph-view {
|
||||
pointer-events: none;
|
||||
transition: opacity 0.1s ease-in-out;
|
||||
opacity: 0;
|
||||
|
||||
&:focus {
|
||||
border: none;
|
||||
outline: none; // Ok for contenteditable element
|
||||
margin: -1px;
|
||||
&.open {
|
||||
cursor: auto;
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--color-2-mildblack);
|
||||
opacity: var(--fade-artwork);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-artwork,
|
||||
.graph {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+478
-522
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
import Document from "@graphite/components/panels/Document.svelte";
|
||||
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
|
||||
import LayerTree from "@graphite/components/panels/LayerTree.svelte";
|
||||
import NodeGraph from "@graphite/components/panels/NodeGraph.svelte";
|
||||
import PopoverButton from "@graphite/components/widgets/buttons/PopoverButton.svelte";
|
||||
import Properties from "@graphite/components/panels/Properties.svelte";
|
||||
import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte";
|
||||
@@ -10,7 +9,6 @@
|
||||
const PANEL_COMPONENTS = {
|
||||
Document,
|
||||
LayerTree,
|
||||
NodeGraph,
|
||||
Properties,
|
||||
};
|
||||
type PanelTypes = keyof typeof PANEL_COMPONENTS;
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
const PANEL_SIZES = {
|
||||
/**/ root: 100,
|
||||
/* ├── */ content: 80,
|
||||
/* │ ├── */ document: 50,
|
||||
/* │ └── */ graph: 50,
|
||||
/* │ ├── */ document: 100,
|
||||
/* └── */ details: 20,
|
||||
/* ├── */ properties: 45,
|
||||
/* └── */ layers: 55,
|
||||
@@ -111,12 +110,6 @@
|
||||
bind:this={documentPanel}
|
||||
/>
|
||||
</LayoutRow>
|
||||
{#if $portfolio.documents.length > 0}
|
||||
<LayoutRow class="workspace-grid-resize-gutter" data-gutter-vertical on:pointerdown={resizePanel} />
|
||||
<LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["graph"] }} data-subdivision-name="graph">
|
||||
<Panel panelType="NodeGraph" tabLabels={[{ name: "Node Graph" }]} tabActiveIndex={0} />
|
||||
</LayoutRow>
|
||||
{/if}
|
||||
</LayoutCol>
|
||||
<LayoutCol class="workspace-grid-resize-gutter" data-gutter-horizontal on:pointerdown={(e) => resizePanel(e)} />
|
||||
<LayoutCol class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["details"] }} data-subdivision-name="details">
|
||||
|
||||
@@ -103,7 +103,7 @@ export function createInputManager(editor: Editor, dialog: DialogState, document
|
||||
if (await shouldRedirectKeyboardEventToBackend(e)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.instance.onKeyDown(key, modifiers);
|
||||
editor.instance.onKeyDown(key, modifiers, e.repeat);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export function createInputManager(editor: Editor, dialog: DialogState, document
|
||||
if (await shouldRedirectKeyboardEventToBackend(e)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeKeyboardModifiersBitfield(e);
|
||||
editor.instance.onKeyUp(key, modifiers);
|
||||
editor.instance.onKeyUp(key, modifiers, e.repeat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
UpdateToolOptionsLayout,
|
||||
UpdateToolShelfLayout,
|
||||
UpdateWorkingColorsLayout,
|
||||
UpdateGraphViewOverlayButtonLayout,
|
||||
UpdateNodeGraphBarLayout,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
@@ -21,7 +23,9 @@ export function createDocumentState(editor: Editor) {
|
||||
toolOptionsLayout: defaultWidgetLayout(),
|
||||
documentBarLayout: defaultWidgetLayout(),
|
||||
toolShelfLayout: defaultWidgetLayout(),
|
||||
graphViewOverlayButtonLayout: defaultWidgetLayout(),
|
||||
workingColorsLayout: defaultWidgetLayout(),
|
||||
nodeGraphBarLayout: defaultWidgetLayout(),
|
||||
});
|
||||
const { subscribe, update } = state;
|
||||
|
||||
@@ -62,6 +66,14 @@ export function createDocumentState(editor: Editor) {
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateGraphViewOverlayButtonLayout, async (updateGraphViewOverlayButtonLayout) => {
|
||||
await tick();
|
||||
|
||||
update((state) => {
|
||||
patchWidgetLayout(state.graphViewOverlayButtonLayout, updateGraphViewOverlayButtonLayout);
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateWorkingColorsLayout, async (updateWorkingColorsLayout) => {
|
||||
await tick();
|
||||
|
||||
@@ -71,6 +83,14 @@ export function createDocumentState(editor: Editor) {
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphBarLayout, (updateNodeGraphBarLayout) => {
|
||||
update((state) => {
|
||||
patchWidgetLayout(state.nodeGraphBarLayout, updateNodeGraphBarLayout);
|
||||
return state;
|
||||
});
|
||||
});
|
||||
|
||||
// Other
|
||||
editor.subscriptions.subscribeJsMessage(TriggerRefreshBoundsOfViewports, async () => {
|
||||
// Wait to display the unpopulated document panel (missing: tools, options bar content, scrollbar positioning, and canvas)
|
||||
await tick();
|
||||
|
||||
@@ -8,10 +8,7 @@ import {
|
||||
type FrontendNodeType,
|
||||
UpdateNodeGraph,
|
||||
UpdateNodeTypes,
|
||||
UpdateNodeGraphBarLayout,
|
||||
UpdateZoomWithScroll,
|
||||
defaultWidgetLayout,
|
||||
patchWidgetLayout,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
@@ -20,7 +17,6 @@ export function createNodeGraphState(editor: Editor) {
|
||||
nodes: [] as FrontendNode[],
|
||||
links: [] as FrontendNodeLink[],
|
||||
nodeTypes: [] as FrontendNodeType[],
|
||||
nodeGraphBarLayout: defaultWidgetLayout(),
|
||||
zoomWithScroll: false as boolean,
|
||||
});
|
||||
|
||||
@@ -38,12 +34,6 @@ export function createNodeGraphState(editor: Editor) {
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphBarLayout, (updateNodeGraphBarLayout) => {
|
||||
update((state) => {
|
||||
patchWidgetLayout(state.nodeGraphBarLayout, updateNodeGraphBarLayout);
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateZoomWithScroll, (updateZoomWithScroll) => {
|
||||
update((state) => {
|
||||
state.zoomWithScroll = updateZoomWithScroll.zoomWithScroll;
|
||||
|
||||
@@ -105,6 +105,8 @@ import FlipHorizontal from "@graphite-frontend/assets/icon-16px-solid/flip-horiz
|
||||
import FlipVertical from "@graphite-frontend/assets/icon-16px-solid/flip-vertical.svg";
|
||||
import Folder from "@graphite-frontend/assets/icon-16px-solid/folder.svg";
|
||||
import GraphiteLogo from "@graphite-frontend/assets/icon-16px-solid/graphite-logo.svg";
|
||||
import GraphViewClosed from "@graphite-frontend/assets/icon-16px-solid/graph-view-closed.svg";
|
||||
import GraphViewOpen from "@graphite-frontend/assets/icon-16px-solid/graph-view-open.svg";
|
||||
import Layer from "@graphite-frontend/assets/icon-16px-solid/layer.svg";
|
||||
import NodeArtboard from "@graphite-frontend/assets/icon-16px-solid/node-artboard.svg";
|
||||
import NodeBlur from "@graphite-frontend/assets/icon-16px-solid/node-blur.svg";
|
||||
@@ -166,6 +168,8 @@ const SOLID_16PX = {
|
||||
FlipVertical: { svg: FlipVertical, size: 16 },
|
||||
Folder: { svg: Folder, size: 16 },
|
||||
GraphiteLogo: { svg: GraphiteLogo, size: 16 },
|
||||
GraphViewClosed: { svg: GraphViewClosed, size: 16 },
|
||||
GraphViewOpen: { svg: GraphViewOpen, size: 16 },
|
||||
Layer: { svg: Layer, size: 16 },
|
||||
NodeArtboard: { svg: NodeArtboard, size: 16 },
|
||||
NodeBlur: { svg: NodeBlur, size: 16 },
|
||||
|
||||
@@ -725,6 +725,10 @@ export class TriggerFontLoad extends JsMessage {
|
||||
isDefault!: boolean;
|
||||
}
|
||||
|
||||
export class TriggerGraphViewOverlay extends JsMessage {
|
||||
open!: boolean;
|
||||
}
|
||||
|
||||
export class TriggerVisitLink extends JsMessage {
|
||||
url!: string;
|
||||
}
|
||||
@@ -1199,7 +1203,7 @@ export function defaultWidgetLayout(): WidgetLayout {
|
||||
};
|
||||
}
|
||||
|
||||
// Updates a widget layout based on a list of updates, returning the new layout
|
||||
// Updates a widget layout based on a list of updates, giving the new layout by mutating the `layout` argument
|
||||
export function patchWidgetLayout(/* mut */ layout: WidgetLayout, updates: WidgetDiffUpdate): void {
|
||||
layout.layoutTarget = updates.layoutTarget;
|
||||
|
||||
@@ -1300,24 +1304,15 @@ function createLayoutGroup(layoutGroup: any): LayoutGroup {
|
||||
// WIDGET LAYOUTS
|
||||
export class UpdateDialogDetails extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateDocumentBarLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate { }
|
||||
export class UpdateGraphViewOverlayButtonLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate { }
|
||||
|
||||
// Extends JsMessage instead of WidgetDiffUpdate because the menu bar isn't diffed
|
||||
export class UpdateMenuBarLayout extends JsMessage {
|
||||
layoutTarget!: unknown;
|
||||
|
||||
@@ -1327,6 +1322,18 @@ export class UpdateMenuBarLayout extends JsMessage {
|
||||
layout!: MenuBarEntry[];
|
||||
}
|
||||
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function createMenuLayout(menuBarEntry: any[]): MenuBarEntry[] {
|
||||
return menuBarEntry.map((entry) => ({
|
||||
@@ -1364,6 +1371,7 @@ export const messageMakers: Record<string, MessageMaker> = {
|
||||
TriggerDownloadRaster,
|
||||
TriggerDownloadTextFile,
|
||||
TriggerFontLoad,
|
||||
TriggerGraphViewOverlay,
|
||||
TriggerImport,
|
||||
TriggerIndexedDbRemoveDocument,
|
||||
TriggerIndexedDbWriteDocument,
|
||||
@@ -1382,17 +1390,18 @@ export const messageMakers: Record<string, MessageMaker> = {
|
||||
UpdateActiveDocument,
|
||||
UpdateDialogDetails,
|
||||
UpdateDocumentArtboards,
|
||||
UpdateDocumentNodeRender,
|
||||
UpdateDocumentArtwork,
|
||||
UpdateDocumentBarLayout,
|
||||
UpdateDocumentLayerDetails,
|
||||
UpdateDocumentLayerTreeStructureJs: newUpdateDocumentLayerTreeStructure,
|
||||
UpdateDocumentModeLayout,
|
||||
UpdateDocumentNodeRender,
|
||||
UpdateDocumentOverlays,
|
||||
UpdateDocumentRulers,
|
||||
UpdateDocumentScrollbars,
|
||||
UpdateDocumentTransform,
|
||||
UpdateEyedropperSamplingState,
|
||||
UpdateGraphViewOverlayButtonLayout,
|
||||
UpdateImageData,
|
||||
UpdateInputHints,
|
||||
UpdateLayerTreeOptionsLayout,
|
||||
|
||||
Reference in New Issue
Block a user