class LogicEngineSettings { constructor() { this.ActiveConnectionColor = "#aabbaa"; this.InactiveConnectionColor = "#bbaaaa"; this.LinkWidth = "2"; this.LinkDash = []; this.LinkingConnectionColor = "#aabbbb"; this.LinkingWidth = "3"; this.LinkingDash = [2,2]; this.ShadowColor = "#222"; } } class LogicEngine { Resize(evt) { let leftmenu = document.getElementById("left-menu"); leftmenu.style.height = (window.innerHeight - 52) + "px"; this.Canvas.width = window.innerWidth - 205; this.Canvas.height = window.innerHeight - 50; this.Mouse = false; let gridPlane = document.getElementById("GridPlane"); gridPlane.width = this.Canvas.width; gridPlane.height = this.Canvas.height; let Ctx = gridPlane.getContext("2d"); Ctx.save(); let gridWidth = 20; for (let x = gridWidth;x < (this.Canvas.width); x+= gridWidth) { Ctx.beginPath(); Ctx.moveTo(x,0); Ctx.lineTo(x,this.Canvas.height); Ctx.strokeStyle = "#777"; Ctx.lineWidth = "1"; Ctx.stroke(); } for (let y = gridWidth;y < (this.Canvas.height); y+= gridWidth) { Ctx.beginPath(); Ctx.moveTo(0,y); Ctx.lineTo(this.Canvas.width,y); Ctx.lineWidth = "1"; Ctx.strokeStyle = "#777"; Ctx.stroke(); } Ctx.restore(); } PropertyChange(property) { if (!this.ActiveContainer.Selected.getProperty(property)) return false; let propElement = document.getElementById("prop_" + property); this.ActiveContainer.Selected.getProperty(property).Call(propElement.value); } Mouse_Down(evt) { let mousePos = getMousePos(this.Canvas, evt); this.MouseDownTime = performance.now(); let element = this.ActiveContainer.checkMouseBounds(mousePos); if (element) { this.MouseDown = true; this.ActiveContainer.Select(element); this.MovingElement = element; this.MovingElementStartX = element.X; this.MovingElementStartY = element.Y; this.MovingElementMouseStartX = mousePos.x; this.MovingElementMouseStartY = mousePos.y; element.MouseDown(mousePos); } else { this.ActiveLink = false; } } Mouse_Up(evt) { let mousePos = getMousePos(this.Canvas, evt); if (this.MovingElement) this.MovingElement.MouseUp(mousePos); if (this.MovingElement && (this.MovingElement.X == this.MovingElementStartX) && (this.MovingElement.Y == this.MovingElementStartY)) { if ((performance.now() - this.MouseDownTime) < 3000) { // Presume this was a click this.MovingElement.MouseClick(mousePos); } //console.log("Mouse Up"); } if (!this.MovingElement) this.ActiveContainer.Selected = false; this.MovingElement = false; this.MouseDown = false; } Mouse_Move(evt) { //this.Canvas.focus(); let mousePos = getMousePos(this.Canvas, evt); this.Mouse = mousePos; if(this.MouseDown) { //console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y); if (this.MovingElement) { if ((performance.now() - this.MouseDownTime) > 100) { let xOffset = mousePos.x - this.MovingElementMouseStartX; let yOffset = mousePos.y - this.MovingElementMouseStartY; let diffxOffset = this.MovingElementMouseStartX - this.MovingElementStartX; let diffyOffset = this.MovingElementMouseStartY - this.MovingElementStartY; let actualPosX = (this.MovingElementMouseStartX + xOffset) - diffxOffset; let actualPosY = (this.MovingElementMouseStartY + yOffset) - diffyOffset; if (!this.ControlPressed) actualPosX = Math.round(actualPosX/20)*20; if (!this.ControlPressed) actualPosY = Math.round(actualPosY/20)*20; this.MovingElement.X = actualPosX; this.MovingElement.Y = actualPosY; } } } else { this.ActiveContainer.checkMouseBounds(mousePos); } } Key_Up(evt) { if (!evt.ctrlKey) { this.ControlPressed = false; } } Key_Press(evt) { if (evt.ctrlKey) { this.ControlPressed = true; } if (evt.key == "Escape") { if (this.MovingElement && this.MouseDown) { this.MovingElement.X = this.MovingElementStartX; this.MovingElement.Y = this.MovingElementStartY; this.MovingElement = false; } } if (evt.key == "Delete") { if (this.ActiveContainer.Selected) { this.ActiveContainer.DeleteElement(this.ActiveContainer.Selected); this.ActiveContainer.Selected = false; } } } constructor(canvas) { this.Canvas = canvas; this.Ctx = canvas.getContext("2d"); this.Settings = new LogicEngineSettings; this.FPSCounter = 0; this.FPS = 0; this.PotentialFPS = 0; this.PotentialFPSAVGs = new Array(20); this.PotentialFPSAVGLoc = 0; this.LastFPSCheck = performance.now(); this.MouseDown = false; this.MouseDownTime = 0; this.MovingElementContainer = false; this.MovingElement = false; this.MovingElementStartX = 0; this.MovingElementStartY = 0; this.MovingElementMouseStartX = 0; this.MovingElementMouseStartY = 0; this.ActiveContainer = new elementContainer(); this.ActiveLink = false; this.Scheduler = new ScheduleEngine(); this.RecursionCount = 0; this.RecursionError = false; this.Canvas.setAttribute('tabindex','0'); this.ControlPressed = false; } Link(input = 0) { if (this.ActiveLink) { if (this.ActiveContainer.Selected && (this.ActiveContainer.Selected != this.ActiveLink)) { this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected,input,this.ActiveLink.OutputLink.Output); this.ActiveLink = false; } else { this.ActiveLink = false; } } else { if (this.ActiveContainer.Selected) { this.ActiveLink = this.ActiveContainer.Selected; } } } DrawLoop() { if (this.RecursionError) { this.RecursionError = false; alert("Recursion Error! Whatever you last did is causing an oscillating loop, please check your connections and try again!"); } let startLoop = performance.now(); this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height); this.ActiveContainer.DrawAll(this.Ctx,this.Settings); let btn_CreateIC = document.getElementById("btn_CreateIC"); btn_CreateIC.disabled = true; if (this.ActiveContainer.ICOutputs > 0) btn_CreateIC.disabled = false; if (this.ActiveLink) { let startX = this.ActiveLink.LinkOutLocation().x; let startY = this.ActiveLink.LinkOutLocation().y; let endX = this.Mouse.x; let endY = this.Mouse.y; let startMidX = startX + ((endX - startX)/2); let startMidY = startY; let midX = startMidX; let midY = startY + ((endY - startY)/2); let endMidX = startMidX; let endMidY = endY; this.Ctx.save(); this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor; this.Ctx.lineWidth = this.Settings.LinkingWidth; this.Ctx.setLineDash(this.Settings.LinkingDash); this.Ctx.beginPath(); this.Ctx.moveTo(startX, startY); this.Ctx.quadraticCurveTo(startMidX,startMidY,midX,midY); this.Ctx.quadraticCurveTo(endMidX,endMidY,endX,endY); this.Ctx.stroke(); this.Ctx.restore(); } let ct = new CanvasTools(); let FPSOffset = this.Canvas.width - 150; ct.drawText(this.Ctx,FPSOffset,650,"FPS: " + this.FPS,"12px console", "#00ff00"); ct.drawText(this.Ctx,FPSOffset,670,"Potential FPS: " + this.PotentialFPS,"12px console", "#00ff00"); let timeCheck = performance.now(); this.FPSCounter++; if (!(Math.round(timeCheck - this.LastFPSCheck) % 50)) { let frameTimeUS = (performance.now() - startLoop) * 1000; let potentialFPS = 1000000 / frameTimeUS; this.PotentialFPSAVGs[this.PotentialFPSAVGLoc] = Math.round(potentialFPS); this.PotentialFPSAVGLoc++; if (this.PotentialFPSAVGLoc == this.PotentialFPSAVGs.length) this.PotentialFPSAVGLoc = 0; this.PotentialFPS = averageArray(this.PotentialFPSAVGs); } if ((timeCheck - this.LastFPSCheck) >= 1000) { this.FPS = this.FPSCounter; this.FPSCounter = 0; this.LastFPSCheck = performance.now(); //console.log("Frame Time: " + frameTimeUS + "uS" + ", Potential FPS: " + potentialFPS); //console.log("FPS: " + FPS); } requestAnimationFrame(this.DrawLoop.bind(this)); } StartEngine() { this.Resize(""); this.DrawLoop(); } }