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:
0HyperCube
2023-02-11 08:56:31 +00:00
committed by GitHub
parent 70f4d60e66
commit e14618b234
35 changed files with 1172 additions and 553 deletions

View File

@@ -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);
}
}

View File

@@ -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;