Files
Graph-Explorer-JS/index.html

292 lines
5.5 KiB
HTML
Raw Normal View History

2025-12-25 10:36:24 +01:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Live Snap Drag Window with Canvas</title>
</head>
<body>
<div class="top-panel">
<button id="graphExplorer">Graph Explorer</button>
<button id="resetParticlesButton">Reset Particles</button>
</div>
<div id="wireMenu" style="
position: absolute;
display: none;
background: #333;
color: #eee;
padding: 8px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
z-index: 1000;
box-shadow: 0 2px 6px rgba(0,0,0,0.8);
">
<button id="deleteWireBtn" style="background:#900; color:#fff; border:none; padding:4px 8px; cursor:pointer;">Delete Wire</button>
</div>
<!-- Node context menu -->
<div id="nodeMenu" style="
position: absolute;
display: none;
background: #333;
color: #eee;
padding: 8px;
border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 14px;
z-index: 1000;
box-shadow: 0 2px 6px rgba(0,0,0,0.8);
">
<button id="deleteNodeBtn" style="background:#900; color:#fff; border:none; padding:4px 8px; cursor:pointer;">Delete Node</button>
</div>
<link rel="stylesheet" href="./style/main.css" >
<script type="module">
function autoLayoutNodes( graphExplorer ) {
const placedNodes = new Set();
const visited = new Set();
const levels = new Map();
function dfs( node, level ) {
if ( visited.has( node ) ) return;
visited.add( node );
// Assign the current level (depth) if its deeper
if ( !levels.has( node ) || levels.get( node ) < level ) {
levels.set( node, level );
}
// Traverse all outgoing edges
for ( var i = 0; i < graphExplorer.edges.length; i++ ) {
const edge = graphExplorer.edges[i];
if ( edge.fromNode === node ) {
dfs( edge.toNode, level + 1 );
}
}
}
// Start from nodes with no incoming edges
for ( var i = 0; i < graphExplorer.nodes.length; i++ ) {
const node = graphExplorer.nodes[i];
const hasIncoming = graphExplorer.edges.some( edge => edge.toNode === node );
if ( !hasIncoming ) {
dfs( node, 0 );
}
}
// Group nodes by level
const layers = {};
for ( const [node, level] of levels ) {
if ( !layers[level] ) layers[level] = [];
layers[level].push( node );
}
const xSpacing = 400;
const yBase = 150;
for ( const levelEntry of Object.entries( layers ) ) {
const levelStr = levelEntry[0];
const nodesAtLevel = levelEntry[1];
const level = Number( levelStr );
const spacing = yBase + Math.max(...nodesAtLevel.map(n => n.inputs.length)) * 25;
for ( let i = 0; i < nodesAtLevel.length; i++ ) {
const node = nodesAtLevel[i];
const xJitter = ( Math.random() - 0.5 ) * 80; // wider jitter horizontally
const yJitter = ( Math.random() - 0.5 ) * 80; // wider jitter vertically
node.x = level * xSpacing + xJitter;
node.y = i * spacing + yJitter;
}
}
}
async function loadJSON( pathName ) {
const response = await fetch( pathName );
if ( !response.ok ) {
throw new Error( `Failed to load shader: ${ pathName }` );
}
return await response.json();
}
function getShaderByName( shaders, shaderName ) {
for (var i = 0; i < shaders.length; i++) {
var shader = shaders[i]
if( shader.name == shaderName ) {
return shader;
}
}
}
function getPortIndex( bindings, variableName ) {
for (var i = 0; i < bindings.length; i++) {
var binding = bindings[i]
if( binding.varName == variableName ) {
return i;
}
}
}
import { Node } from "./GraphExplorer.js"
import { Edge } from "./GraphExplorer.js"
import { GraphExplorer } from "./GraphExplorer.js"
import { WindowController } from "./WindowController.js"
var graphExplorer = new GraphExplorer();
const windowController = new WindowController();
windowController.setGraphExplorer( graphExplorer );
var graphCanvas = document.createElement( "canvas" );
graphCanvas.id = "graphCanvas";
graphCanvas.width = windowController.startWidth;
graphCanvas.height = windowController.startHeight;
console.log("set element", graphCanvas);
await windowController.setElement( graphCanvas );
await windowController.setup();
windowController.maximizeWindow();
var nodes = await loadJSON("./nodes.json");
console.log(nodes);
var shaders = nodes.shaders;
for (var i = 0; i < shaders.length; i++) {
var shader = shaders[i]
var bindings = shader.bindings;
var newNode = new Node(shader.name, 50 + 240 * i, 100, [], []);
for (var j = 0; j < bindings.length; j++) {
var binding = bindings[j]
var varName = binding.varName;
newNode.inputs[j] = varName;
newNode.outputs[j] = varName;
}
shader.node = newNode;
graphExplorer.addNode( newNode );
}
var edges = nodes.edges;
for (var i = 0; i < edges.length; i++) {
var edge = edges[i]
var fromShader = getShaderByName( shaders, edge.from );
var toShader = getShaderByName( shaders, edge.to );
var fromPortIndex = getPortIndex( fromShader.bindings, edge.fromBuffer );
var toPortIndex = getPortIndex( toShader.bindings, edge.buffer );
var edge = new Edge( fromShader.node, fromPortIndex, toShader.node, toPortIndex );
graphExplorer.addEdge( edge );
//console.log(edge, shaders, edge.from, fromShader);
}
autoLayoutNodes( graphExplorer );
graphExplorer.setup( graphCanvas );
graphExplorer.inertiaLoop();
graphExplorer.draw();
document.querySelector("#graphExplorer").addEventListener("click", function () {
windowController.show();
});
windowController.resizeCanvas();
</script>
</body>
</html>