Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
# Runs on pushes targeting the default branch
push:
branches: ["feature/functions"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: 'src'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/assets/starter.json

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@
</div>
</div>
<div class="left-panel-content">
<div id="input-params-section" class="hidden">
<div id="input-params" class="left-panel-tab">Input Parameters <div id="input-params-arrow"
style="position: absolute; right: 0.7rem; transition: 0.1s;"><i class="fas fa-chevron-down"></i></div>
</div>
<div id="input-params-content" class="left-panel-tab-content"></div>
</div>
<div id="output-params-section" class="hidden">
<div id="output-params" class="left-panel-tab">Output Parameters <div id="output-params-arrow"
style="position: absolute; right: 0.7rem; transition: 0.1s;"><i class="fas fa-chevron-down"></i></div>
</div>
<div id="output-params-content" class="left-panel-tab-content"></div>
</div>
<div id="doc-string-section" class="hidden">
<div id="doc-string" class="left-panel-tab">Description <div id="doc-string-arrow"
style="position: absolute; right: 0.7rem; transition: 0.1s;"><i class="fas fa-chevron-down"></i></div>
</div>
<div id="doc-string-content" class="left-panel-tab-content">
<div class="left-panel-section-inner">
<textarea id="doc-string-input" class="doc-string-textarea" placeholder="Describe what this function does..." rows="3"></textarea>
</div>
</div>
</div>
<div id="update-callers-section" class="hidden">
<div class="left-panel-section-inner" style="padding: 0.5rem 0;">
<button type="button" id="update-callers-btn" class="update-callers-btn" title="Update all Call nodes for this function to the current definition">Update callers</button>
</div>
</div>
<div id="add-variables" class="left-panel-tab">Add Variable <div id="add-variables-plus-icon"
style="position: absolute; right: 0.7rem; transition: 0.1s;"><i class="fas fa-chevron-down"></i></div>
</div>
Expand Down Expand Up @@ -64,8 +91,20 @@
</ul>
</div>
</div>
<div id="list-of-functions" class="left-panel-tab">Functions<div id="list-of-functions-down-icon"
style="position: absolute; right: 0.7rem; transition: 0.1s;"><i class="fas fa-chevron-down"></i></div>
</div>
<div id="list-of-functions-content" class="left-panel-tab-content">
<div class="variableList" style="width: 100%;">
<ul id="function-list" class="param-list"></ul>
</div>
</div>
</div>
</div>
<div id="tab-bar">
<div id="tab-list"></div>
<button id="add-tab-btn" title="Add Function">+</button>
</div>
<div id="container">

</div>
Expand Down
42 changes: 27 additions & 15 deletions src/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,49 @@ import { Export, Import, Save, prompLastSave } from './persistence/saveAndLoad.j
import { showAlert, prompRefreshOrStarter } from './ui/dialogs.js'
import { refresh } from './compiler/codePreview.js'
import { enableNodeGroups } from './editor/nodeGroup.js'
// var width = window.innerWidth;
// var height = window.innerHeight;
import { tabManager } from './editor/tabManager.js'
import { initFunctionPanel } from './ui/functionPanel.js'

let stage = AppStage.getStage(document.getElementById("container").clientWidth, document.getElementById("container").clientHeight, 'container');
var layer = new Konva.Layer({
id: 'main_layer'
});
let wireLayer = new Konva.Layer({
id: 'wireLayer',
});
let dragLayer = new Konva.Layer({
id: 'dragLayer',
});
stage.add(wireLayer);
stage.add(layer);
stage.add(dragLayer);
layer.moveToBottom();
stage.container().style.backgroundPosition = `${stage.position().x} ${stage.position().y}`;

// stage.on("wheel", () => {
// if (inputIsFocused) {
// document.getElementById("number-ip").blur();
// document.getElementById("string-ip").blur();
// document.getElementById("bool-ip").blur();
// }
// });
tabManager.init(stage, layer, wireLayer, dragLayer);

// SelectionBox.setSelectionBox(layer, stage);
enableNodeGroups(stage, layer);
enableNodeGroups(stage);
Delete.enableDelete(stage, layer);
// DragAndDrop.DragAndDrop(stage, layer);
Wiring.enableWiring(stage, layer);
ContextMenu.contextMenu(stage, layer);
Wiring.enableWiring(stage);
ContextMenu.contextMenu(stage);
let panel = new leftPanel();
variableList.init(layer, stage);
// layer.toggleHitCanvas();
// document.getElementById("number-ip").value = 12;
tabManager.getTab('main').variables = variableList.variables;
initFunctionPanel();
layer.draw();

document.getElementById('add-tab-btn').addEventListener('click', () => {
const name = prompt('Enter function name:');
if (name && name.trim()) {
tabManager.createTab(name.trim());
}
});

tabManager.on('tabSwitched', ({ to }) => {
variableList.layer = to.layer;
variableList.switchToTab(to.variables);
});
document.getElementById("Run").addEventListener("click", (e) => {
try {
let script = new VSToJS(stage, layer, "Run").script;
Expand Down
116 changes: 114 additions & 2 deletions src/js/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { variableList } from '../ui/variableList.js'
import { showAlert } from '../ui/dialogs.js'
import { BuilInFunctions } from './builtInFunctions.js'
import { runExecCodegen, runExprCodegen, hasType } from '../registry/index.js'
import { tabManager } from '../editor/tabManager.js'
export var VSToJS = class {

constructor(stage, layer, isRunOrCode) {
Expand All @@ -10,7 +11,13 @@ export var VSToJS = class {
this.nodeCount = 0;
this.isRunOrCode = isRunOrCode;
this.compileIssues = [];
for (let variable of variableList.variables) {
this._callCounter = 0;

this.compileFunctionTabs();

const mainTab = tabManager.getTab('main');
const globalVars = mainTab ? mainTab.variables : variableList.variables;
for (let variable of globalVars) {
this.script += `let ${variable.name} = ${variable.value};\n`;
}
let begin = this.getBegin(stage);
Expand Down Expand Up @@ -88,6 +95,33 @@ export var VSToJS = class {
}
}
}
compileFunctionTabs() {
const funcTabs = tabManager.getAllFunctionTabs();
for (const tab of funcTabs) {
const funcBegin = tab.layer.findOne('#FunctionBegin');
if (!funcBegin) continue;

const params = tab.inputParams.map(p => p.name).join(', ');
const savedScript = this.script;
this.script = '';

if (tab.variables && tab.variables.length > 0) {
for (const v of tab.variables) {
this.script += `let ${v.name} = ${v.value};\n`;
}
}

const execOutPins = this.getExecOut(funcBegin);
for (let each of execOutPins) {
this.coreAlgorithm(each);
}

const bodyScript = this.script;
this.script = savedScript;
this.script += `function ${tab.name}(${params}) {\n${bodyScript}}\n`;
}
}

getBegin(stage) {
let X = stage.find("#Begin");
if (X.length == 0) {
Expand Down Expand Up @@ -127,7 +161,8 @@ export var VSToJS = class {
X.push({ node: aNode.wire.attrs.src.getParent(), isWire: true, wire: aNode.wire, srcOutputPinNumber: this.getSrcOutputPinNumber(aNode.wire.attrs.src.getParent(), aNode.wire) });
}
else {
X.push({ node: aNode.textBox.textBox.text(), isWire: false, wire: null, srcOutputPinNumber: null });
const val = aNode.textBox ? aNode.textBox.textBox.text() : 'undefined';
X.push({ node: val, isWire: false, wire: null, srcOutputPinNumber: null });
}
}
return X;
Expand All @@ -144,6 +179,54 @@ export var VSToJS = class {
return;
}

const nodeType = node.customClass.type.typeOfNode;

if (nodeType === 'FunctionBegin') {
let execOutPins = this.getExecOut(node);
for (let each of execOutPins) {
this.coreAlgorithm(each);
}
return;
}

if (nodeType === 'Return') {
let inputPins = this.getInputPins(node);
if (inputPins.length > 0) {
const nd = node.customClass.nodeDescription;
const outputNames = [];
if (nd.inputs) {
for (const key of Object.keys(nd.inputs)) {
outputNames.push(nd.inputs[key].inputTitle);
}
}
if (inputPins.length === 1) {
this.script += `return ${this.handleInputs(inputPins[0])};\n`;
} else {
const pairs = outputNames.map((name, i) =>
`${name}: ${this.handleInputs(inputPins[i])}`
).join(', ');
this.script += `return { ${pairs} };\n`;
}
} else {
this.script += `return;\n`;
}
return;
}

if (nodeType.startsWith('Call ')) {
let inputPins = this.getInputPins(node);
let execOutPins = this.getExecOut(node);
const funcName = node.customClass.nodeDescription.calledFunctionName || nodeType.slice(5);
const args = inputPins.map(ip => this.handleInputs(ip)).join(', ');
const varName = `_call_${funcName}_${this._callCounter++}`;
this.script += `let ${varName} = ${funcName}(${args});\n`;
node._callResultVar = varName;
for (let each of execOutPins) {
this.coreAlgorithm(each);
}
return;
}

let execOutPins = this.getExecOut(node);
let inputPins = this.getInputPins(node);
if (node.customClass.type.isGetSet) {
Expand Down Expand Up @@ -176,6 +259,35 @@ export var VSToJS = class {
return "undefined";
}

const nodeType = inputNode.node.customClass.type.typeOfNode;

if (nodeType === 'FunctionBegin') {
const nd = inputNode.node.customClass.nodeDescription;
if (nd.outputs) {
const outputKey = `output${inputNode.srcOutputPinNumber}`;
const paramName = nd.outputs[outputKey]?.outputTitle;
if (paramName) return paramName;
}
return 'undefined';
}

if (nodeType.startsWith('Call ')) {
const resultVar = inputNode.node._callResultVar;
if (resultVar) {
const nd = inputNode.node.customClass.nodeDescription;
if (nd.outputs) {
const outputKeys = Object.keys(nd.outputs);
if (outputKeys.length === 1) {
return resultVar;
}
const outputName = nd.outputs[`output${inputNode.srcOutputPinNumber}`]?.outputTitle;
if (outputName) return `${resultVar}.${outputName}`;
}
return resultVar;
}
return 'undefined';
}

let inputPins = this.getInputPins(inputNode.node);
if (inputNode.node.customClass.type.isGetSet) {
return `${inputNode.node.customClass.type.typeOfNode.slice(4)}`;
Expand Down
3 changes: 3 additions & 0 deletions src/js/core/colorMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export const colorMap = {
'Get': '#2e7d32', // Array / access – green
'Str': '#ad1457', // String – pink/magenta
'Obj': '#00695c', // Object / Map – teal
'FunctionBegin': '#ff6d00', // Function entry – warm orange
'Return': '#d50000', // Function exit – red
'Call': '#00bfa5', // Function call – teal
'GroupBody': 'rgba(255, 255, 255, 0.31)',
'GroupBorder': 'rgba(255,255,255,0.3)',
'GroupTitleBar': 'rgba(41,68,150,0.8)',
Expand Down
Loading
Loading