{"version":3,"sources":["_init.js","Button.js","Input.js","Logger.js","other-dummy-node.js"],"names":["_Class","_Class2","_Class3","_Class5","_Class6","_Class7","_Class8","_classPrivateFieldLooseBase","e","t","hasOwnProperty","call","TypeError","id","_classPrivateFieldLooseKey","window","globalThis","async","imports","urls","sf","loader","mjs","Promise","all","map","v","import","task","Blackprint","loadScope","url","hasInterface","Context","createContext","EventSlot","slot","consoleStyle","log","which","text","Environment","isBrowser","console","registerNode","Node","constructor","instance","super","this","setInterface","title","clicked","ev","output","Clicked","syncOut","syncIn","data","Types","Trigger","registerInterface","IFace","Button","Interface","node","imported","iface","JSON","stringify","undefined","Object","assign","Value","value","Changed","String","Input","ExampleInputData","changed","importing","_iface","_value","defineProperty","writable","val","routes","routeOut","utils","setEnumerablePrototype","description","_refreshLogger","ref","IInput","Any","cables","length","init","on","update","input","target","name","namespace","Port","ArrayOf","Logger","args","_log","setTimeout","x","multiply","A","B","_inactive_","Result","port","$decoration","warn","Number","Exec","destroy","executed","request","cable","Out","Math","round","random","Boolean","ifaceList","indexOf","B1","A1","B2","A2"],"mappings":"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","file":"nodes-example.mjs","sourcesContent":["// We don't have graphics node for non-browser :3\n// Let's just use this file to load .sf.mjs and .sf.css\n\nlet Blackprint = window.Blackprint.loadScope({\n\t// You can find the URL on Blackprint menu -> Modules\n\t// This will also be exported to JSON if this module's nodes is being used\n\turl: import.meta.url,\n\n\t// This will autoload (*.sf.mjs) and (*.sf.css) file for Browser\n\thasInterface: true,\n\n\t// This will autoload (*.docs.json) for Browser\n\t// hasDocs: true,\n});\n\n// Global shared context\nlet Context = Blackprint.createContext('Example');\n\n// This is needed to avoid duplicated event listener when using hot reload\n// Event listener that registered with same slot will be replaced\nContext.EventSlot = {slot: 'my-private-event-slot'};\n\nlet consoleStyle = \"color: yellow\";\nContext.log = function(which, ...text){\n\tif(Blackprint.Environment.isBrowser)\n\t\tconsole.log(`%c${which}:`, consoleStyle, ...text);\n\telse\n\t\tconsole.log(`\\x1b[1m\\x1b[33m${which}:\\x1b[0m`, ...text);\n}","// Register Node\n// Blackprint will handle data flow between nodes connection\n// This should be simple and contain structure only\n// Just like creating a template/base and attach an interface for extra control\nBlackprint.registerNode('Example/Button/Simple',\nclass extends Blackprint.Node {\n  static output = {\n    Clicked: Blackprint.Types.Trigger\n  };\n\n  constructor(instance){\n    super(instance);\n\n    // Must be called once\n    let iface = this.setInterface('BPIC/Example/Button');\n\n    // iface only exist after setInterface\n    iface.title = \"Button\";\n  }\n\n  // <Just for example>\n  // This can be called from Interface\n  clicked(ev){\n    Context.log('Example/Button/Simple', 'I got ', ev, \"time to trigger to the other node\");\n    this.output.Clicked(ev);\n    this.syncOut('click', true);\n  }\n\n\t// Remote sync in\n\tsyncIn(id, data){\n\t\tif(id === 'click') this.clicked();\n\t}\n});\n\n\n// Register Interface\n// Interface will be exposed to public and being attached for a node\n// it's just like API or User Interface (on sketch editor)\n// Let's think you're creating a library, these properties can be accessed by other developers\nBlackprint.registerInterface('BPIC/Example/Button',\nContext.IFace.Button = class ButtonIFace extends Blackprint.Interface {\n  clicked(ev){\n    Context.log('BPIC/Example/Button (non-HTML)', \"'Trigger' button clicked, going to run the handler\");\n    this.node.clicked?.(ev);\n  }\n});","// Register Node\n// Blackprint will handle data flow between nodes connection\n// This should be simple and contain structure only\n// Just like creating a template/base and attach an interface for extra control\nBlackprint.registerNode('Example/Input/Simple',\nclass extends Blackprint.Node {\n\t// Output Port's Template (This will be transformed to it's type after initialized)\n\tstatic output = {\n\t\tChanged: Blackprint.Types.Trigger,\n\t\tValue: String, // Default to empty string\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Example/Input'); // Let's use ./input.js\n\t\tiface.title = \"Input\";\n\t}\n\n\t// Bring value from imported node to handle output\n\timported(data){\n\t\tlet iface = this.iface;\n\n\t\tContext.log('Example/Input/Simple', \"Old data:\", JSON.stringify(iface.data));\n\t\tContext.log('Example/Input/Simple', \"Imported data:\", JSON.stringify(data));\n\n\t\tif(data === undefined) return;\n\n\t\t// Use object assign to avoid replacing the object reference\n\t\tObject.assign(iface.data, data);\n\t\tthis.output.Value = data.value;\n\t}\n\n\t// Remote sync in\n\tsyncIn(id, data){\n\t\tif(id === 'data'){\n\t\t\tObject.assign(this.iface.data, data);\n\t\t}\n\t\telse if(id === 'value'){\n\t\t\tthis.iface.data.value = data;\n\t\t}\n\t}\n});\n\n\n// Register Interface\n// Interface will be exposed to public and being attached for a node\n// it's just like API or User Interface (on sketch editor)\n// Let's think you're creating a library, these properties can be accessed by other developers\nBlackprint.registerInterface('BPIC/Example/Input',\nContext.IFace.Input = class InputIFace extends Blackprint.Interface{\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\t// You can also use\n\t\tthis.data = new ExampleInputData(this);\n\t}\n\n\t// Proxy string value from: data.value(setter) -> iface.changed -> output.Value\n\t// And also call output.Changed() if connected to other node\n\tchanged(text, ev){\n\t\tlet node = this.node;\n\n\t\t// This node still being imported\n\t\tif(this.importing !== false)\n\t\t\treturn;\n\n\t\tContext.log('Example/Input/Simple', 'The input box have new value:', text);\n\n\t\t// iface.data.value === text;\n\t\tnode.output.Value = this.data.value;\n\t\tnode.syncOut('data', {value: this.data.value});\n\n\t\t// This will call every connected node\n\t\tnode.output.Changed();\n\t}\n});\n\nclass ExampleInputData {\n\t#iface = null;\n\n\tconstructor(iface){\n\t\tthis.#iface = iface;\n\t}\n\n\t// Use underscore \"_\" or \"$\" to avoid being exported as JSON\n\t#value = '';\n\n\tget value(){ return this.#value }\n\tset value(val){\n\t\tif(this.#value === val) return;\n\t\tthis.#value = val;\n\t\tthis.#iface.changed(val);\n\t\tthis.#iface.node.routes.routeOut();\n\t}\n}\n\n// Using getter/setter will make the property not enumerable and Blackprint will skip that property when exporting\nBlackprint.utils.setEnumerablePrototype(ExampleInputData, {\n\tvalue: true,\n});","Blackprint.registerNode('Example/Display/Logger',\nclass extends Blackprint.Node {\n\tstatic input = {\n\t\tAny: Blackprint.Port.ArrayOf(Blackprint.Types.Any) // Any data type, and can be used for many cable\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Example/Logger');\n\t\tiface.title = \"Logger\";\n\t\tiface.description = 'Print anything into text';\n\t}\n\n\t_refreshLogger(val){\n\t\tif(this.ref.IInput.Any.cables.length > 1)\n\t\t\tthis.iface.log = JSON.stringify(val);\n\t\telse {\n\t\t\tlet val = this.ref.Input.Any?.[0];\n\n\t\t\tif(val === null)\n\t\t\t\tthis.iface.log = \"null\";\n\t\t\telse if(val === undefined)\n\t\t\t\tthis.iface.log = \"undefined\";\n\t\t\telse if(typeof val === 'object')\n\t\t\t\tthis.iface.log = JSON.stringify(val);\n\t\t\telse this.iface.log = val;\n\t\t}\n\t}\n\n\tinit(){\n\t\t// Let's show data after new cable was connected or disconnected\n\t\tthis.iface.on('cable.disconnect', Context.EventSlot, () => {\n\t\t\tContext.log('Logger ('+(this.iface.id || '')+')', \"A cable was changed on Logger, manual update will be triggered\");\n\n\t\t\tthis.update();\n\t\t});\n\n\t\tthis.iface.input.Any.on('value', Context.EventSlot, ({ target }) => {\n\t\t\tContext.log('Logger ('+(this.iface.id || '')+')', `I connected to port ${target.name} (${target.iface.namespace}), that have value: ${target.value}`);\n\t\t});\n\t}\n\n\tupdate(){\n\t\tlet { Input } = this.ref;\n\n\t\t// Let's take all data from all connected nodes\n\t\t// Instead showing new single data-> val\n\t\tthis._refreshLogger(Input.Any);\n\t}\n\n\t// Remote sync in\n\tsyncIn(id, data){\n\t\tif(id === 'log') this.iface.log = data;\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Example/Logger',\nContext.IFace.Logger = class extends Blackprint.Interface {\n\t_log = '...';\n\n\t// Template Binding -> https://github.com/ScarletsFiction/ScarletsFrame/wiki/Input-Binding\n\tget log(){ return this._log }\n\tset log(val){\n\t\tthis._log = val;\n\t\tContext.log(\"Logger (\"+(this.id || '')+\") Data\", val);\n\t\tthis.node.syncOut('log', val);\n\t}\n});","// These registration is using function for constructing nodes\n// Using class is more recommended for better performance and memory usage\n\n// We will use 'default' node interface and only being used as an example\nBlackprint.registerNode('Example/Math/Multiply', class extends Blackprint.Node {\n\t// Handle all output port here\n\tstatic output = { Result: Number };\n\n\t// Handle all input port here\n\tstatic input = {\n\t\tExec: Blackprint.Port.Trigger(function({ iface }){\n\t\t\tlet node = iface.node;\n\t\t\tnode.output.Result = node.multiply();\n\t\t\tContext.log('Example/Math/Multiply', \"Result has been set:\", node.output.Result);\n\n\t\t\tif(iface._inactive_){\n\t\t\t\tiface._inactive_.destroy?.();\n\t\t\t\tiface._inactive_ = false;\n\t\t\t}\n\t\t}),\n\t\tA: Number,\n\t\tB: Blackprint.Types.Any,\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface(); // Let's use default node interface\n\t\tiface.title = \"Multiply\";\n\n\t\t// If you want to test it or play around from the browser console\n\t\tsetTimeout(function(){\n\t\t\tif(!Blackprint.Environment.isBrowser) return;\n\n\t\t\tif(iface.x === undefined)\n\t\t\t\tconsole.log('Node from Engine:', iface);\n\t\t\telse\n\t\t\t\tconsole.log('Node from Sketch:', iface);\n\t\t}, 10);\n\t}\n\n\t// Your own processing mechanism\n\tmultiply(){\n\t\tlet Input = this.input;\n\n\t\tContext.log('Example/Math/Multiply', 'Multiplying', Input.A, 'with', Input.B);\n\t\treturn Input.A * Input.B;\n\t}\n\n\t// When any output value from other node are updated\n\t// Let's immediately change current node result\n\tupdate(){\n\t\tif(this.iface._inactive_) return;\n\t\tthis.output.Result = this.multiply();\n\t}\n\n\t// Event listener can only be registered after handle init\n\tinit(){\n\t\tlet iface = this.iface;\n\n\t\tiface.on('cable.connect', Context.EventSlot, function({ port, target }){\n\t\t\tContext.log('Example/Math/Multiply', `Cable connected from ${port.iface.title} (${port.name}) to ${target.iface.title} (${target.name})`);\n\t\t});\n\n\t\t// $decoration only available for Sketch (Browser)\n\t\tiface._inactive_ = iface.$decoration?.warn(\"Need activation\") || true;\n\t}\n});\n\nBlackprint.registerNode('Example/Math/Random', class extends Blackprint.Node {\n\texecuted = false;\n\n\tstatic output = { Out: Number };\n\tstatic input = {\n\t\t'Re-seed': Blackprint.Port.Trigger(function({ iface: { node } }){\n\t\t\tnode.executed = true;\n\t\t\tnode.output.Out = Math.round(Math.random()*100);\n\t\t})\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface(); // Let's use default node interface\n\t\tiface.title = \"Random\";\n\t\tiface.description = \"Number (0-100)\";\n\t}\n\n\t// When the connected node is requesting for the output value\n\trequest(cable){\n\t\t// Only run once this node never been executed\n\t\t// Return false if no value was changed\n\t\tif(this.executed === true) return false;\n\n\t\tContext.log('Example/Math/Random', 'Value request for port:', cable.output.name, \"from node:\", cable.input.iface.title);\n\n\t\t// Let's create the value for him\n\t\tthis.input['Re-seed']();\n\t}\n});\n\n// Do nothing :3\nBlackprint.registerNode('Example/Dummy/Test', class extends Blackprint.Node {\n\t// PortName must different any port\n\tstatic input = {\n\t\t\"Input 1\": Boolean,\n\t\t\"Input 2\": String\n\t};\n\n\tstatic output = {\n\t\t\"Output 1\": Object,\n\t\t\"Output 2\": Number\n\t};\n\n\t// static property = {\n\t// \t\"Property 1\": Boolean,\n\t// \t\"Property 2\": Number\n\t// };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface(); // Let's use default node interface\n\t\tiface.title = \"Do nothing\";\n\t}\n});\n\nBlackprint.registerNode('Example/Dummy/UpdateTest', class extends Blackprint.Node {\n\tstatic input = {\n\t\tA1: String,\n\t\tA2: String,\n\t};\n\n\tstatic output = {\n\t\tB1: String,\n\t\tB2: String,\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface(); // Let's use default node interface\n\t\tiface.title = \"Pass data only\";\n\n\t\t// iface.on('port.value', ({ port, target }) => {\n\t\t// \tconsole.log(port, target);\n\t\t// \tif(port.source !== 'input') return;\n\t\t// \tthis[port.name] = target.value;\n\t\t// });\n\t}\n\n\tupdate(){\n\t\tlet index = this.iface.id || this.instance.ifaceList.indexOf(this.iface);\n\t\t// console.error(\"UpdateTest \"+index+\"> Updating ports\");\n\n\t\t// if(this.input.A1 !== this.A1) console.error(\"A1 from event listener value was mismatched\");\n\t\t// if(this.input.A2 !== this.A2) console.error(\"A2 from event listener value was mismatched\");\n\n\t\tthis.output.B1 = this.input.A1;\n\t\tthis.output.B2 = this.input.A2;\n\t\t// console.log(\"UpdateTest \"+index+\"> Updated\");\n\t}\n});"]}