// Temporarily kept - to be deleted var totalObjects = 0; function scheduleUpdate(count = 0, time = 100, fn) { // return; // //////console.log(willBeUpdated,updateSimulation,); if (lightMode) time *= 5; if (count && !layoutMode) { for (var i = 0; i < count; i++) setTimeout(update, 10 + 50 * i); } if (willBeUpdated) return; willBeUpdated = true; // if (simulationArea.mouseDown) if (layoutMode) { setTimeout(layoutUpdate, time); return; } if (fn) setTimeout(function() { fn(); update(); }, time); else setTimeout(update, time); // else // setTimeout(update, 100); } // fn that calls update on everything else. If any change is there, it resolves the circuit and draws it again // fn to change scale (zoom) - It also shifts origin so that the position //of the object in focus doent changeB function update(scope = globalScope, updateEverything = false) { willBeUpdated = false; if (loading == true || layoutMode) return; // //////console.log("UPDATE"); var updated = false; simulationArea.hover = undefined; // wireToBeChecked=true; if (wireToBeChecked || updateEverything) { if (wireToBeChecked == 2) wireToBeChecked = 0; // this required due to timing issues else wireToBeChecked++; // WHY IS THIS REQUIRED ???? we are checking inside wire ALSO var prevLength = scope.wires.length; for (var i = 0; i < scope.wires.length; i++) { scope.wires[i].checkConnections(); if (scope.wires.length != prevLength) { prevLength--; i--; } } scheduleUpdate(); } if (updateSubcircuit || updateEverything) { for (var i = 0; i < scope.SubCircuit.length; i++) scope.SubCircuit[i].reset(); updateSubcircuit = false; } if (updatePosition || updateEverything) { //////console.log("updatePosition"); for (var i = 0; i < updateOrder.length; i++) for (var j = 0; j < scope[updateOrder[i]].length; j++) { updated |= scope[updateOrder[i]][j].update(); } } // updateSimulation |= updated; if (updatePosition) { } if (updatePosition || updateEverything) { updateSelectionsAndPane(scope); } if (!embed && simulationArea.mouseDown && simulationArea.lastSelected && simulationArea.lastSelected != globalScope.root) { if (!lightMode) $('#miniMap').fadeOut('fast'); } if (updateSimulation) { play(); } if (!embed && prevPropertyObj != simulationArea.lastSelected) { if (simulationArea.lastSelected && simulationArea.lastSelected.objectType !== "Wire") { showProperties(simulationArea.lastSelected); //////console.log("yo"); } else { // hideProperties(); } } //Draw if (updateCanvas) { renderCanvas(scope); } // if (updateSimulation||update) scheduleUpdate(); updateSimulation = updateCanvas = updatePosition = false; // if(updated){ // updatePosition=true; // updateCanvas=true; // scheduleUpdate(); // } } function findDimensions(scope = globalScope) { totalObjects = 0; simulationArea.minWidth = undefined; simulationArea.maxWidth = undefined; simulationArea.minHeight = undefined; simulationArea.maxHeight = undefined; for (var i = 0; i < updateOrder.length; i++) { if (updateOrder[i] !== 'wires') for (var j = 0; j < scope[updateOrder[i]].length; j++) { totalObjects += 1; var obj = scope[updateOrder[i]][j]; if (totalObjects == 1) { simulationArea.minWidth = obj.absX(); simulationArea.minHeight = obj.absY(); simulationArea.maxWidth = obj.absX(); simulationArea.maxHeight = obj.absY(); } if (obj.objectType != 'Node') { if (obj.y - obj.upDimensionY < simulationArea.minHeight) simulationArea.minHeight = obj.y - obj.upDimensionY; if (obj.y + obj.downDimensionY > simulationArea.maxHeight) simulationArea.maxHeight = obj.y + obj.downDimensionY; if (obj.x - obj.leftDimensionX < simulationArea.minWidth) simulationArea.minWidth = obj.x - obj.leftDimensionX; if (obj.x + obj.rightDimensionX > simulationArea.maxWidth) simulationArea.maxWidth = obj.x + obj.rightDimensionX; } else { if (obj.absY() < simulationArea.minHeight) simulationArea.minHeight = obj.absY(); if (obj.absY() > simulationArea.maxHeight) simulationArea.maxHeight = obj.absY(); if (obj.absX() < simulationArea.minWidth) simulationArea.minWidth = obj.absX(); if (obj.absX() > simulationArea.maxWidth) simulationArea.maxWidth = obj.absX(); } } } simulationArea.objectList = updateOrder; } function updateSelectionsAndPane(scope = globalScope) { //////console.log("updateSelectionsAndPane"); if (!simulationArea.selected && simulationArea.mouseDown) { //mouse click NOT on object simulationArea.selected = true; simulationArea.lastSelected = scope.root; simulationArea.hover = scope.root; if (simulationArea.shiftDown) { objectSelection = true; } else { if (!embed) { findDimensions(scope); miniMapArea.setup(); $('#miniMap').show(); } } } else if (simulationArea.lastSelected == scope.root && simulationArea.mouseDown) { //pane canvas if (!objectSelection) { globalScope.ox = (simulationArea.mouseRawX - simulationArea.mouseDownRawX) + simulationArea.oldx; globalScope.oy = (simulationArea.mouseRawY - simulationArea.mouseDownRawY) + simulationArea.oldy; globalScope.ox = Math.round(globalScope.ox); globalScope.oy = Math.round(globalScope.oy); gridUpdate = true; if (!embed && !lightMode) miniMapArea.setup(); } else { } } else if (simulationArea.lastSelected == scope.root) { simulationArea.lastSelected = undefined; simulationArea.selected = false; simulationArea.hover = undefined; if (objectSelection) { objectSelection = false; var x1 = simulationArea.mouseDownX; var x2 = simulationArea.mouseX; var y1 = simulationArea.mouseDownY; var y2 = simulationArea.mouseY; // simulationArea.multipleObjectSelections=[]; // //////console.log(x1,x2,y1,y2); // [x1,x2]=[x1,x2].sort(); // [y1,y2]=[y1,y2].sort(); if (x1 > x2) { var temp = x1; x1 = x2; x2 = temp; } if (y1 > y2) { var temp = y1; y1 = y2; y2 = temp; } // //////console.log(x1,x2,y1,y2); for (var i = 0; i < updateOrder.length; i++) { for (var j = 0; j < scope[updateOrder[i]].length; j++) { var obj = scope[updateOrder[i]][j]; // //////console.log(obj); if (simulationArea.multipleObjectSelections.contains(obj)) continue; var x, y; if (obj.objectType == "Node") { x = obj.absX(); y = obj.absY(); } else if (obj.objectType != "Wire") { x = obj.x; y = obj.y; } else { // //////console.log(obj); continue; } if (x > x1 && x < x2 && y > y1 && y < y2) { simulationArea.multipleObjectSelections.push(obj); } } } } } } function renderCanvas(scope) { if (layoutMode) { return; } var ctx = simulationArea.context; simulationArea.clear(); if (gridUpdate) { gridUpdate = false; dots(); } // dots(); // draw dots canvasMessageData = undefined; for (var i = 0; i < renderOrder.length; i++) for (var j = 0; j < scope[renderOrder[i]].length; j++) scope[renderOrder[i]][j].draw(); if (canvasMessageData) { canvasMessage(ctx, canvasMessageData.string, canvasMessageData.x, canvasMessageData.y) } if (objectSelection) { ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "black" ctx.fillStyle = "rgba(0,0,0,0.1)" rect2(ctx, simulationArea.mouseDownX, simulationArea.mouseDownY, simulationArea.mouseX - simulationArea.mouseDownX, simulationArea.mouseY - simulationArea.mouseDownY, 0, 0, "RIGHT"); ctx.stroke(); ctx.fill(); } } //Main fn that resolves circuit function play(scope = globalScope, resetNodes = false) { // throw("ERROR"); //////console.log("play"); if (errorDetected) return; // //////console.log("simulation"); if (loading == true) return; if (!embed) plotArea.stopWatch.Stop(); // scope.stack=[]; scope.pending = []; scope.queue = new PriorityQueue({ comparator: function(a, b) { return a.priority - b.priority; } }); if (resetNodes || forceResetNodes) { forceResetNodes = false; for (var i = 0; i < scope.allNodes.length; i++) scope.allNodes[i].reset(); } else { // clearBuses(scope); for (var i = 0; i < scope.TriState.length; i++) { // console.log("HIT2",i); scope.TriState[i].removePropagation(); } } for (var i = 0; i < scope.SubCircuit.length; i++) { if (scope.SubCircuit[i].isResolvable()) scope.queue.queue(scope.SubCircuit[i]); } // for (var i = 0; i < scope.FlipFlop.length; i++) { // scope.queue.queue(scope.FlipFlop[i]); // } for (var i = 0; i < inputList.length; i++) { for (var j = 0; j < scope[inputList[i]].length; j++) { scope.queue.queue(scope[inputList[i]][j]); } } // console.log(scope.stack); var stepCount = 0; var elem = undefined while (scope.queue.length || scope.pending.length) { // if(stepCount%100==0)console.log(scope.stack); if (errorDetected) return; if (scope.queue.length) { elem = scope.queue.dequeue(); // if(elem.objectType=="TriState"){ // // elem.removePropagation(); // scope.pending.push(elem); // continue; // } } else elem = scope.pending.pop(); // console.log("resolving:",elem) // scope.pending.clean(this); // scope.stack.clean(this); elem.resolve(); stepCount++; if (stepCount > 1000) { // console.log(elem) showError("Simulation Stack limit exceeded: maybe due to cyclic paths or contention"); return; } } for (var i = 0; i < scope.Flag.length; i++) scope.Flag[i].setPlotValue(); // for (var i = 0; i < scope.SubCircuit.length; i++) { // if(!scope.SubCircuit[i].isResolvable()) // { // scope.queue.queue(scope.SubCircuit[i]); // while (scope.stack.length) { // if(errorDetected)return; // var elem = scope.stack.pop(); // elem.resolve(); // stepCount++; // if (stepCount > 1000) { // showError("Simulation Stack limit exceeded: maybe due to cyclic paths or contention"); // return; // } // } // } // } } function clearBuses(scope = globalScope) { scope.stack = []; scope.pending = []; for (var i = 0; i < scope.TriState.length; i++) { console.log("HIT2", i); scope.TriState[i].removePropagation(); } for (var i = 0; i < scope.Clock.length; i++) { console.log("HIT2", i); scope.Clock[i].removePropagation(); } // console.log(scope.stack); var stepCount = 0; var elem = undefined while (scope.stack.length || scope.pending.length) { // if(stepCount%100==0)console.log(scope.stack); if (errorDetected) return; if (scope.stack.length) { elem = scope.stack.pop(); // if(elem.objectType=="TriState"){ // // elem.removePropagation(); // scope.pending.push(elem); // continue; // } } else elem = scope.pending.pop(); // scope.pending.clean(this); // scope.stack.clean(this); elem.resolve(); stepCount++; if (stepCount > 1000) { // console.log(elem) showError("BUS ERROR: Contention"); return; } } }