628 lines
27 KiB
JavaScript
628 lines
27 KiB
JavaScript
class LogicEngineSettings {
|
|
constructor(restoresettings = false) {
|
|
this.ActiveConnectionColor = "#aabbaa";
|
|
this.ActiveConnectionHoverColor = "#ccffcc";
|
|
this.InactiveConnectionColor = "#bbaaaa";
|
|
this.InactiveConnectionHoverColor = "#ffcccc";
|
|
this.LinkWidth = "2";
|
|
this.LinkDash = [];
|
|
this.LinkingConnectionColor = "#aabbbb";
|
|
this.LinkingWidth = "3";
|
|
this.LinkingDash = [2,2];
|
|
this.ShadowColor = "#222";
|
|
this.InputCircleSize = 10;
|
|
this.OutputCircleSize = 10;
|
|
this.ShowGrid = true;
|
|
this.SnapGrid = true;
|
|
this.TopConnections = true;
|
|
this.HideConnections = false;
|
|
this.GridSize = 20;
|
|
this.ShowFPS = true;
|
|
this.Keybindings = {
|
|
FileNew: {Key: "n", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "New Design",
|
|
Description: "Start a new design",
|
|
Category: "File"},
|
|
FileOpen: {Key: "o", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Open Design",
|
|
Description: "Open a design",
|
|
Category: "File"},
|
|
FileSave: {Key: "s", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Save Design",
|
|
Description: "Save current design",
|
|
Category: "File"},
|
|
EditUndo: {Key: "z", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Undo",
|
|
Description: "Steps back through the last things you have done reversing them",
|
|
Category: "Edit"},
|
|
EditRedo: {Key: "y", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Redo",
|
|
Description: "Reverse any changes done via Redo",
|
|
Category: "Edit"},
|
|
DeleteElements: {Key: "delete",
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Delete Element(s)",
|
|
Description: "Delete currently selected elements",
|
|
Category: "Edit"},
|
|
DisconnectElements: {Key: "d",
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Disconnect Element(s)",
|
|
Description: "Disconnect currently selected elements",
|
|
Category: "Edit"},
|
|
SelectAll: {Key: "a", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Select All",
|
|
Description: "Select all elments in the design",
|
|
Category: "Edit"},
|
|
ResetCanvas: {Key: "home", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Reset View",
|
|
Description: "Resets the pan back to the default location",
|
|
Category: "View"},
|
|
ShowConnections: {Key: "c", // lowercase
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Toggle Connections",
|
|
Description: "Show / Hide connections",
|
|
Category: "View"},
|
|
ConnectionLayer: {Key: "c", // lowercase
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Connection Layer",
|
|
Description: "Toggle connections above / below elements",
|
|
Category: "View"},
|
|
ShowGrid: {Key: "g", // lowercase
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Toggle Grid",
|
|
Description: "Show / Hide the grid",
|
|
Category: "View"},
|
|
SnapGrid: {Key: "g", // lowercase
|
|
Alt: true,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Snap to Grid",
|
|
Description: "Snap to grid or not",
|
|
Category: "View"},
|
|
GridPlus: {Key: "+", // lowercase
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Enlarge Grid",
|
|
Description: "Make the grid larger",
|
|
Category: "View"},
|
|
GridMinus: {Key: "-", // lowercase
|
|
Alt: false,
|
|
Shift: true,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Shrink Grid",
|
|
Description: "Make the grid smaller",
|
|
Category: "View"},
|
|
ShowFPS: {Key: "f3", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Toggle FPS",
|
|
Description: "Show / Hide FPS counter",
|
|
Category: "View"},
|
|
CreateIC: {Key: "c", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: true,
|
|
Meta: false,
|
|
Name: "Create IC",
|
|
Description: "Turns the current design into an IC",
|
|
Category: "Tools"},
|
|
Help: {Key: "f1", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "Help Window",
|
|
Description: "Opens help window",
|
|
Category: "Other"}
|
|
|
|
|
|
/*
|
|
keybind_name: {Key: "", // lowercase
|
|
Alt: false,
|
|
Shift: false,
|
|
Ctrl: false,
|
|
Meta: false,
|
|
Name: "",
|
|
Description: "",
|
|
Category: ""}
|
|
|
|
*/
|
|
};
|
|
if (restoresettings) {
|
|
let othis = this;
|
|
Object.keys(restoresettings).forEach(function(key) {
|
|
othis[key] = restoresettings[key];
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
class LogicEngine {
|
|
Resize(evt) {
|
|
let leftmenu = document.getElementById("left-menu");
|
|
let topbar = document.getElementById("top-bar");
|
|
let lmrect = leftmenu.getBoundingClientRect();
|
|
let tbrect = topbar.getBoundingClientRect();
|
|
leftmenu.style.height = (window.innerHeight - (tbrect.height + 2)) + "px";
|
|
this.Canvas.width = window.innerWidth - lmrect.width;
|
|
this.Canvas.height = window.innerHeight - tbrect.height;
|
|
this.Mouse = false;
|
|
let gridPlane = document.getElementById("GridPlane");
|
|
gridPlane.style.top = tbrect.height + "px";
|
|
gridPlane.style.left = lmrect.width + "px";
|
|
this.Canvas.style.top = tbrect.height + "px";
|
|
this.Canvas.style.left = lmrect.width + "px";
|
|
gridPlane.width = this.Canvas.width;
|
|
gridPlane.height = this.Canvas.height;
|
|
this.Ctx.setTransform(1,0,0,1,0,0);
|
|
this.Ctx.translate(this.Panning.OffsetX,this.Panning.OffsetY);
|
|
if (this.Settings.ShowGrid) {
|
|
let Ctx = gridPlane.getContext("2d");
|
|
Ctx.save();
|
|
let gridWidth = this.Settings.GridSize;
|
|
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.length > 1) return false;
|
|
if (!this.ActiveContainer.Selected[0].getProperty(property)) return false;
|
|
let propElement = document.getElementById("prop_" + property);
|
|
this.ActiveContainer.Selected[0].getProperty(property).Call(propElement.value);
|
|
}
|
|
|
|
Mouse_Down(evt) {
|
|
if (evt.which === 1) {
|
|
let mousePos = getMousePos(this.Canvas, evt);
|
|
this.MouseDownTime = performance.now();
|
|
let element = this.ActiveContainer.checkMouseBounds(mousePos);
|
|
if (element) {
|
|
this.MouseDown = true;
|
|
|
|
if (this.ActiveContainer.isSelected(element)) {
|
|
|
|
} else {
|
|
this.ActiveContainer.Select(element);
|
|
}
|
|
this.MovingElement = new Array(this.ActiveContainer.Selected.length);
|
|
|
|
for (let a = 0; a < this.ActiveContainer.Selected.length; a++) {
|
|
this.MovingElement[a] = {
|
|
StartX: this.ActiveContainer.Selected[a].X,
|
|
StartY: this.ActiveContainer.Selected[a].Y
|
|
};
|
|
this.MovingElementMouseStartX = mousePos.x;
|
|
this.MovingElementMouseStartY = mousePos.y;
|
|
}
|
|
element.MouseDown(mousePos);
|
|
} else {
|
|
this.MouseDown = true;
|
|
this.ActiveLink = false;
|
|
if (this.ControlPressed) {
|
|
this.Panning.StartOffsetX = this.Panning.OffsetX;
|
|
this.Panning.StartOffsetY = this.Panning.OffsetY;
|
|
this.Panning.StartX = mousePos.x;
|
|
this.Panning.StartY = mousePos.y;
|
|
} else {
|
|
|
|
let cmPos = this.getCanvasMousePos(mousePos);
|
|
this.MultiSelectStart.InProgress = true;
|
|
this.MultiSelectStart.x = cmPos.x;
|
|
this.MultiSelectStart.y = cmPos.y;
|
|
this.ActiveContainer.Selected = false;
|
|
let PropertiesBox = document.getElementById("PropertiesBox");
|
|
PropertiesBox.style.display = "none";
|
|
}
|
|
}
|
|
if (this.ActiveContainer.Selected?.length > 0) {
|
|
disableSelectedRCMs(false);
|
|
} else {
|
|
disableSelectedRCMs(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
Mouse_Up(evt) {
|
|
let mousePos = getMousePos(this.Canvas, evt);
|
|
if (this.MovingElement) {
|
|
let element = this.ActiveContainer.checkMouseBounds(mousePos);
|
|
if (element) element.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
|
|
let element = this.ActiveContainer.checkMouseBounds(mousePos);
|
|
if (element) element.MouseClick(mousePos);
|
|
}
|
|
//console.log("Mouse Up");
|
|
}
|
|
if (!this.MovingElement && evt.which === 1) {
|
|
this.ActiveContainer.Selected = false;
|
|
let PropertiesBox = document.getElementById("PropertiesBox");
|
|
PropertiesBox.style.display = "none";
|
|
}
|
|
|
|
this.MovingElement = false;
|
|
this.MouseDown = false;
|
|
|
|
if (this.MultiSelectStart.InProgress) {
|
|
this.MultiSelectStart.InProgress = false;
|
|
let cmStartPos = {x: this.MultiSelectStart.x, y: this.MultiSelectStart.y};
|
|
let cmEndPos = this.getCanvasMousePos(mousePos);
|
|
this.ActiveContainer.SelectWithin((cmStartPos.x>cmEndPos.x) ? cmEndPos.x : cmStartPos.x,
|
|
(cmStartPos.y>cmEndPos.y) ? cmEndPos.y : cmStartPos.y,
|
|
(cmStartPos.x>cmEndPos.x) ? cmStartPos.x : cmEndPos.x,
|
|
(cmStartPos.y>cmEndPos.y) ? cmStartPos.y : cmEndPos.y);
|
|
}
|
|
|
|
if (this.ActiveContainer.Selected?.length > 0) {
|
|
disableSelectedRCMs(false);
|
|
} else {
|
|
disableSelectedRCMs(true);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
for (let a = 0; a < this.ActiveContainer.Selected.length; a++) {
|
|
let diffxOffset = this.MovingElementMouseStartX - this.MovingElement[a].StartX;
|
|
let diffyOffset = this.MovingElementMouseStartY - this.MovingElement[a].StartY;
|
|
let actualPosX = (this.MovingElementMouseStartX + xOffset) - diffxOffset;
|
|
let actualPosY = (this.MovingElementMouseStartY + yOffset) - diffyOffset;
|
|
|
|
if (!this.ControlPressed && this.Settings.SnapGrid) actualPosX = Math.round(actualPosX / this.Settings.GridSize) * this.Settings.GridSize;
|
|
if (!this.ControlPressed && this.Settings.SnapGrid) actualPosY = Math.round(actualPosY / this.Settings.GridSize) * this.Settings.GridSize;
|
|
|
|
this.ActiveContainer.Selected[a].X = actualPosX;
|
|
this.ActiveContainer.Selected[a].Y = actualPosY;
|
|
this.ActiveContainer.Selected[a].redraw = true;
|
|
}
|
|
}
|
|
|
|
|
|
} else {
|
|
if (this.ControlPressed) {
|
|
let distX = mousePos.x - this.Panning.StartX;
|
|
let distY = mousePos.y - this.Panning.StartY;
|
|
this.Panning.StartX += distX;
|
|
this.Panning.StartY += distY;
|
|
|
|
this.Panning.OffsetX += distX;
|
|
this.Panning.OffsetY += distY;
|
|
|
|
this.Ctx.translate(distX, distY);
|
|
}
|
|
}
|
|
} else {
|
|
this.ActiveContainer.checkMouseBounds(mousePos);
|
|
}
|
|
}
|
|
|
|
|
|
Key_Up(evt) {
|
|
if (!evt.ctrlKey) {
|
|
this.ControlPressed = false;
|
|
}
|
|
}
|
|
|
|
Key_Press(evt) {
|
|
if (evt.ctrlKey) {
|
|
this.ControlPressed = true;
|
|
}
|
|
|
|
if (document.activeElement.tagName.toLowerCase() == "input") return; // Dont interupt a textbox
|
|
if (evt.key == "Escape") {
|
|
if (this.MovingElement && this.MouseDown) {
|
|
this.MovingElement.X = this.MovingElementStartX;
|
|
this.MovingElement.Y = this.MovingElementStartY;
|
|
this.MovingElement = false;
|
|
}
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.FileNew,evt)) {
|
|
evt.preventDefault();
|
|
tfm_New.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.FileOpen,evt)) {
|
|
evt.preventDefault();
|
|
alert("It is not possible to do a dialog box file open with javascript keyboard shortcuts, however this feature will work soon once server storage is implemented! Until then you will have to click on Open.");
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.FileSave,evt)) {
|
|
evt.preventDefault();
|
|
tfm_Save.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.ResetCanvas,evt)) {
|
|
evt.preventDefault();
|
|
tfm_Pan2Center.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.ShowConnections,evt)) {
|
|
evt.preventDefault();
|
|
tfm_ShowConns.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.ConnectionLayer,evt)) {
|
|
evt.preventDefault();
|
|
tfm_ConnLayer.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.SelectAll,evt)) {
|
|
evt.preventDefault();
|
|
tfm_SelectAll.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.ShowGrid,evt)) {
|
|
evt.preventDefault();
|
|
tfm_ShowGrid.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.SnapGrid,evt)) {
|
|
evt.preventDefault();
|
|
tfm_SnapGrid.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.GridPlus,evt)) {
|
|
evt.preventDefault();
|
|
in_GridSize.value = logicEngine.Settings.GridSize + Math.ceil(logicEngine.Settings.GridSize * 0.05);
|
|
in_GridSize.dispatchEvent(new Event('change'));
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.GridMinus,evt)) {
|
|
evt.preventDefault();
|
|
in_GridSize.value = ((logicEngine.Settings.GridSize - Math.ceil(logicEngine.Settings.GridSize * 0.05)) < 2) ? 2 : logicEngine.Settings.GridSize - Math.ceil(logicEngine.Settings.GridSize * 0.05) ;
|
|
in_GridSize.dispatchEvent(new Event('change'));
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.ShowFPS,evt)) {
|
|
evt.preventDefault();
|
|
tfm_ShowFPS.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.CreateIC,evt)) {
|
|
evt.preventDefault();
|
|
tfm_CreateIC.click(evt);
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.Help,evt)) {
|
|
evt.preventDefault();
|
|
ShowHelp();
|
|
}
|
|
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.DeleteElements,evt)) {
|
|
if (this.ActiveContainer.Selected?.length > 0) {
|
|
this.ActiveContainer.DeleteElement(this.ActiveContainer.Selected);
|
|
this.ActiveContainer.Selected = false;
|
|
let PropertiesBox = document.getElementById("PropertiesBox");
|
|
PropertiesBox.style.display = "none";
|
|
}
|
|
}
|
|
|
|
if (MatchesPress(this.Settings.Keybindings.DisconnectElements,evt)) {
|
|
if (this.ActiveContainer.Selected?.length > 0) {
|
|
for (let a = 0; a < logicEngine.ActiveContainer.Selected.length; a++) {
|
|
logicEngine.ActiveContainer.Selected[a].Disconnect();
|
|
}
|
|
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
|
|
}
|
|
}
|
|
}
|
|
|
|
constructor(canvas) {
|
|
this.Canvas = canvas;
|
|
this.Ctx = canvas.getContext("2d");
|
|
|
|
let restoresettings = false;
|
|
if (localStorage.getItem("LogicEngineSettings")) {
|
|
restoresettings = JSON.parse(localStorage.getItem("LogicEngineSettings"));
|
|
console.log("Restoring Settings");
|
|
}
|
|
|
|
this.Settings = new LogicEngineSettings(restoresettings);
|
|
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.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;
|
|
this.Panning = {OffsetX: 0, OffsetY: 0,StartOffsetX: 0, StartOffsetY: 0, StartX: 0, StartY: 0};
|
|
this.MultiSelectStart = {
|
|
x: 0,
|
|
y: 0,
|
|
InProgress: false
|
|
};
|
|
}
|
|
|
|
Link(input = 0) {
|
|
if (this.ActiveLink) {
|
|
if ((this.ActiveContainer.Selected?.length == 1) && (this.ActiveContainer.Selected?.[0] != this.ActiveLink)) {
|
|
this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected[0],input,this.ActiveLink.OutputLink.Output);
|
|
this.ActiveLink = false;
|
|
} else {
|
|
this.ActiveLink = false;
|
|
}
|
|
} else {
|
|
if (this.ActiveContainer.Selected.length == 1) {
|
|
|
|
if (!this.ActiveContainer.Selected[0].NoOutput) this.ActiveLink = this.ActiveContainer.Selected[0];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
getCanvasMousePos(mousePos) {
|
|
return {x: mousePos.x - this.Panning.OffsetX, y: mousePos.y - this.Panning.OffsetY};
|
|
}
|
|
|
|
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- this.Panning.OffsetX,0- this.Panning.OffsetY,this.Canvas.width,this.Canvas.height);
|
|
let ct = new CanvasTools();
|
|
|
|
if (this.MultiSelectStart.InProgress) {
|
|
let cmPos = this.getCanvasMousePos(this.Mouse);
|
|
ct.drawBorderBox(this.Ctx,this.MultiSelectStart.x,this.MultiSelectStart.y,cmPos.x - this.MultiSelectStart.x,cmPos.y - this.MultiSelectStart.y,0,"rgba(100,200,255,0.25)","rgba(100,200,255,0.25)");
|
|
}
|
|
|
|
this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
|
|
let tfm_CreateIC = document.getElementById("tfm_CreateIC");
|
|
let rcm_CreateIC = document.getElementById("rcm_CreateIC");
|
|
|
|
tfm_CreateIC.classList.add("disabled");
|
|
rcm_CreateIC.classList.add("disabled");
|
|
if (this.ActiveContainer.ICOutputs > 0) tfm_CreateIC.classList.remove("disabled");
|
|
if (this.ActiveContainer.ICOutputs > 0) rcm_CreateIC.classList.remove("disabled");
|
|
if (this.ActiveLink) {
|
|
let startX = this.ActiveLink.LinkOutLocation().x;
|
|
let startY = this.ActiveLink.LinkOutLocation().y;
|
|
let endX = this.Mouse.x - this.Panning.OffsetX;
|
|
let endY = this.Mouse.y - this.Panning.OffsetY;
|
|
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 FPSOffset = 5 - this.Panning.OffsetX;
|
|
if (this.Settings.ShowFPS) {
|
|
ct.drawText(this.Ctx, FPSOffset, 15 - this.Panning.OffsetY, "FPS: " + this.FPS, "12px console", "#00ff00");
|
|
ct.drawText(this.Ctx, FPSOffset, 29 - this.Panning.OffsetY, "Potential FPS: " + Math.floor(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(); // Get the animation loop going
|
|
}
|
|
}
|