mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 03:18:06 +08:00
Update Imaginate to output bitmap data to the graph via Image Frame node (#1001)
* Multiple node outputs * Add new nodes * gcore use std by default to allow for testing * Allow multiple node outputs * Multiple outputs to frontend * Add ImageFrameNode to node registry * Minor cleanup * Basic transform implementation * Add some logging to image encoding * Fix ImageFrameNode * Add transform input to Imaginate node (#1014) * Add transform input to imaginate node * Force the resolution to be edited with no transform * Add transform to imaginate generation * Fix compilation --------- Co-authored-by: Keavon Chambers <keavon@keavon.com> * Add labels to node outputs * Fix seed; disable mask when transform is disconnected; add Imaginate tooltips * Rename 'Input Multiple' node to 'Input' * Code review * Replicate to Svelte * Show only the primary input chain in the Properties panel --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev> Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
v-for="node in nodes"
|
||||
:key="String(node.id)"
|
||||
class="node"
|
||||
:class="{ selected: selected.includes(node.id), output: node.output, disabled: node.disabled }"
|
||||
:class="{ selected: selected.includes(node.id), previewed: node.previewed, disabled: node.disabled }"
|
||||
:style="{
|
||||
'--offset-left': (node.position?.x || 0) + (selected.includes(node.id) ? draggingNodes?.roundX || 0 : 0),
|
||||
'--offset-top': (node.position?.y || 0) + (selected.includes(node.id) ? draggingNodes?.roundY || 0 : 0),
|
||||
@@ -58,8 +58,8 @@
|
||||
v-if="node.outputs.length > 0"
|
||||
class="output port"
|
||||
data-port="output"
|
||||
:data-datatype="node.outputs[0]"
|
||||
:style="{ '--data-color': `var(--color-data-${node.outputs[0]})`, '--data-color-dim': `var(--color-data-${node.outputs[0]}-dim)` }"
|
||||
:data-datatype="node.outputs[0].dataType"
|
||||
:style="{ '--data-color': `var(--color-data-${node.outputs[0].dataType})`, '--data-color-dim': `var(--color-data-${node.outputs[0].dataType}-dim)` }"
|
||||
>
|
||||
<div></div>
|
||||
</div>
|
||||
@@ -67,19 +67,32 @@
|
||||
<IconLabel :icon="nodeIcon(node.displayName)" />
|
||||
<TextLabel>{{ node.displayName }}</TextLabel>
|
||||
</div>
|
||||
<div v-if="node.exposedInputs.length > 0" class="arguments">
|
||||
<div v-for="(argument, index) in node.exposedInputs" :key="index" class="argument">
|
||||
<div v-if="[...node.exposedInputs, ...node.outputs.slice(1)].length > 0" class="parameters">
|
||||
<div v-for="(parameter, index) in [...node.exposedInputs, ...node.outputs.slice(1)]" :key="index" class="parameter">
|
||||
<div class="ports">
|
||||
<div
|
||||
v-if="index < node.exposedInputs.length"
|
||||
class="input port"
|
||||
data-port="input"
|
||||
:data-datatype="argument.dataType"
|
||||
:style="{ '--data-color': `var(--color-data-${argument.dataType})`, '--data-color-dim': `var(--color-data-${argument.dataType}-dim)` }"
|
||||
:data-datatype="parameter.dataType"
|
||||
:style="{
|
||||
'--data-color': `var(--color-data-${parameter.dataType})`,
|
||||
'--data-color-dim': `var(--color-data-${parameter.dataType}-dim)`,
|
||||
}"
|
||||
>
|
||||
<div></div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="output port"
|
||||
data-port="output"
|
||||
:data-datatype="parameter.dataType"
|
||||
:style="{ '--data-color': `var(--color-data-${parameter.dataType})`, '--data-color-dim': `var(--color-data-${parameter.dataType}-dim)` }"
|
||||
>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
<TextLabel>{{ argument.name }}</TextLabel>
|
||||
<TextLabel :class="index < node.exposedInputs.length ? 'name' : 'output'">{{ parameter.name }}</TextLabel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,7 +221,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.output {
|
||||
&.previewed {
|
||||
outline: 3px solid var(--color-data-vector);
|
||||
}
|
||||
|
||||
@@ -231,20 +244,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.arguments {
|
||||
.parameters {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.argument {
|
||||
.parameter {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
width: calc(100% - 24px * 2);
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
|
||||
.text-label {
|
||||
width: 100%;
|
||||
|
||||
&.output {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Squares to cover up the rounded corners of the primary area and make them have a straight edge
|
||||
@@ -315,8 +336,6 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, nextTick } from "vue";
|
||||
|
||||
// import type { FrontendNode } from "@/wasm-communication/messages";
|
||||
|
||||
import type { IconName } from "@/utility-functions/icons";
|
||||
|
||||
import { UpdateNodeGraphSelection, type FrontendNodeLink } from "@/wasm-communication/messages";
|
||||
@@ -411,12 +430,15 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
resolveLink(link: FrontendNodeLink, containerBounds: HTMLDivElement): { nodePrimaryOutput: HTMLDivElement | undefined; nodePrimaryInput: HTMLDivElement | undefined } {
|
||||
const connectorIndex = Number(link.linkEndInputIndex);
|
||||
|
||||
const nodePrimaryOutput = (containerBounds.querySelector(`[data-node="${String(link.linkStart)}"] [data-port="output"]`) || undefined) as HTMLDivElement | undefined;
|
||||
const outputIndex = Number(link.linkStartOutputIndex);
|
||||
const inputIndex = Number(link.linkEndInputIndex);
|
||||
|
||||
const nodeOutputConnectors = containerBounds.querySelectorAll(`[data-node="${String(link.linkStart)}"] [data-port="output"]`) || undefined;
|
||||
const nodeInputConnectors = containerBounds.querySelectorAll(`[data-node="${String(link.linkEnd)}"] [data-port="input"]`) || undefined;
|
||||
const nodePrimaryInput = nodeInputConnectors?.[connectorIndex] as HTMLDivElement | undefined;
|
||||
|
||||
const nodePrimaryOutput = nodeOutputConnectors?.[outputIndex] as HTMLDivElement | undefined;
|
||||
const nodePrimaryInput = nodeInputConnectors?.[inputIndex] as HTMLDivElement | undefined;
|
||||
|
||||
return { nodePrimaryOutput, nodePrimaryInput };
|
||||
},
|
||||
async refreshLinks(): Promise<void> {
|
||||
@@ -579,8 +601,8 @@ export default defineComponent({
|
||||
const inputIndexInt = BigInt(inputIndex);
|
||||
const links = this.nodeGraph.state.links;
|
||||
const linkIndex = links.findIndex((value) => value.linkEnd === nodeIdInt && value.linkEndInputIndex === inputIndexInt);
|
||||
const queryString = `[data-node="${String(links[linkIndex].linkStart)}"] [data-port="output"]`;
|
||||
this.linkInProgressFromConnector = (containerBounds.querySelector(queryString) || undefined) as HTMLDivElement | undefined;
|
||||
const nodeOutputConnectors = containerBounds.querySelectorAll(`[data-node="${String(links[linkIndex].linkStart)}"] [data-port="output"]`) || undefined;
|
||||
this.linkInProgressFromConnector = nodeOutputConnectors?.[Number(links[linkIndex].linkEndInputIndex)] as HTMLDivElement | undefined;
|
||||
const nodeInputConnectors = containerBounds.querySelectorAll(`[data-node="${String(links[linkIndex].linkEnd)}"] [data-port="input"]`) || undefined;
|
||||
this.linkInProgressToConnector = nodeInputConnectors?.[Number(links[linkIndex].linkEndInputIndex)] as HTMLDivElement | undefined;
|
||||
this.disconnecting = { nodeId: nodeIdInt, inputIndex, linkIndex };
|
||||
@@ -674,13 +696,16 @@ export default defineComponent({
|
||||
|
||||
if (outputNode && inputNode && outputConnectedNodeID && inputConnectedNodeID) {
|
||||
const inputNodeInPorts = Array.from(inputNode.querySelectorAll(`[data-port="input"]`));
|
||||
const outputNodeInPorts = Array.from(outputNode.querySelectorAll(`[data-port="output"]`));
|
||||
|
||||
const inputNodeConnectionIndexSearch = inputNodeInPorts.indexOf(this.linkInProgressToConnector);
|
||||
const outputNodeConnectionIndexSearch = outputNodeInPorts.indexOf(this.linkInProgressFromConnector);
|
||||
|
||||
const inputNodeConnectionIndex = inputNodeConnectionIndexSearch > -1 ? inputNodeConnectionIndexSearch : undefined;
|
||||
const outputNodeConnectionIndex = outputNodeConnectionIndexSearch > -1 ? outputNodeConnectionIndexSearch : undefined;
|
||||
|
||||
if (inputNodeConnectionIndex !== undefined) {
|
||||
// const oneBasedIndex = inputNodeConnectionIndex + 1;
|
||||
|
||||
this.editor.instance.connectNodesByLink(BigInt(outputConnectedNodeID), BigInt(inputConnectedNodeID), inputNodeConnectionIndex);
|
||||
if (inputNodeConnectionIndex !== undefined && outputNodeConnectionIndex !== undefined) {
|
||||
this.editor.instance.connectNodesByLink(BigInt(outputConnectedNodeID), outputNodeConnectionIndex, BigInt(inputConnectedNodeID), inputNodeConnectionIndex);
|
||||
}
|
||||
}
|
||||
} else if (this.draggingNodes) {
|
||||
@@ -728,8 +753,8 @@ export default defineComponent({
|
||||
});
|
||||
// If the node has been dragged on top of the link then connect it into the middle.
|
||||
if (link) {
|
||||
this.editor.instance.connectNodesByLink(link.linkStart, selectedNodeId, 0);
|
||||
this.editor.instance.connectNodesByLink(selectedNodeId, link.linkEnd, Number(link.linkEndInputIndex));
|
||||
this.editor.instance.connectNodesByLink(link.linkStart, 0, selectedNodeId, 0);
|
||||
this.editor.instance.connectNodesByLink(selectedNodeId, 0, link.linkEnd, Number(link.linkEndInputIndex));
|
||||
this.editor.instance.shiftNode(selectedNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,12 @@ export class NodeGraphInput {
|
||||
readonly name!: string;
|
||||
}
|
||||
|
||||
export class NodeGraphOutput {
|
||||
readonly dataType!: FrontendGraphDataType;
|
||||
|
||||
readonly name!: string;
|
||||
}
|
||||
|
||||
export class FrontendNode {
|
||||
readonly id!: bigint;
|
||||
|
||||
@@ -92,12 +98,12 @@ export class FrontendNode {
|
||||
|
||||
readonly exposedInputs!: NodeGraphInput[];
|
||||
|
||||
readonly outputs!: FrontendGraphDataType[];
|
||||
readonly outputs!: NodeGraphOutput[];
|
||||
|
||||
@TupleToVec2
|
||||
readonly position!: XY | undefined;
|
||||
|
||||
readonly output!: boolean;
|
||||
readonly previewed!: boolean;
|
||||
|
||||
readonly disabled!: boolean;
|
||||
}
|
||||
@@ -105,6 +111,8 @@ export class FrontendNode {
|
||||
export class FrontendNodeLink {
|
||||
readonly linkStart!: bigint;
|
||||
|
||||
readonly linkStartOutputIndex!: bigint;
|
||||
|
||||
readonly linkEnd!: bigint;
|
||||
|
||||
readonly linkEndInputIndex!: bigint;
|
||||
|
||||
Reference in New Issue
Block a user