From 3227b96e4e41dcb50042c3a691b28fb3f48f46db Mon Sep 17 00:00:00 2001 From: saurabh-prosoft Date: Thu, 22 Jun 2023 22:32:18 +0530 Subject: [PATCH] general bugfixes --- docs/.vuepress/config.cjs | 2 +- package.json | 2 +- src/core/flow.ts | 12 +++++------- src/flow-connect.ts | 2 +- src/ui/envelope.ts | 39 +++++++++++++++++++++++++++++++++------ src/utils/linked-list.ts | 25 +++++++++++-------------- src/utils/utils.ts | 7 +++++++ 7 files changed, 59 insertions(+), 30 deletions(-) diff --git a/docs/.vuepress/config.cjs b/docs/.vuepress/config.cjs index 55a59624..3b5c5786 100644 --- a/docs/.vuepress/config.cjs +++ b/docs/.vuepress/config.cjs @@ -85,7 +85,7 @@ module.exports = { }, ], }, - { text: "v2.0.5", link: "/" }, + { text: "v2.0.6", link: "/" }, ], sidebar: { "/guide/": [ diff --git a/package.json b/package.json index bde6c2dc..a472530e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flow-connect", - "version": "2.0.5", + "version": "2.0.6", "description": "FlowConnect is a highly-customizable library for creating node-based editors, graphs and diagrams.", "type": "module", "main": "dist/cjs/flow-connect.js", diff --git a/src/core/flow.ts b/src/core/flow.ts index 9f7060d1..de6618e6 100644 --- a/src/core/flow.ts +++ b/src/core/flow.ts @@ -1,5 +1,5 @@ import { Color, FlowConnect } from "../flow-connect.js"; -import { Vector } from "./vector.js"; +import { SerializedVector, Vector } from "./vector.js"; import { Node, NodeOptions, SerializedNode } from "./node.js"; import { Hooks } from "./hooks.js"; import { Group, SerializedGroup } from "./group.js"; @@ -16,7 +16,7 @@ import { } from "../common/interfaces.js"; import { SerializedSubFlowNode, SubFlowNode, SubFlowNodeOptions } from "./subflow-node.js"; import { TunnelNode, SerializedTunnelNode, TunnelNodeOptions } from "./tunnel-node.js"; -import { capitalize, uuid } from "../utils/utils.js"; +import { capitalize, isVector, uuid } from "../utils/utils.js"; import { Graph } from "./graph.js"; import { Terminal } from "./terminal.js"; import { Log } from "../utils/logger.js"; @@ -252,12 +252,10 @@ export class Flow extends Hooks implements Serializable { receive?: DataFetchProvider ): Promise> { for (let key in state) { - if ( - typeof state[key] === "object" && - state[key] && - Object.keys(state[key]).every((k) => ["x", "y"].includes(k) && typeof state[key][k] === "number") - ) { + if (isVector(state[key])) { state[key] = Vector.create(state[key].x, state[key].y); + } else if (Array.isArray(state[key]) && state[key].length > 0 && isVector(state[key][0])) { + state[key] = state[key].map((sv: SerializedVector) => Vector.create(sv.x, sv.y)); } else if (typeof state[key] === "object" && state[key] && state[key].id?.startsWith("raw##")) { if (receive) { state[key] = await receive({ ...state[key], id: (state[key].id as string).replace("raw##", "") }); diff --git a/src/flow-connect.ts b/src/flow-connect.ts index b8ab93b4..54ad2ec2 100644 --- a/src/flow-connect.ts +++ b/src/flow-connect.ts @@ -717,7 +717,7 @@ export class FlowConnect extends Hooks { let hitNode = this.getHitNode(screenPosition); let hitColor = Color.rgbaToString(this.offUIContext.getImageData(screenPosition.x, screenPosition.y, 1, 1).data); - let currHitUINode = hitNode.getHitUINode(hitColor); + let currHitUINode = hitNode?.getHitUINode(hitColor); if (!currHitUINode) { this.call("dbl-press", { screenPos: screenPosition, realPos: realPosition, target: hitNode ?? this }); } diff --git a/src/ui/envelope.ts b/src/ui/envelope.ts index ced1e37a..f62def35 100644 --- a/src/ui/envelope.ts +++ b/src/ui/envelope.ts @@ -18,14 +18,23 @@ export class Envelope extends UINode { private offPointsContext: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D; get value(): Vector[] { - return this._value.toArray().map((vec) => vec.clone()); + let value; + if (this.propName) value = this.getProp().map((vec: Vector) => vec.clone()); + else value = this._value.toArray().map((vec) => vec.clone()); + + return value; } set value(value: Vector[]) { - const oldVal = this.value; + let oldVal = this._value.toArray().map((vec) => vec.clone()); + let newVal = value; - this.handleEnvelopeChange(value); + if (this.propName) { + this.setProp(newVal); + } else { + this.handleEnvelopeChange(newVal); + } - if (this.node.flow.state !== FlowState.Stopped) this.call("change", this, oldVal, this._value.toArray()); + if (this.node.flow.state !== FlowState.Stopped) this.call("change", this, oldVal, newVal); } constructor(_node: Node, options: EnvelopeOptions = DefaultEnvelopeOptions()) { @@ -66,7 +75,7 @@ export class Envelope extends UINode { } this.offPointsContext = this.offPointsCanvas.getContext("2d"); - this.handleEnvelopeChange(values); + this.handleEnvelopeChange(this.getProp() ?? values); } handleEnvelopeChange(values: Vector[]) { @@ -183,6 +192,8 @@ export class Envelope extends UINode { .clampInPlace(this.currHitPoint.prev?.data.x || 0, this.currHitPoint.next?.data.x || 1, -Infinity, Infinity); this.currHitPoint.data = Vector.create(this.currHitPoint.data.x, 1 - this.currHitPoint.data.y); + this.updateState(); + this.renderOffPoints(); } newPoint(realPosition: Vector, width: number, height: number) { @@ -201,6 +212,9 @@ export class Envelope extends UINode { this.pointHitColorPoint.set(Color.Random().hexValue, newPointNode); this.renderOffPoints(); + + this.updateState(); + if (this.node.flow.state !== FlowState.Stopped) this.call("change", this, oldVal, this._value.toArray()); } deletePoint() { @@ -209,10 +223,23 @@ export class Envelope extends UINode { this.pointHitColorPoint.delete(this.currHitPoint); this.renderOffPoints(); + this.updateState(); + if (this.node.flow.state !== FlowState.Stopped) this.call("change", this, oldVal, this._value.toArray()); } + updateState() { + if (this.propName && this.node.state[this.propName]) { + this.node.state[this.propName].length = 0; + const updatedVal = this._value.toArray().map((vec) => vec.clone()); + this.node.state[this.propName].push(...updatedVal); + } + } + + onPropChange(_oldVal: any, newVal: any) { + this.handleEnvelopeChange(newVal); - onPropChange() {} + this.output && this.output.setData(newVal); + } private currHitPoint: ListNode; private lastDownPosition: Vector; diff --git a/src/utils/linked-list.ts b/src/utils/linked-list.ts index 2bdca7c8..c7c66add 100644 --- a/src/utils/linked-list.ts +++ b/src/utils/linked-list.ts @@ -7,7 +7,7 @@ export class List extends Hooks { constructor(public comparator?: (a: T, b: T) => number, source?: Array) { super(); - if (source) source.forEach(value => this.append(value)); + if (source) source.forEach((value) => this.append(value)); } prepend(data: T) { @@ -22,7 +22,7 @@ export class List extends Hooks { } this.length += 1; - this.call('prepend', this, newNode); + this.call("prepend", this, newNode); return newNode; } append(data: T | ListNode) { @@ -37,7 +37,7 @@ export class List extends Hooks { } this.length += 1; - this.call('append', this, newNode); + this.call("append", this, newNode); return newNode; } removeFirst(hook: boolean = true): T { @@ -54,7 +54,7 @@ export class List extends Hooks { } this.length -= 1; - if (hook) this.call('removefirst', this, removed); + if (hook) this.call("removefirst", this, removed); return removed; } removeLast(): T { @@ -71,7 +71,7 @@ export class List extends Hooks { } this.length -= 1; - this.call('removelast', this, removed); + this.call("removelast", this, removed); return removed; } addAfter(data: T, node: ListNode): ListNode { @@ -100,11 +100,8 @@ export class List extends Hooks { if (this.length === 1) { this.head = null; this.tail = null; - } - else if (node === this.head) - this.removeFirst(); - else if (node === this.tail) - this.removeLast(); + } else if (node === this.head) this.removeFirst(); + else if (node === this.tail) this.removeLast(); else { if (node.prev) node.prev.next = node.next; if (node.next) node.next.prev = node.prev; @@ -130,7 +127,7 @@ export class List extends Hooks { get(index: number): T { if (index >= this.length) return null; else if (index === 0) return this.head ? this.head.data : null; - else if (index === (this.length - 1)) return this.tail ? this.tail.data : null; + else if (index === this.length - 1) return this.tail ? this.tail.data : null; else { let count = 0; let curr = this.head; @@ -152,16 +149,16 @@ export class List extends Hooks { } map(callback: (node: ListNode) => any): any[] { let mapped: any[] = []; - this.forEach(node => mapped.push(callback(node))); + this.forEach((node) => mapped.push(callback(node))); return mapped; } toArray(): T[] { let data: T[] = []; - this.forEach(node => data.push(node.data)); + this.forEach((node) => data.push(node.data)); return data; } toString(): string { - return this.toArray().join(', '); + return this.toArray().join(", "); } } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index dd86bb60..afe0805e 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -79,3 +79,10 @@ export const cloneAudioBuffer = (from: AudioBuffer): AudioBuffer => { } return cloned; }; +export const isVector = (obj: any) => { + return ( + typeof obj === "object" && + obj && + Object.keys(obj).every((k) => ["x", "y"].includes(k) && typeof obj[k] === "number") + ); +};