diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png index 0c57f7db1..6c0bdcc60 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png index 8f87009b7..5d89bf47f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png differ diff --git a/src/composables/graph/useGraphNodeManager.ts b/src/composables/graph/useGraphNodeManager.ts index ad030222a..3b52bc7ff 100644 --- a/src/composables/graph/useGraphNodeManager.ts +++ b/src/composables/graph/useGraphNodeManager.ts @@ -69,6 +69,7 @@ export interface VueNodeData { } color?: string bgcolor?: string + shape?: number } export interface GraphNodeManager { @@ -234,7 +235,8 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager { outputs: node.outputs ? [...node.outputs] : undefined, flags: node.flags ? { ...node.flags } : undefined, color: node.color || undefined, - bgcolor: node.bgcolor || undefined + bgcolor: node.bgcolor || undefined, + shape: node.shape } } @@ -571,6 +573,15 @@ export function useGraphNodeManager(graph: LGraph): GraphNodeManager { ? propertyEvent.newValue : undefined }) + break + case 'shape': + vueNodeData.set(nodeId, { + ...currentData, + shape: + typeof propertyEvent.newValue === 'number' + ? propertyEvent.newValue + : undefined + }) } } }, diff --git a/src/lib/litegraph/src/LGraphNode.ts b/src/lib/litegraph/src/LGraphNode.ts index 961d30911..f87c1ceae 100644 --- a/src/lib/litegraph/src/LGraphNode.ts +++ b/src/lib/litegraph/src/LGraphNode.ts @@ -495,6 +495,7 @@ export class LGraphNode } set shape(v: RenderShape | 'default' | 'box' | 'round' | 'circle' | 'card') { + const oldValue = this._shape switch (v) { case 'default': this._shape = undefined @@ -514,6 +515,14 @@ export class LGraphNode default: this._shape = v } + if (oldValue !== this._shape) { + this.graph?.trigger('node:property:changed', { + nodeId: this.id, + property: 'shape', + oldValue, + newValue: this._shape + }) + } } /** diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index 109d0c562..fe95cae24 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -11,7 +11,8 @@ 'bg-component-node-background lg-node absolute pb-1', 'contain-style contain-layout min-w-[225px] min-h-(--node-height) w-(--node-width)', - 'rounded-2xl touch-none flex flex-col', + shapeClass, + 'touch-none flex flex-col', 'border-1 border-solid border-component-node-border', // hover (only when node should handle events) shouldHandleNodePointerEvents && @@ -21,9 +22,9 @@ outlineClass, cursorClass, { - 'before:rounded-2xl before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0': + [`${beforeShapeClass} before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0`]: bypassed, - 'before:rounded-2xl before:pointer-events-none before:absolute before:inset-0': + [`${beforeShapeClass} before:pointer-events-none before:absolute before:inset-0`]: muted, 'ring-4 ring-primary-500 bg-primary-500/10': isDraggingOver }, @@ -140,7 +141,8 @@ import { st } from '@/i18n' import { LGraphCanvas, LGraphEventMode, - LiteGraph + LiteGraph, + RenderShape } from '@/lib/litegraph/src/litegraph' import { useSettingStore } from '@/platform/settings/settingStore' import { useTelemetry } from '@/platform/telemetry' @@ -383,6 +385,28 @@ const cursorClass = computed(() => { ) }) +const shapeClass = computed(() => { + switch (nodeData.shape) { + case RenderShape.BOX: + return 'rounded-none' + case RenderShape.CARD: + return 'rounded-tl-2xl rounded-br-2xl rounded-tr-none rounded-bl-none' + default: + return 'rounded-2xl' + } +}) + +const beforeShapeClass = computed(() => { + switch (nodeData.shape) { + case RenderShape.BOX: + return 'before:rounded-none' + case RenderShape.CARD: + return 'before:rounded-tl-2xl before:rounded-br-2xl before:rounded-tr-none before:rounded-bl-none' + default: + return 'before:rounded-2xl' + } +}) + // Event handlers const handleCollapse = () => { handleNodeCollapse(nodeData.id, !isCollapsed.value) diff --git a/src/renderer/extensions/vueNodes/components/NodeHeader.vue b/src/renderer/extensions/vueNodes/components/NodeHeader.vue index debb358d6..fb5e6afec 100644 --- a/src/renderer/extensions/vueNodes/components/NodeHeader.vue +++ b/src/renderer/extensions/vueNodes/components/NodeHeader.vue @@ -6,9 +6,9 @@ v-else :class=" cn( - 'lg-node-header py-2 pl-2 pr-3 text-sm rounded-t-2xl w-full min-w-0', + 'lg-node-header py-2 pl-2 pr-3 text-sm w-full min-w-0', 'text-node-component-header bg-node-component-header-surface', - collapsed && 'rounded-2xl' + headerShapeClass ) " :style="headerStyle" @@ -99,7 +99,7 @@ import EditableText from '@/components/common/EditableText.vue' import type { VueNodeData } from '@/composables/graph/useGraphNodeManager' import { useErrorHandling } from '@/composables/useErrorHandling' import { st } from '@/i18n' -import { LGraphEventMode } from '@/lib/litegraph/src/litegraph' +import { LGraphEventMode, RenderShape } from '@/lib/litegraph/src/litegraph' import { useSettingStore } from '@/platform/settings/settingStore' import NodeBadge from '@/renderer/extensions/vueNodes/components/NodeBadge.vue' import { useNodeTooltips } from '@/renderer/extensions/vueNodes/composables/useNodeTooltips' @@ -204,6 +204,28 @@ const nodeBadges = computed(() => ) const isPinned = computed(() => Boolean(nodeData?.flags?.pinned)) const isApiNode = computed(() => Boolean(nodeData?.apiNode)) + +const headerShapeClass = computed(() => { + if (collapsed) { + switch (nodeData?.shape) { + case RenderShape.BOX: + return 'rounded-none' + case RenderShape.CARD: + return 'rounded-tl-2xl rounded-br-2xl rounded-tr-none rounded-bl-none' + default: + return 'rounded-2xl' + } + } + switch (nodeData?.shape) { + case RenderShape.BOX: + return 'rounded-t-none' + case RenderShape.CARD: + return 'rounded-tl-2xl rounded-tr-none' + default: + return 'rounded-t-2xl' + } +}) + // Subgraph detection const isSubgraphNode = computed(() => { if (!nodeData?.id) return false