💥 Graph.deserialize is now async
This commit is contained in:
28
src/graph.js
28
src/graph.js
@@ -18,17 +18,19 @@ export default class Graph {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static deserialize(nodes) {
|
static async deserialize(nodes) {
|
||||||
const graph = new Graph();
|
const graph = new Graph();
|
||||||
graph.nodes = createNodes(nodes);
|
graph.nodes = await createNodes(nodes);
|
||||||
for (let {node} of graph.nodes) {
|
for (let {node} of graph.nodes) {
|
||||||
node.subject.on('running', (isRunning) => {
|
node.subject.on('running', (isRunning) => {
|
||||||
graph.__nodesActive += isRunning ? 1 : -1;
|
graph.__nodesActive += isRunning ? 1 : -1;
|
||||||
clearTimeout(graph.__nodesActiveDebounce);
|
clearTimeout(graph.__nodesActiveDebounce);
|
||||||
graph.__nodesActiveDebounce = setTimeout(() => {
|
graph.__nodesActiveDebounce = setTimeout(() => {
|
||||||
if (graph.__nodesActive > 0) {
|
if (graph.__nodesActive > 0) {
|
||||||
|
console.log('running');
|
||||||
graph.subject.next('running');
|
graph.subject.next('running');
|
||||||
} else {
|
} else {
|
||||||
|
console.log('stopped');
|
||||||
graph.subject.next('stopped');
|
graph.subject.next('stopped');
|
||||||
}
|
}
|
||||||
}, 16);
|
}, 16);
|
||||||
@@ -65,31 +67,31 @@ export default class Graph {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const createNode = ({name, options, id}) => {
|
export const createNode = async ({name, options, id}) => {
|
||||||
try {
|
try {
|
||||||
const node = new nodes[name](options);
|
const node = new nodes[name](options);
|
||||||
node.deserialize({id, options});
|
await node.deserialize({id, options});
|
||||||
return node;
|
return node;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to create node', name, err)
|
console.error('Failed to create node', name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createNodes = (nodes) => {
|
export const createNodes = async (nodes) => {
|
||||||
nodes = nodes.map(({node, x, y}) => {
|
nodes = (await Promise.all(nodes.map(async ({node, x, y}) => {
|
||||||
const nodeInstance = createNode(node);
|
const nodeInstance = await createNode(node);
|
||||||
return ({
|
return ({
|
||||||
node: nodeInstance,
|
node: nodeInstance,
|
||||||
x, y,
|
x, y,
|
||||||
connect(outputs) {
|
async connect(outputs) {
|
||||||
try {
|
try {
|
||||||
nodeInstance.reconnect(node, outputs);
|
await nodeInstance.reconnect(node, outputs);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error('Can\'t recoonect', nodeInstance, err);
|
console.error('Can\'t recoonect', nodeInstance, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).filter(({node}) => node);
|
}))).filter(({node}) => node);
|
||||||
|
|
||||||
const outputsById = nodes
|
const outputsById = nodes
|
||||||
.map(({node}) => Object.values(node.out.__values))
|
.map(({node}) => Object.values(node.out.__values))
|
||||||
@@ -99,8 +101,8 @@ export const createNode = ({name, options, id}) => {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return nodes.map(({node, x, y, connect}) => {
|
return await Promise.all(nodes.map(async ({node, x, y, connect}) => {
|
||||||
connect(outputsById);
|
await connect(outputsById);
|
||||||
return {node,x,y};
|
return {node,x,y};
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
async loadFont(font) {
|
||||||
if (typeof font === 'string') {
|
if (typeof font === 'string') {
|
||||||
return font
|
return font;
|
||||||
} else if (!font) {
|
} else if (!font) {
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
return font.name;
|
return font.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +78,7 @@ export default class Resize extends Canvas2d {
|
|||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
|
|
||||||
ctx.font = `${fontStyle} ${fontSize}px "${(await this.loadFont(font)) || ''}"`;
|
ctx.font = `${fontStyle} ${fontSize}px "${(await this.loadFont(font)) || ''}"`;
|
||||||
|
// ctx.font = `${fontStyle} ${fontSize}px "Arial"`;
|
||||||
ctx.fillStyle = color;
|
ctx.fillStyle = color;
|
||||||
ctx.textAlign = textAlign;
|
ctx.textAlign = textAlign;
|
||||||
const x = textAlign === 'center' ? canvas.width /2 :
|
const x = textAlign === 'center' ? canvas.width /2 :
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ export default class Node {
|
|||||||
|
|
||||||
__update(changes) {
|
__update(changes) {
|
||||||
if (!this.__scheduledUpdate && !this._stopped) {
|
if (!this.__scheduledUpdate && !this._stopped) {
|
||||||
|
this._running = true;
|
||||||
this.__scheduledUpdate = true;
|
this.__scheduledUpdate = true;
|
||||||
this.__currentUpdate = this.__currentUpdate
|
this.__currentUpdate = this.__currentUpdate
|
||||||
.then(() => {
|
|
||||||
this._running = true;
|
|
||||||
})
|
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const startTag =`graphfx-update-start:${this.uid}`;
|
const startTag =`graphfx-update-start:${this.uid}`;
|
||||||
const endTag = `graphfx-update-end:${this.uid}`
|
const endTag = `graphfx-update-end:${this.uid}`
|
||||||
@@ -35,10 +33,10 @@ export default class Node {
|
|||||||
performance.measure(`GraphFX<${this.name}>`, startTag, endTag)
|
performance.measure(`GraphFX<${this.name}>`, startTag, endTag)
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this._running = false;
|
this._running = this.__scheduledUpdate;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this._running = false;
|
this._running = this.__scheduledUpdate;
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -84,11 +82,11 @@ export default class Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize({id, options}) {
|
async deserialize({id, options}) {
|
||||||
this.id = id || uuidv4();
|
this.id = id || uuidv4();
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnect({options}, outputs) {
|
async reconnect({options}, outputs) {
|
||||||
for (let name of Object.keys(options.in)) {
|
for (let name of Object.keys(options.in)) {
|
||||||
const {output} = options.in[name];
|
const {output} = options.in[name];
|
||||||
if (output) {
|
if (output) {
|
||||||
@@ -96,10 +94,10 @@ export default class Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let name of Object.keys(options.out)) {
|
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)) {
|
for (let name of Object.keys(options.in)) {
|
||||||
this.in[name].deserialize(options.in[name]);
|
await this.in[name].deserialize(options.in[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
57
src/nodes/Synchronize.js
Normal file
57
src/nodes/Synchronize.js
Normal file
@@ -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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -51,8 +51,8 @@ export default class Input extends AbstractIO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize({value, label}) {
|
async deserialize({value, label}) {
|
||||||
const deserializedValue = deserialize(value);
|
const deserializedValue = await deserialize(value);
|
||||||
if (deserializedValue) {
|
if (deserializedValue) {
|
||||||
this.value = deserializedValue;
|
this.value = deserializedValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,22 @@ const deserializeImage = ({src}) => {
|
|||||||
return img;
|
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 :
|
return isNil(value) ? value :
|
||||||
value.type === 'image' ? deserializeImage(value) :
|
value.type === 'image' ? await deserializeImage(value) :
|
||||||
|
value.type === 'font' ? await deserializeFont(value) :
|
||||||
value;
|
value;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user