diff --git a/app/state.js b/app/state.js index 5ba40498..31755ede 100644 --- a/app/state.js +++ b/app/state.js @@ -1,9 +1,52 @@ + +import R from 'ramda'; + import * as EDITOR_MODE from './constants/editorModes'; import * as NODE_CATEGORY from './constants/nodeCategory'; import * as PIN_DIRECTION from './constants/pinDirection'; import * as PIN_TYPE from './constants/pinType'; import { PROPERTY_TYPE, PROPERTY_DEFAULT_VALUE } from './constants/property'; +const nodeMetas = { + button: require('../nodes/meta/button.json5'), + either: require('../nodes/meta/either.json5'), + latch: require('../nodes/meta/latch.json5'), + led: require('../nodes/meta/led.json5'), + map: require('../nodes/meta/map.json5'), + not: require('../nodes/meta/not.json5'), + pot: require('../nodes/meta/pot.json5'), + servo: require('../nodes/meta/servo.json5'), +}; + +R.mapDirectedNodeTypePins = (direction, collectionKey) => R.compose( + R.indexBy(R.prop('key')), + R.addIndex(R.map)((pin, index) => R.merge({ index, direction }, pin)), + R.propOr([], collectionKey) +); + +const mapNodeTypePins = meta => R.merge( + R.mapDirectedNodeTypePins(PIN_DIRECTION.INPUT, 'inputs')(meta), + R.mapDirectedNodeTypePins(PIN_DIRECTION.OUTPUT, 'outputs')(meta) +); + +const nodeTypes = R.compose( + R.indexBy(R.prop('id')), + R.values, + R.mapObjIndexed((meta, key, metas) => R.merge( + R.omit(['inputs', 'outputs'], meta), + { + id: R.indexOf(key, R.keys(metas)) + 1, + key, + pins: mapNodeTypePins(meta) + } + )) +)(nodeMetas); + +const maxKey = R.compose( + R.reduce(R.max, -Infinity), + R.keys +); + const initialState = { project: { meta: { @@ -13,323 +56,26 @@ const initialState = { patches: { 1: { id: 1, - name: 'Skynet', - nodes: { - 1: { - id: 1, - typeId: 4, - label: 'Blue LED', - position: { - x: 320, - y: 120, - }, - }, - 2: { - id: 2, - typeId: 1, - position: { - x: 360, - y: 300, - }, - }, - 3: { - id: 3, - typeId: 3, - label: 'My potentiometer with a knob', - position: { - x: 160, - y: 90, - }, - }, - 4: { - id: 4, - typeId: 2, - position: { - x: 170, - y: 380, - }, - }, - 5: { - id: 5, - typeId: 5, - position: { - x: 100, - y: 185, - }, - }, - }, - pins: { - 1: { - id: 1, - nodeId: 1, - key: 'brightness', - }, - 2: { - id: 2, - nodeId: 2, - key: 'in', - }, - 3: { - id: 3, - nodeId: 2, - key: 'out', - }, - 4: { - id: 4, - nodeId: 3, - key: 'out', - }, - 5: { - id: 5, - nodeId: 4, - key: 'in', - }, - 6: { - id: 6, - nodeId: 4, - key: 'ifFalse', - }, - 7: { - id: 7, - nodeId: 4, - key: 'ifTrue', - }, - 8: { - id: 8, - nodeId: 4, - key: 'out', - }, - 9: { - id: 9, - nodeId: 5, - key: 'value', - }, - }, - links: { - 1: { - id: 1, - pins: [4, 1], - }, - 2: { - id: 2, - pins: [4, 6], - }, - }, + name: 'Main', + nodes: {}, + pins: {}, + links: {}, }, 2: { id: 2, - name: 'test', - nodes: { - 6: { - id: 6, - typeId: 4, - label: 'test', - position: { - x: 200, - y: 200, - }, - }, - }, - pins: { - 10: { - id: 10, - nodeId: 6, - key: 'brightness', - }, - }, - }, - }, - nodeTypes: { - 1: { - id: 1, - label: 'Not', - category: NODE_CATEGORY.FUNCTIONAL, - pins: { - in: { - key: 'in', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.INPUT, - index: 0, - }, - out: { - key: 'out', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - }, - 2: { - id: 2, - label: 'Either', - category: NODE_CATEGORY.FUNCTIONAL, - pins: { - in: { - key: 'in', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.INPUT, - label: 'IN', - index: 0, - }, - ifTrue: { - key: 'ifTrue', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.INPUT, - label: 'T', - index: 1, - }, - ifFalse: { - key: 'ifFalse', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.INPUT, - label: 'F', - index: 2, - }, - out: { - key: 'out', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - }, - 3: { - id: 3, - label: 'Pot', - category: NODE_CATEGORY.HARDWARE, - pins: { - out: { - key: 'out', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - }, - 4: { - id: 4, - label: 'LED', - category: NODE_CATEGORY.HARDWARE, - pins: { - brightness: { - key: 'brightness', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.INPUT, - index: 0, - }, - }, - }, - 5: { - id: 5, - label: 'Servo', - category: NODE_CATEGORY.HARDWARE, - pins: { - value: { - key: 'value', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.INPUT, - index: 0, - }, - }, - }, - 6: { - id: 6, - label: 'Constant:Bool', - category: NODE_CATEGORY.CONFIGURATION, - pins: { - value: { - key: 'value', - type: PIN_TYPE.BOOL, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - properties: { - value: { - key: 'value', - label: 'Value', - type: PROPERTY_TYPE.BOOL, - defaultValue: PROPERTY_DEFAULT_VALUE.BOOL, - }, - }, - }, - 7: { - id: 7, - label: 'Constant:Number', - category: NODE_CATEGORY.CONFIGURATION, - pins: { - value: { - key: 'value', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - properties: { - value: { - key: 'value', - label: 'Value', - type: PROPERTY_TYPE.NUMBER, - defaultValue: PROPERTY_DEFAULT_VALUE.NUMBER, - }, - }, - }, - 8: { - id: 8, - label: 'Constant:String', - category: NODE_CATEGORY.CONFIGURATION, - pins: { - value: { - key: 'value', - type: PIN_TYPE.STRING, - direction: PIN_DIRECTION.OUTPUT, - index: 0, - }, - }, - properties: { - value: { - key: 'value', - label: 'Value', - type: PROPERTY_TYPE.STRING, - defaultValue: PROPERTY_DEFAULT_VALUE.STRING, - }, - }, - }, - 9: { - id: 9, - label: 'IMU', - category: NODE_CATEGORY.HARDWARE, - pins: { - yaw: { - key: 'yaw', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.OUTPUT, - label: 'YAW', - index: 0, - }, - pitch: { - key: 'pitch', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.OUTPUT, - label: 'PIT', - index: 1, - }, - roll: { - key: 'roll', - type: PIN_TYPE.NUMBER, - direction: PIN_DIRECTION.OUTPUT, - label: 'ROL', - index: 2, - }, - }, + name: 'AUX', + nodes: {}, + pins: {}, + links: {}, }, }, + nodeTypes, counter: { - patches: 2, - nodes: 6, - pins: 10, - links: 2, - nodeTypes: 9, + patches: 1, + nodes: 1, + pins: 1, + links: 1, + nodeTypes: +maxKey(nodeTypes) + 1, }, }, editor: { diff --git a/nodes/meta/button.json5 b/nodes/meta/button.json5 new file mode 100644 index 00000000..ddda5549 --- /dev/null +++ b/nodes/meta/button.json5 @@ -0,0 +1,7 @@ +{ + outputs: [{ + key: 'state', + type: 'bool', + description: 'Emits `true` when pressed and `false` when released', + }], +} diff --git a/nodes/meta/either.json5 b/nodes/meta/either.json5 new file mode 100644 index 00000000..dbd37e71 --- /dev/null +++ b/nodes/meta/either.json5 @@ -0,0 +1,24 @@ +{ + inputs: [{ + key: 'inp', + label: 'IN', + type: 'bool', + description: 'Selector value' + }, { + key: 'trueValue', + label: 'T', + type: 'number', + description: 'Output if selector is `true`' + }, { + key: 'falseValue', + label: 'F', + type: 'number', + description: 'Output if selector is `false`' + }], + outputs: [{ + name: 'out', + type: 'number', + description: 'Selected output value', + }], +} + diff --git a/nodes/meta/latch.json5 b/nodes/meta/latch.json5 new file mode 100644 index 00000000..0410ac36 --- /dev/null +++ b/nodes/meta/latch.json5 @@ -0,0 +1,24 @@ +{ + inputs: [{ + key: 'toggle', + label: 'TGL', + type: 'pulse', + description: 'Flips current state to opposite' + }, { + key: 'set', + label: 'SET', + type: 'pulse', + description: 'Sets current state to `true`' + }, { + key: 'reset', + label: 'RST', + type: 'pulse', + description: 'Sets current state to `false`' + }], + outputs: [{ + key: 'state', + type: 'bool', + description: 'Emits current latch state when changes', + }], +} + diff --git a/nodes/meta/led.json5 b/nodes/meta/led.json5 new file mode 100644 index 00000000..7b27139c --- /dev/null +++ b/nodes/meta/led.json5 @@ -0,0 +1,8 @@ +{ + label: 'LED', + inputs: [{ + key: 'brightness', + type: 'number', + description: 'Shine brightness' + }] +} diff --git a/nodes/meta/map.json5 b/nodes/meta/map.json5 new file mode 100644 index 00000000..310bd5cb --- /dev/null +++ b/nodes/meta/map.json5 @@ -0,0 +1,38 @@ +{ + inputs: [{ + key: 'in', + label: 'IN', + type: 'number', + description: 'Input value to map' + }, { + key: 'inA', + label: 'As', + type: 'number', + description: 'Input range start' + }, { + key: 'inB', + label: 'Bs', + type: 'number', + description: 'Input range end' + }, { + key: 'outA', + label: 'At', + type: 'number', + description: 'Output range start' + }, { + key: 'outB', + label: 'Bt', + type: 'number', + description: 'Output range end' + }, { + key: 'clip', + label: 'CL', + type: 'bool', + description: 'Clip result to output range' + }], + outputs: [{ + key: 'out', + type: 'number', + description: 'Mapped value', + }], +} diff --git a/nodes/meta/not.json5 b/nodes/meta/not.json5 new file mode 100644 index 00000000..f592a9ab --- /dev/null +++ b/nodes/meta/not.json5 @@ -0,0 +1,13 @@ +{ + label: 'not', + inputs: [{ + name: 'in', + type: 'bool', + description: 'Value to be inverted' + }], + outputs: [{ + name: 'out', + type: 'bool', + description: 'Resulting inverted value', + }], +} diff --git a/nodes/meta/pot.json5 b/nodes/meta/pot.json5 new file mode 100644 index 00000000..9010664f --- /dev/null +++ b/nodes/meta/pot.json5 @@ -0,0 +1,7 @@ +{ + outputs: [{ + name: 'value', + type: 'number', + description: 'Current potentiometer value', + }] +} diff --git a/nodes/meta/servo.json5 b/nodes/meta/servo.json5 new file mode 100644 index 00000000..64830315 --- /dev/null +++ b/nodes/meta/servo.json5 @@ -0,0 +1,15 @@ +{ + inputs: [{ + name: 'enable', + label: 'EN', + type: 'bool', + defaultValue: true, + description: 'Apply torque to the shaft' + }, { + name: 'value', + label: 'VAL', + type: 'number', + defaultValue: 1, + description: 'Rotation angle/value' + }] +}