Wip mirror widget test

This commit is contained in:
Austin Mroz
2025-08-27 21:15:12 -07:00
parent f3d9f4cffb
commit 5be68c03fc
2 changed files with 195 additions and 0 deletions

View File

@@ -576,4 +576,38 @@ export class SubgraphNode extends LGraphNode implements BaseLGraph {
// Call parent serialize method
return super.serialize()
}
addProxyWidget() {
function linkedWidget(graph, nodeId="", widgetName) {
let g = graph
let n = undefined
for (let id of nodeId.split(':')) {
n = g?._nodes_by_id?.[id]
graph = n?.subgraph
}
if (!n) return
return n.widgets.find((w) => w.name === widgetName)
}
const overlay: object = {}
const handler = Object.fromEntries(['get', 'set'].map((s) => {
const func = function(t,p,r) {
if (s == 'get' && p == '_overlay')
return overlay
if (s == 'get' && p == 'value')
return linkedWidget(overlay.graph, overlay.nodeId, overlay.widgetName).value
if (s == 'set' && p == 'value')
return linkedWidget(overlay.graph, overlay.nodeId, overlay.widgetName).value = r
if (s == 'get' && p == 'node')
return linkedWidget(overlay.graph, overlay.nodeId, overlay.widgetName).node
if (['y', 'last_y', 'width', 'computedHeight', 'computedDisabled'].includes(p))
t = overlay
else
t = linkedWidget(overlay.graph, overlay.nodeId, overlay.widgetName)
if (!t)
return//TODO: pass to overlay subitem to display a disconnected state
return Reflect[s](t,p,r)
}
return [s, func]
}))
this.widgets.push(new Proxy(overlay, handler))
}
}

View File

@@ -0,0 +1,161 @@
import type { BaseWidget } from './BaseWidget'
function getProxy2() {
return {
__proto__:
}
}
function getProxy() {
const overlay: object = {}
const handler = Object.fromEntries(['get', 'set'].map((s) => {
const func = function(t,p,r) => {
if (s == 'get' && p == '_overlay')
return overlay
if (!['y', 'last_y', 'width'].includes(p))
t = overlay
else
t = linkedWidget(overlay.graph, overlay.nodeId, overlay.widgetName)
if (!t)
return//TODO: pass to overlay subitem to display a disconnected state
return Reflect[s](t,p,r)
}
return [s, func]
}))
return new Proxy(overlay, handler)
}
function linkedWidget(graph, nodeId, widgetName) {
let g = g
let n = undefined
for (let id of nodeId.split(':')) {
n = g?.nodes_by_id[id]
graph = n?.subgraph
}
if (!node) return
return node.widgets.find((w) => w.name == widgetName)
}
function linkedWidget(graph: Subgraph, nodeId: string, widgetName): IBaseWidget|undefined {
let g: Subgraph|undefined = g
let n: LGraphNode|SubgraphNode|undefined = undefined
for (let id of nodeId.split(':')) {
n = g?.nodes_by_id[id]
graph = n?.subgraph
}
if (!node) return
return node.widgets.find((w) => w.name == widgetName)
}
function createMirrorWidget(nodeId: string, widgetName: string) {
const base = {pos: [0,0], size: [0,0]}
}
export class MirrorWidget extends BaseWidget{
linkedNodeId: string
//TODO: Add node ref to detect id reuse
linkedWidgetName: string
get _linkedWidget(): IBaseWidget|undefined {
let graph: Subgraph|undefined = this.node.subgraph
let node: LGraphNode|SubgraphNode|undefined = undefined
for (let id of this.linkedNodeId.split(':')) {
node = graph.nodes_by_id[id]
graph = node?.subgraph
}
if (!node) return
return node.widgets.find((w) => w.name == this.linkedWidgetName)
}
mockedWidget(): IBaseWidget {
return new Proxy(this._linkedWidget, handler)
}
override get _displayValue() {
}
override canIncrement(): boolean {
const { max } = this.options
return max == null || this.value < max
}
override canDecrement(): boolean {
const { min } = this.options
return min == null || this.value > min
}
override incrementValue(options: WidgetEventOptions): void {
this.setValue(this.value + getWidgetStep(this.options), options)
}
override decrementValue(options: WidgetEventOptions): void {
this.setValue(this.value - getWidgetStep(this.options), options)
}
override setValue(value: number, options: WidgetEventOptions) {
let newValue = value
if (this.options.min != null && newValue < this.options.min) {
newValue = this.options.min
}
if (this.options.max != null && newValue > this.options.max) {
newValue = this.options.max
}
super.setValue(newValue, options)
}
override onClick({ e, node, canvas }: WidgetEventOptions) {
const x = e.canvasX - node.pos[0]
const width = this.width || node.size[0]
// Determine if clicked on left/right arrows
const delta = x < 40 ? -1 : x > width - 40 ? 1 : 0
if (delta) {
// Handle left/right arrow clicks
this.setValue(this.value + delta * getWidgetStep(this.options), {
e,
node,
canvas
})
return
}
// Handle center click - show prompt
canvas.prompt(
'Value',
this.value,
(v: string) => {
// Check if v is a valid equation or a number
if (/^[\d\s()*+/-]+|\d+\.\d+$/.test(v)) {
// Solve the equation if possible
try {
v = eval(v)
} catch {
// Ignore eval errors
}
}
const newValue = Number(v)
if (!isNaN(newValue)) {
this.setValue(newValue, { e, node, canvas })
}
},
e
)
}
/**
* Handles drag events for the number widget
* @param options The options for handling the drag event
*/
override onDrag({ e, node, canvas }: WidgetEventOptions) {
const width = this.width || node.width
const x = e.canvasX - node.pos[0]
const delta = x < 40 ? -1 : x > width - 40 ? 1 : 0
if (delta && x > -3 && x < width + 3) return
this.setValue(this.value + (e.deltaX ?? 0) * getWidgetStep(this.options), {
e,
node,
canvas
})
}
}