diff --git a/src/graph.js b/src/graph.js index 01dde98..d624570 100644 --- a/src/graph.js +++ b/src/graph.js @@ -18,17 +18,19 @@ export default class Graph { })); } - static deserialize(nodes) { + static async deserialize(nodes) { const graph = new Graph(); - graph.nodes = createNodes(nodes); + graph.nodes = await createNodes(nodes); for (let {node} of graph.nodes) { node.subject.on('running', (isRunning) => { graph.__nodesActive += isRunning ? 1 : -1; clearTimeout(graph.__nodesActiveDebounce); graph.__nodesActiveDebounce = setTimeout(() => { if (graph.__nodesActive > 0) { + console.log('running'); graph.subject.next('running'); } else { + console.log('stopped'); graph.subject.next('stopped'); } }, 16); @@ -65,31 +67,31 @@ export default class Graph { -export const createNode = ({name, options, id}) => { +export const createNode = async ({name, options, id}) => { try { const node = new nodes[name](options); - node.deserialize({id, options}); + await node.deserialize({id, options}); return node; } catch (err) { console.error('Failed to create node', name, err) } } - export const createNodes = (nodes) => { - nodes = nodes.map(({node, x, y}) => { - const nodeInstance = createNode(node); + export const createNodes = async (nodes) => { + nodes = (await Promise.all(nodes.map(async ({node, x, y}) => { + const nodeInstance = await createNode(node); return ({ node: nodeInstance, x, y, - connect(outputs) { + async connect(outputs) { try { - nodeInstance.reconnect(node, outputs); + await nodeInstance.reconnect(node, outputs); } catch(err) { console.error('Can\'t recoonect', nodeInstance, err); } } }); - }).filter(({node}) => node); + }))).filter(({node}) => node); const outputsById = nodes .map(({node}) => Object.values(node.out.__values)) @@ -99,8 +101,8 @@ export const createNode = ({name, options, id}) => { return acc; }, {}); - return nodes.map(({node, x, y, connect}) => { - connect(outputsById); + return await Promise.all(nodes.map(async ({node, x, y, connect}) => { + await connect(outputsById); return {node,x,y}; - }) + })) } diff --git a/src/nodes/Canvas2d/Text.js b/src/nodes/Canvas2d/Text.js index 61a01f6..a2f8f74 100644 --- a/src/nodes/Canvas2d/Text.js +++ b/src/nodes/Canvas2d/Text.js @@ -61,27 +61,14 @@ export default class Resize extends Canvas2d { /** * - * @param {{name: string, url: string, fontface: FontFace}} font + * @param {{name: string, url: string, fontface: FontFace, type: 'font'}} font */ async loadFont(font) { if (typeof font === 'string') { - return font + return font; } else if (!font) { return; - } - - if (font.name && !font.url && !font.fontface) { - return name; - } - if (font.name && font.url && isEmpty(font.fontface)) { - font.fontface = new FontFace(font.name, font.url); - } - - if (font.fontface) { - await font.fontface.load(); - if (!document.fonts.has(font.fontface)) { - await document.fonts.add(font.fontface) - } + } else { return font.name; } } @@ -91,6 +78,7 @@ export default class Resize extends Canvas2d { canvas.height = height; ctx.font = `${fontStyle} ${fontSize}px "${(await this.loadFont(font)) || ''}"`; + // ctx.font = `${fontStyle} ${fontSize}px "Arial"`; ctx.fillStyle = color; ctx.textAlign = textAlign; const x = textAlign === 'center' ? canvas.width /2 : diff --git a/src/nodes/Node.js b/src/nodes/Node.js index 4781fd5..1e44d46 100644 --- a/src/nodes/Node.js +++ b/src/nodes/Node.js @@ -20,11 +20,9 @@ export default class Node { __update(changes) { if (!this.__scheduledUpdate && !this._stopped) { + this._running = true; this.__scheduledUpdate = true; this.__currentUpdate = this.__currentUpdate - .then(() => { - this._running = true; - }) .then(async () => { const startTag =`graphfx-update-start:${this.uid}`; const endTag = `graphfx-update-end:${this.uid}` @@ -35,10 +33,10 @@ export default class Node { performance.measure(`GraphFX<${this.name}>`, startTag, endTag) }) .then(() => { - this._running = false; + this._running = this.__scheduledUpdate; }) .catch((err) => { - this._running = false; + this._running = this.__scheduledUpdate; throw err; }); } @@ -84,11 +82,11 @@ export default class Node { } } - deserialize({id, options}) { + async deserialize({id, options}) { this.id = id || uuidv4(); } - reconnect({options}, outputs) { + async reconnect({options}, outputs) { for (let name of Object.keys(options.in)) { const {output} = options.in[name]; if (output) { @@ -96,10 +94,10 @@ export default class Node { } } for (let name of Object.keys(options.out)) { - this.out[name].deserialize(options.out[name]); + await this.out[name].deserialize(options.out[name]); } for (let name of Object.keys(options.in)) { - this.in[name].deserialize(options.in[name]); + await this.in[name].deserialize(options.in[name]); } } diff --git a/src/nodes/Synchronize.js b/src/nodes/Synchronize.js new file mode 100644 index 0000000..b49b4a6 --- /dev/null +++ b/src/nodes/Synchronize.js @@ -0,0 +1,57 @@ +import Node from './Node'; + +export default class Numbers extends Node { + constructor() { + super('Synchronize', { + first: { + type: 'Image', + default: 0, + }, + second: { + type: 'Image', + default: 0, + }, + }, { + first: { + type: 'Image', + default: 0, + }, + second: { + type: 'Image', + default: 0, + }, + }, {}); + this.__changed = { + first: false, + second: false, + }; + this.in.first.onchange((value) => { + if (value) { + console.log('first hit', value) + this.__changed.first = true; + } + }); + this.in.second.onchange((value) => { + if (value) { + console.log('second hit', value) + this.__changed.second = true; + } + }); + } + + async _update() { + const {first, second} = this.__changed; + if (first && second) { + console.log('synced') + this.out.first.value = this.in.first.value; + this.out.second.value = this.in.second.value; + this.__changed = { + first: false, + second: false, + }; + } else { + console.log('not synced') + } + } + +} \ No newline at end of file diff --git a/src/nodes/io/Input.js b/src/nodes/io/Input.js index d4ae721..f230f07 100644 --- a/src/nodes/io/Input.js +++ b/src/nodes/io/Input.js @@ -51,8 +51,8 @@ export default class Input extends AbstractIO { } } - deserialize({value, label}) { - const deserializedValue = deserialize(value); + async deserialize({value, label}) { + const deserializedValue = await deserialize(value); if (deserializedValue) { this.value = deserializedValue; } diff --git a/src/nodes/io/serializer.js b/src/nodes/io/serializer.js index d2b6dfa..fb258ec 100644 --- a/src/nodes/io/serializer.js +++ b/src/nodes/io/serializer.js @@ -16,8 +16,22 @@ const deserializeImage = ({src}) => { return img; } -export const deserialize = (value) => { +const deserializeFont = async (font) => { + try { + font.fontface = new FontFace(font.name, font.url); + await font.fontface.load(); + if (!document.fonts.has(font.fontface)) { + await document.fonts.add(font.fontface) + } + } catch(err) { + console.warn('Failed to load font', err) + } + return font; +} + +export const deserialize = async (value) => { return isNil(value) ? value : - value.type === 'image' ? deserializeImage(value) : + value.type === 'image' ? await deserializeImage(value) : + value.type === 'font' ? await deserializeFont(value) : value; } \ No newline at end of file