diff --git a/packages/design-system/src/icons/nodeSlot2.svg b/packages/design-system/src/icons/nodeSlot2.svg
new file mode 100644
index 0000000000..cc12805700
--- /dev/null
+++ b/packages/design-system/src/icons/nodeSlot2.svg
@@ -0,0 +1,19 @@
+
diff --git a/packages/design-system/src/icons/nodeSlot3.svg b/packages/design-system/src/icons/nodeSlot3.svg
new file mode 100644
index 0000000000..fc94a178bb
--- /dev/null
+++ b/packages/design-system/src/icons/nodeSlot3.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/lib/litegraph/src/node/NodeSlot.ts b/src/lib/litegraph/src/node/NodeSlot.ts
index e7a2de3826..4e17069b28 100644
--- a/src/lib/litegraph/src/node/NodeSlot.ts
+++ b/src/lib/litegraph/src/node/NodeSlot.ts
@@ -30,6 +30,8 @@ export interface IDrawOptions {
highlight?: boolean
}
+const ROTATION_OFFSET = -Math.PI / 2
+
/** Shared base class for {@link LGraphNode} input and output slots. */
export abstract class NodeSlot extends SlotBase implements INodeSlot {
pos?: Point
@@ -130,6 +132,7 @@ export abstract class NodeSlot extends SlotBase implements INodeSlot {
slot_type === SlotType.Array ? SlotShape.Grid : this.shape
) as SlotShape
+ ctx.save()
ctx.beginPath()
let doFill = true
@@ -163,16 +166,52 @@ export abstract class NodeSlot extends SlotBase implements INodeSlot {
if (lowQuality) {
ctx.rect(pos[0] - 4, pos[1] - 4, 8, 8)
} else {
- let radius: number
if (slot_shape === SlotShape.HollowCircle) {
+ const path = new Path2D()
+ path.arc(pos[0], pos[1], 10, 0, Math.PI * 2)
+ path.arc(pos[0], pos[1], highlight ? 2.5 : 1.5, 0, Math.PI * 2)
+ ctx.clip(path, 'evenodd')
+ }
+ const radius = highlight ? 5 : 4
+ const typesSet = new Set(
+ `${this.type}`
+ .split(',')
+ .map(
+ this.isConnected
+ ? (type) => colorContext.getConnectedColor(type)
+ : (type) => colorContext.getDisconnectedColor(type)
+ )
+ )
+ const types = [...typesSet].slice(0, 3)
+ if (types.length > 1) {
doFill = false
- doStroke = true
- ctx.lineWidth = 3
- ctx.strokeStyle = ctx.fillStyle
- radius = highlight ? 4 : 3
- } else {
- // Normal circle
- radius = highlight ? 5 : 4
+ const arcLen = (Math.PI * 2) / types.length
+ types.forEach((type, idx) => {
+ ctx.moveTo(pos[0], pos[1])
+ ctx.fillStyle = type
+ ctx.arc(
+ pos[0],
+ pos[1],
+ radius,
+ arcLen * idx + ROTATION_OFFSET,
+ Math.PI * 2 + ROTATION_OFFSET
+ )
+ ctx.fill()
+ ctx.beginPath()
+ })
+ //add stroke dividers
+ ctx.save()
+ ctx.strokeStyle = 'black'
+ ctx.lineWidth = 0.5
+ types.forEach((_, idx) => {
+ ctx.moveTo(pos[0], pos[1])
+ const xOffset = Math.cos(arcLen * idx + ROTATION_OFFSET) * radius
+ const yOffset = Math.sin(arcLen * idx + ROTATION_OFFSET) * radius
+ ctx.lineTo(pos[0] + xOffset, pos[1] + yOffset)
+ })
+ ctx.stroke()
+ ctx.restore()
+ ctx.beginPath()
}
ctx.arc(pos[0], pos[1], radius, 0, Math.PI * 2)
}
@@ -180,6 +219,7 @@ export abstract class NodeSlot extends SlotBase implements INodeSlot {
if (doFill) ctx.fill()
if (!lowQuality && doStroke) ctx.stroke()
+ ctx.restore()
// render slot label
const hideLabel = lowQuality || this.isWidgetInputSlot
diff --git a/src/renderer/extensions/vueNodes/components/InputSlot.vue b/src/renderer/extensions/vueNodes/components/InputSlot.vue
index e32be802d4..9205768e67 100644
--- a/src/renderer/extensions/vueNodes/components/InputSlot.vue
+++ b/src/renderer/extensions/vueNodes/components/InputSlot.vue
@@ -20,13 +20,13 @@
{
return false
})
-const slotColor = computed(() => {
- if (hasSlotError.value) {
- return 'var(--color-error)'
- }
- return getSlotColor(props.slotData.type)
-})
-
const { state: dragState } = useSlotLinkDragUIState()
const slotKey = computed(() =>
getSlotKey(props.nodeId ?? '', props.index, true)
diff --git a/src/renderer/extensions/vueNodes/components/OutputSlot.vue b/src/renderer/extensions/vueNodes/components/OutputSlot.vue
index a05b969fa4..9a7506130f 100644
--- a/src/renderer/extensions/vueNodes/components/OutputSlot.vue
+++ b/src/renderer/extensions/vueNodes/components/OutputSlot.vue
@@ -10,8 +10,8 @@
@@ -22,7 +22,6 @@ import { computed, onErrorCaptured, ref, watchEffect } from 'vue'
import type { ComponentPublicInstance } from 'vue'
import { useErrorHandling } from '@/composables/useErrorHandling'
-import { getSlotColor } from '@/constants/slotColors'
import type { INodeSlot } from '@/lib/litegraph/src/litegraph'
import { useSlotLinkDragUIState } from '@/renderer/core/canvas/links/slotLinkDragUIState'
import { getSlotKey } from '@/renderer/core/layout/slots/slotIdentifier'
@@ -67,9 +66,6 @@ onErrorCaptured((error) => {
return false
})
-// Get slot color based on type
-const slotColor = computed(() => getSlotColor(props.slotData.type))
-
const { state: dragState } = useSlotLinkDragUIState()
const slotKey = computed(() =>
getSlotKey(props.nodeId ?? '', props.index, false)
diff --git a/src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue b/src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
index 273c6ea503..3921128b02 100644
--- a/src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
+++ b/src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
@@ -1,20 +1,45 @@
@@ -27,19 +52,26 @@ defineExpose({
"
>
+
+
+
+