Compare commits

..

No commits in common. "master" and "dev-0.4-cp" have entirely different histories.

15 changed files with 533 additions and 812 deletions

View File

@ -1,48 +1,19 @@
# MatCat BrowserLogic # MatCat BrowserLogic
MatCat BrowserLogic https://www.logic.parts/ is a logic simulator written purely in HTML5 / Javascript using 2D Canvas. This code will always work standalone, just download and browse to index.html with your favorite browser. MatCat BrowserLogic https://www.logic.parts/ is a logic simulator written purely in HTML5 / Javascript using 2D Canvas.
The goal of this project is to offer a logic simulator that is full featured conceptual simulation of logic. It does not aim to be an electrical simulator, so realistic propagation delays and such are not simulated, however that is not to say that there aren't (as some elements such as clocks and buffers and IC I/O do have delayed buffers).
I designed this to design CPU's in, I am sure someone with some imagination could design nearly anything in it :).
## Status ## Status
Currently, in pre-alpha early dev stage; however the simulator is about to enter the alpha stage, this means that the simulator core functionality is mostly in place. The Alpha stage will be dedicated to polishing the simulator itself, finding and fixing bugs, introduction of local storage for saves, introduction of server storage, and development of the website including adding integration features. Outside contribution is welcome, please contact me (MatCat) in #LogicParts on Freenode IRC network. This simulator is in extremely early stages, it is not even Alpha at this point but early development. Outside contribution is welcome, please contact me in #LogicParts on Freenode IRC network.
## License ## License
To be decided, but at this moment this code is open source and free to use for non-commercial uses. To be decided, but at this moment this code is open source and free to use for non-commercial uses.
Copyright (c) 2021, MatCat
LZ-String, Copyright 2013 pieroxy under MIT license https://github.com/pieroxy/lz-string/blob/master/LICENSE LZ-String, Copyright 2013 pieroxy under MIT license https://github.com/pieroxy/lz-string/blob/master/LICENSE
## Changelog ## Changelog
### 0.4.16
* Fixed bug where properties window didn't disappear at certain times when it should
### 0.4.15
* Prepending ! or ~ (active low) before a pin name will now overline it when displayed on element
* Fixed a bug that disabled a switch after it was disconnected
* Fixed bug in how JK flipflops handled PRE and CLR and CLK
### 0.4.14
* Added WireNode element, allows you to better manage wires. Please note that signals only flow in the direction of connection! It is NOT a bidirectional element
* Added draw speed to FPS display (in uS)
### 0.4.13
* Clicking on an element on the toolbar no longer spawns an element to the work area directly, but rather lets the user place it.
### 0.4.12
* Fixed bug where pastes would get offset when canvas is panned
### 0.4.11 ### 0.4.11
* Copy and Paste, note that Paste in the menu may not work on some browsers because of security permissions, but standard keyboard shortcuts will work. * Copy and Paste, note that Paste in the menu may not work on some browsers because of security permissions, but standard keyboard shortcuts will work.

View File

@ -382,13 +382,6 @@ textarea {
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f85032', endColorstr='#e73827',GradientType=0 ); /* IE6-9 */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f85032', endColorstr='#e73827',GradientType=0 ); /* IE6-9 */
} }
#floatCanvas {
display: none;
position: absolute;
left: 0px;
right: 0px;
}
#darkout-overlay { #darkout-overlay {
position: absolute; position: absolute;
left: 0px; left: 0px;

View File

@ -186,11 +186,8 @@
</div> </div>
</div> </div>
</div> </div>
<div id="floatCanvas"><canvas></canvas></div>
<div id="darkout-overlay"></div> <div id="darkout-overlay"></div>
<script src="js/vendor/lz-string.min.js"></script> <script src="js/vendor/lz-string.min.js"></script>
<script src="js/topmenu/topmenu.js"></script>
<script src="js/rightclickmenu/rightclickmenu.js"></script>
<script src="js/globalfunctions.js"></script> <script src="js/globalfunctions.js"></script>
<script src="js/baseclasses.js"></script> <script src="js/baseclasses.js"></script>
<script src="js/scheduler.js"></script> <script src="js/scheduler.js"></script>
@ -202,8 +199,8 @@
<script src="js/elements/TimingElements.js"></script> <script src="js/elements/TimingElements.js"></script>
<script src="js/elements/ICElements.js"></script> <script src="js/elements/ICElements.js"></script>
<script src="js/logicengine.js"></script> <script src="js/logicengine.js"></script>
<script src="js/mainevents.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
</body> </body>
</html> </html>

View File

@ -32,41 +32,25 @@ class CanvasTools {
ctx.restore(); ctx.restore();
} }
drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555", Overline = false) { drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555") {
ctx.save(); ctx.save();
ctx.font = fontStyle; ctx.font = fontStyle;
ctx.fillStyle = fontColor; ctx.fillStyle = fontColor;
let textSize = this.textSize(ctx,text,fontStyle);
let tHeight = ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent; let tHeight = ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent;
let tX = x+((x2/2)-(ctx.measureText(text).width/2)); let tX = x+((x2/2)-(ctx.measureText(text).width/2));
let tY = y+tHeight+((y2/2)-(tHeight/2)); let tY = y+tHeight+((y2/2)-(tHeight/2));
if (Overline) {
ctx.strokeStyle = fontColor;
ctx.beginPath();
ctx.moveTo(tX,tY-textSize.height-1);
ctx.lineTo(tX+textSize.width,tY-textSize.height-1);
ctx.stroke();
}
ctx.fillText(text,tX,tY); ctx.fillText(text,tX,tY);
ctx.restore(); ctx.restore();
} }
drawText(ctx,x,y,text,fontStyle="24px Console",fontColor = "#555",Overline = false) { drawText(ctx,x,y,text,fontStyle="24px Console",fontColor = "#555") {
let textSize = this.textSize(ctx,text,fontStyle);
ctx.save(); ctx.save();
ctx.font = fontStyle; ctx.font = fontStyle;
ctx.fillStyle = fontColor; ctx.fillStyle = fontColor;
ctx.fillText(text,x,y); ctx.fillText(text,x,y);
if (Overline) {
ctx.strokeStyle = fontColor;
ctx.beginPath();
ctx.moveTo(x,y-textSize.height-2);
ctx.lineTo(x+textSize.width,y-textSize.height-2);
ctx.stroke();
}
ctx.restore(); ctx.restore();
} }
} }
class ContainerConnection { class ContainerConnection {

View File

@ -239,7 +239,6 @@ class Element extends CanvasTools {
this.OutputConnections.splice(a,1); this.OutputConnections.splice(a,1);
a--; a--;
} }
this.Disconnecting = false;
} }
this.drawElement(0,0,this.StaticCtx); this.drawElement(0,0,this.StaticCtx);
} }
@ -355,17 +354,7 @@ class Element extends CanvasTools {
if ((mouseDist <= (this.inputCircleRadius)) && this.LogicEngine.ActiveLink) ctx.fillStyle = circleColorHover; if ((mouseDist <= (this.inputCircleRadius)) && this.LogicEngine.ActiveLink) ctx.fillStyle = circleColorHover;
ctx.fill(); ctx.fill();
ctx.stroke(); ctx.stroke();
let drawOverline = false; if (this.InputLabels[a] && drawFresh) this.drawText(ctx,x+(this.inputCircleRadius*2)+ 5,(firstY + (a*24)) + 5,this.InputLabels[a],"10px Console","#000");
let label = this.InputLabels[a];
if (this.InputLabels[a] && drawFresh) {
if (this.InputLabels[a].charAt(0) == "!" || this.InputLabels[a].charAt(0) == "~") {
// Draw a NOT line
drawOverline = true;
label = this.InputLabels[a].substring(1);
}
this.drawText(ctx,x+(this.inputCircleRadius*2)+ 5,(firstY + (a*24)) + 5,label,"10px Console","#000",drawOverline);
}
} }
ctx.restore(); ctx.restore();
} }
@ -390,18 +379,9 @@ class Element extends CanvasTools {
ctx.fill(); ctx.fill();
ctx.stroke(); ctx.stroke();
let textSize = false; let textSize = false;
let drawOverline = false;
let label = this.OutputLabels[a];
if (this?.OutputLabels[a]?.charAt(0) == "!" || this?.OutputLabels[a]?.charAt(0) == "~") {
// Draw a NOT line
drawOverline = true;
label = this.OutputLabels[a].substring(1);
}
if (this.OutputLabels[a]) textSize = this.textSize(ctx,label,"10px Console"); if (this.OutputLabels[a]) textSize = this.textSize(ctx,this.OutputLabels[a],"10px Console");
if (this.OutputLabels[a] && drawFresh) { if (this.OutputLabels[a] && drawFresh) this.drawText(ctx,(x+(this.Width)) - (textSize.width + 5 + (this.outputCircleRadius*2)),(firstY + (a*24)) + 5,this.OutputLabels[a],"10px Console","#000");
this.drawText(ctx,(x+(this.Width)) - (textSize.width + 5 + (this.outputCircleRadius*2)),(firstY + (a*24)) + 5,label,"10px Console","#000",drawOverline);
}
} }
ctx.restore(); ctx.restore();
} }

View File

@ -1,28 +1,3 @@
class LogicWireNode extends Element {
constructor(_Container, RestoreData = null, logicengine) {
super(_Container, RestoreData,logicengine,1);
this.removeProperty("Inputs");
this.Name = "WireNode";
this.Width = 20;
this.Height = 20;
}
getOutput(Output = 0) {
if (Output > 0) return false;
return this.Inputs[0];
}
drawElement(x,y,ctx) {
if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible
this.StaticCanvas.width = this.Width;
this.StaticCanvas.height = this.Height;
this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
}
}
let ElementCatalog_WireNode = new ElementCatalog_Element("WireNode","A simple compact wire node for organizing wiring","-O-",LogicWireNode,[]);
ElementReferenceTable.push(ElementCatalog_WireNode);
ElementCategory_Other.addElement(ElementCatalog_WireNode);
class LogicAND extends Element { class LogicAND extends Element {
constructor(_Container, RestoreData = null, logicengine,Inputs) { constructor(_Container, RestoreData = null, logicengine,Inputs) {
super(_Container, RestoreData,logicengine,Inputs); super(_Container, RestoreData,logicengine,Inputs);

View File

@ -3,12 +3,11 @@ class FlipFlopJK extends Element {
super(_Container, RestoreData,logicengine,5); super(_Container, RestoreData,logicengine,5);
this.Name = "JK-FF"; this.Name = "JK-FF";
this.Outputs = new Array(2); this.Outputs = new Array(2);
this.InputLabels = new Array("J","!CLK","K","!PRE", "!CLR"); this.InputLabels = new Array("J","CLK","K","!PRE", "!CLR");
this.OutputLabels = new Array("Q","~Q"); this.OutputLabels = new Array("Q","~Q");
this.removeProperty("Inputs"); this.removeProperty("Inputs");
this.Height = 140; this.Height = 140;
this.Outputs[0] = true;
this.Outputs[1] = true;
if (RestoreData) { if (RestoreData) {
this.Outputs = RestoreData.OutputStates; this.Outputs = RestoreData.OutputStates;
} }
@ -27,12 +26,9 @@ class FlipFlopJK extends Element {
if (Value !== false) Value = true; if (Value !== false) Value = true;
let oldOutput = this.Outputs[0]; let oldOutput = this.Outputs[0];
let oldOutput2 = this.Outputs[1]; let oldOutput2 = this.Outputs[1];
let oldInput2 = this.Inputs[1];
let oldInput3 = this.Inputs[3];
let oldInput4 = this.Inputs[4];
this.Inputs[Input] = Value; this.Inputs[Input] = Value;
if (!this.Inputs[1] && oldInput2) { if (this.Inputs[1]) {
if (!this.Inputs[0] && this.Inputs[2]) { if (!this.Inputs[0] && this.Inputs[2]) {
// set Q low // set Q low
this.Outputs[0] = false; this.Outputs[0] = false;
@ -47,18 +43,11 @@ class FlipFlopJK extends Element {
this.Outputs[1] = !this.Outputs[0]; this.Outputs[1] = !this.Outputs[0];
} }
} }
if (!this.Inputs[3]) {
if (this.Inputs[4] && !oldInput4 && this.Outputs[0] && this.Outputs[1]) {
this.Outputs[1] = false;
}
if (this.Inputs[3] && !oldInput3 && this.Outputs[0] && this.Outputs[1]) {
this.Outputs[0] = false;
}
if (!this.Inputs[3] && oldInput3) {
this.Outputs[0] = true; this.Outputs[0] = true;
this.Outputs[1] = false; this.Outputs[1] = false;
} }
if (!this.Inputs[4] && oldInput4) { if (!this.Inputs[4]) {
this.Outputs[0] = false; this.Outputs[0] = false;
this.Outputs[1] = true; this.Outputs[1] = true;
} }
@ -116,37 +105,26 @@ class FlipFlopSR extends Element {
if (Value !== false) Value = true; if (Value !== false) Value = true;
let oldOutput = this.Outputs[0]; let oldOutput = this.Outputs[0];
let oldOutput2 = this.Outputs[1]; let oldOutput2 = this.Outputs[1];
let oldInput1 = this.Inputs[1];
let oldInput3 = this.Inputs[3];
let oldInput4 = this.Inputs[4];
this.Inputs[Input] = Value; this.Inputs[Input] = Value;
this.redraw = true; this.redraw = true;
if (this.Inputs[1] && !oldInput1) { if (this.Inputs[1]) {
if (!this.Inputs[0] && this.Inputs[2]) { if (!this.Inputs[0] && this.Inputs[2]) {
// set Q low // set Q low
this.Outputs[0] = false; this.Outputs[0] = false;
this.Outputs[1] = true; this.Outputs[1] = true;
} else if (this.Inputs[0] && !this.Inputs[2]) { } else if (this.Inputs[0] && !this.Inputs[2]) {
// set Q high // set Q low
this.Outputs[0] = true; this.Outputs[0] = true;
this.Outputs[1] = false; this.Outputs[1] = false;
} }
} }
if (this.Inputs[4] && !oldInput4 && !this.Inputs[3] && this.Outputs[1]) { if (!this.Inputs[3]) {
this.Outputs[1] = false;
}
if (this.Inputs[3] && !oldInput3 && !this.Inputs[4] && this.Outputs[0]) {
this.Outputs[0] = false;
}
if (!this.Inputs[3] && oldInput3) {
this.Outputs[0] = true; this.Outputs[0] = true;
this.Outputs[1] = false; this.Outputs[1] = false;
} }
if (!this.Inputs[4] && oldInput4) { if (!this.Inputs[4]) {
this.Outputs[0] = false; this.Outputs[0] = false;
this.Outputs[1] = true; this.Outputs[1] = true;
} }
@ -204,8 +182,6 @@ class FlipFlopT extends Element {
if (Value !== false) Value = true; if (Value !== false) Value = true;
let oldOutput = this.Outputs[0]; let oldOutput = this.Outputs[0];
let oldOutput2 = this.Outputs[1]; let oldOutput2 = this.Outputs[1];
let oldInput2 = this.Inputs[2];
let oldInput3 = this.Inputs[3];
this.Inputs[Input] = Value; this.Inputs[Input] = Value;
this.redraw = true; this.redraw = true;
@ -214,11 +190,11 @@ class FlipFlopT extends Element {
this.Outputs[1] = !this.Outputs[0]; this.Outputs[1] = !this.Outputs[0];
} }
if (!this.Inputs[2] && oldInput2) { if (!this.Inputs[2]) {
this.Outputs[0] = true; this.Outputs[0] = true;
this.Outputs[1] = false; this.Outputs[1] = false;
} }
if (!this.Inputs[3] && oldInput3) { if (!this.Inputs[3]) {
this.Outputs[0] = false; this.Outputs[0] = false;
this.Outputs[1] = true; this.Outputs[1] = true;
} }
@ -278,19 +254,18 @@ class FlipFlopD extends Element {
let oldOutput = this.Outputs[0]; let oldOutput = this.Outputs[0];
let oldOutput2 = this.Outputs[1]; let oldOutput2 = this.Outputs[1];
let oldInput = this.Inputs[1]; let oldInput = this.Inputs[1];
let oldInput2 = this.Inputs[2];
let oldInput3 = this.Inputs[3];
this.Inputs[Input] = Value; this.Inputs[Input] = Value;
this.redraw = true;
if (this.Inputs[1] && !oldInput) { if (this.Inputs[1] && !oldInput) {
this.Outputs[0] = this.Inputs[0]; this.Outputs[0] = this.Inputs[0];
this.Outputs[1] = !this.Outputs[0]; this.Outputs[1] = !this.Outputs[0];
} }
if (!this.Inputs[2] && oldInput2) { if (!this.Inputs[2]) {
this.Outputs[0] = true; this.Outputs[0] = true;
this.Outputs[1] = false; this.Outputs[1] = false;
} }
if (!this.Inputs[3] && oldInput3) { if (!this.Inputs[3]) {
this.Outputs[0] = false; this.Outputs[0] = false;
this.Outputs[1] = true; this.Outputs[1] = true;
} }

View File

@ -78,17 +78,9 @@ class ICInput extends Element {
this.StaticCanvas.width = this.Width; this.StaticCanvas.width = this.Width;
this.StaticCanvas.height = this.Height; this.StaticCanvas.height = this.Height;
let drawOverline = false;
let label = (this.Properties[0].CurrentValue) ? this.Properties[0].CurrentValue.toString() : "";
if (label.charAt(0) == "!" || label.charAt(0) == "~") {
// Draw a NOT line
drawOverline = true;
label = label.substring(1);
}
this.drawBorderBox(ctx,x+10,y,this.Width-30,this.Height); this.drawBorderBox(ctx,x+10,y,this.Width-30,this.Height);
this.drawTextCentered(ctx,x,y+2,this.Width-10,14,this.Designator,"12px Console"); this.drawTextCentered(ctx,x,y+2,this.Width-10,14,this.Designator,"12px Console");
this.drawTextCentered(ctx,x,y,this.Width-10,this.Height,label,"12px Console",undefined,drawOverline); this.drawTextCentered(ctx,x,y,this.Width-10,this.Height,this.Properties[0].CurrentValue,"12px Console");
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -194,17 +186,9 @@ class ICOutput extends Element {
this.StaticCanvas.width = this.Width; this.StaticCanvas.width = this.Width;
this.StaticCanvas.height = this.Height; this.StaticCanvas.height = this.Height;
let drawOverline = false;
let label = (this.Properties[0].CurrentValue) ? this.Properties[0].CurrentValue.toString() : "";
if (label.charAt(0) == "!" || label.charAt(0) == "~") {
// Draw a NOT line
drawOverline = true;
label = label.substring(1);
}
this.drawBorderBox(ctx,x+20,y,this.Width-10,this.Height); this.drawBorderBox(ctx,x+20,y,this.Width-10,this.Height);
this.drawTextCentered(ctx,x+20,y+2,this.Width-10,14,this.Designator,"12px Console"); this.drawTextCentered(ctx,x+20,y+2,this.Width-10,14,this.Designator,"12px Console");
this.drawTextCentered(ctx,x+20,y,this.Width-10,this.Height,label,"12px Console",undefined,drawOverline); this.drawTextCentered(ctx,x+20,y,this.Width-10,this.Height,this.Properties[0].CurrentValue,"12px Console");
this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
} }
} }

View File

@ -307,11 +307,12 @@ class InputKeypad extends inputElement {
for (let pX = 0; pX < this.ButtonColumns; pX++) { for (let pX = 0; pX < this.ButtonColumns; pX++) {
this.drawBorderBox(ctx, x + (5*(pX+1))+(buttonWidth*pX), y + (5*(pY+1))+(buttonHeight*pY), buttonWidth, buttonHeight, 1, "#ccc", "#777"); this.drawBorderBox(ctx, x + (5*(pX+1))+(buttonWidth*pX), y + (5*(pY+1))+(buttonHeight*pY), buttonWidth, buttonHeight, 1, "#ccc", "#777");
this.drawTextCentered(ctx,x + (5*(pX+1))+(buttonWidth*pX), y + (5*(pY+1))+(buttonHeight*pY), buttonWidth, buttonHeight, this.Buttons[(pY*this.ButtonColumns) + pX].Text,"16px Console", "#fff"); this.drawTextCentered(ctx,x + (5*(pX+1))+(buttonWidth*pX), y + (5*(pY+1))+(buttonHeight*pY), buttonWidth, buttonHeight, this.Buttons[(pY*this.ButtonColumns) + pX].Text,"16px Console", "#fff");
} }
} }
this.drawTextCentered(ctx,x,y+(this.Height-14),this.Width-(this.outputCircleRadius*2),12,this.Designator,"12px Console","#000"); this.drawTextCentered(ctx,x,y+(this.Height-14),this.Width-(this.outputCircleRadius*2),12,this.Designator,"12px Console","#000");
this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true); this.drawOutputs(ctx,x,y);
} }
} }

View File

@ -33,26 +33,7 @@ function addElement(RestoreData = null,refClass,props) {
} }
logicEngine.ActiveContainer.AddElement(newElement); logicEngine.ActiveContainer.AddElement(newElement);
logicEngine.ActiveContainer.Select(newElement); logicEngine.ActiveContainer.Select(newElement);
disableSelectedRCMs(false);
logicEngine.MovingElement = new Array(logicEngine.ActiveContainer.Selected.length);
for (let b = 0; b < logicEngine.ActiveContainer.Selected.length; b++) {
logicEngine.ActiveContainer.Selected[b].X = (logicEngine.Mouse.x - logicEngine.Panning.OffsetX) - (logicEngine.ActiveContainer.Selected[b].Width/2);
logicEngine.ActiveContainer.Selected[b].Y = (logicEngine.Mouse.y - logicEngine.Panning.OffsetY) - (logicEngine.ActiveContainer.Selected[b].Height/2);
logicEngine.MovingElement[b] = {
StartX: logicEngine.ActiveContainer.Selected[b].X,
StartY: logicEngine.ActiveContainer.Selected[b].Y
};
logicEngine.MovingElementMouseStartX = logicEngine.Mouse.x;
logicEngine.MovingElementMouseStartY = logicEngine.Mouse.y;
}
let rect = logicEngine.Canvas.getBoundingClientRect();
let realMouseX = logicEngine.Mouse.x + rect.left;
let realMouseY = logicEngine.Mouse.y + rect.top;
logicEngine.MouseDown = true;
logicEngine.DrawOffCanvasElement({clientX: realMouseX, clientY: realMouseY});
disableSelectedMenus(false);
return newElement; return newElement;
} }
@ -190,6 +171,43 @@ function GetCopyObject() {
} }
} }
function BuildTopMenu() {
// Make sure settings are set correct
if (logicEngine.Settings.HideConnections) {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.TopConnections) {
tfm_ConnLayer.innerHTML = '<span class="blankbox">&nbsp;</span>Connections Above';
} else {
tfm_ConnLayer.innerHTML = '<span class="blankbox">&nbsp;</span>Connections Below';
}
if (!logicEngine.Settings.ShowFPS) {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.ShowGrid) {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.SnapGrid) {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
in_GridSize.value = logicEngine.Settings.GridSize;
}
function BuildToolbox() { function BuildToolbox() {
let toolbox = document.getElementById("inner-left-menu"); let toolbox = document.getElementById("inner-left-menu");
@ -249,9 +267,31 @@ function isVersionNewer(version1,version2,orEqual = true) {
return false; return false;
} }
function disableSelectedMenus(bool) { function disableSelectedRCMs(bool) {
disableSelectedRCMs(bool); let rcm_Delete = document.getElementById("rcm_Delete");
disableSelectedTFMs(bool); let rcm_Disconnect = document.getElementById("rcm_Disconnect");
let tfm_Delete = document.getElementById("tfm_Delete");
let tfm_Disconnect = document.getElementById("tfm_Disconnect");
if (bool) {
rcm_Delete.classList.add("disabled");
rcm_Disconnect.classList.add("disabled");
tfm_Delete.classList.add("disabled");
tfm_Disconnect.classList.add("disabled");
} else {
rcm_Delete.classList.remove("disabled");
rcm_Disconnect.classList.remove("disabled");
tfm_Delete.classList.remove("disabled");
tfm_Disconnect.classList.remove("disabled");
}
}
function showRCM(evt) {
evt.preventDefault();
let rcm = document.getElementById("RightClickMenu");
rcm.style.left = (evt.clientX-40) + "px";
rcm.style.top = (evt.clientY-25) + "px";
rcm.style.display = "block";
} }
function ShowHelp() { function ShowHelp() {
@ -266,9 +306,12 @@ function HideHelp() {
helpWindow.style.display = "none"; helpWindow.style.display = "none";
} }
function HidePropertiesWindow() { function hideMenus() {
let propwin = document.getElementById("PropertiesBox"); let tds = document.getElementsByClassName("top-menu-div");
propwin.style.display = "none"; for (let a = 0; a < tds.length; a++) {
tds[a].setAttribute('style','display: none;');
}
} }
function SaveSettings() { function SaveSettings() {
@ -385,8 +428,8 @@ function loadActiveContainer(Elements) {
logicEngine.MovingElement = new Array(logicEngine.ActiveContainer.Selected.length); logicEngine.MovingElement = new Array(logicEngine.ActiveContainer.Selected.length);
for (let b = 0; b < logicEngine.ActiveContainer.Selected.length; b++) { for (let b = 0; b < logicEngine.ActiveContainer.Selected.length; b++) {
logicEngine.ActiveContainer.Selected[b].X = (logicEngine.ActiveContainer.Selected[b].X - lowestX) + (logicEngine.Mouse.x - logicEngine.Panning.OffsetX) - ((highestX-lowestX)/2); logicEngine.ActiveContainer.Selected[b].X = (logicEngine.ActiveContainer.Selected[b].X - lowestX) + logicEngine.Mouse.x - ((highestX-lowestX)/2);
logicEngine.ActiveContainer.Selected[b].Y = (logicEngine.ActiveContainer.Selected[b].Y - lowestY) + (logicEngine.Mouse.y - logicEngine.Panning.OffsetY) - ((highestY-lowestY)/2); logicEngine.ActiveContainer.Selected[b].Y = (logicEngine.ActiveContainer.Selected[b].Y - lowestY) + logicEngine.Mouse.y - ((highestY-lowestY)/2);
logicEngine.MovingElement[b] = { logicEngine.MovingElement[b] = {
StartX: logicEngine.ActiveContainer.Selected[b].X, StartX: logicEngine.ActiveContainer.Selected[b].X,
StartY: logicEngine.ActiveContainer.Selected[b].Y StartY: logicEngine.ActiveContainer.Selected[b].Y

View File

@ -150,7 +150,7 @@ class LogicEngineSettings {
CreateIC: {Key: "i", // lowercase CreateIC: {Key: "i", // lowercase
Alt: false, Alt: false,
Shift: true, Shift: true,
Ctrl: false, Ctrl: true,
Meta: false, Meta: false,
Name: "Create IC", Name: "Create IC",
Description: "Turns the current design into an IC", Description: "Turns the current design into an IC",
@ -203,7 +203,7 @@ class LogicEngineSettings {
if (restoresettings) { if (restoresettings) {
let othis = this; let othis = this;
Object.keys(restoresettings).forEach(function(key) { Object.keys(restoresettings).forEach(function(key) {
if (key != "Keybindings") othis[key] = restoresettings[key]; //TODO: Iterate keybindings as well othis[key] = restoresettings[key];
}); });
} }
} }
@ -284,7 +284,6 @@ class LogicEngine {
} }
element.MouseDown(mousePos); element.MouseDown(mousePos);
} else { } else {
this.HideOffCanvasElement();
this.MouseDown = true; this.MouseDown = true;
this.ActiveLink = false; this.ActiveLink = false;
if (this.ControlPressed) { if (this.ControlPressed) {
@ -304,9 +303,9 @@ class LogicEngine {
} }
} }
if (this.ActiveContainer.Selected?.length > 0) { if (this.ActiveContainer.Selected?.length > 0) {
disableSelectedMenus(false); disableSelectedRCMs(false);
} else { } else {
disableSelectedMenus(true); disableSelectedRCMs(true);
} }
} }
} }
@ -330,12 +329,10 @@ class LogicEngine {
this.ActiveContainer.Selected = false; this.ActiveContainer.Selected = false;
let PropertiesBox = document.getElementById("PropertiesBox"); let PropertiesBox = document.getElementById("PropertiesBox");
PropertiesBox.style.display = "none"; PropertiesBox.style.display = "none";
this.HideOffCanvasElement();
} }
this.MovingElement = false; this.MovingElement = false;
this.MouseDown = false; this.MouseDown = false;
this.HideOffCanvasElement();
if (this.MultiSelectStart.InProgress) { if (this.MultiSelectStart.InProgress) {
this.MultiSelectStart.InProgress = false; this.MultiSelectStart.InProgress = false;
@ -348,33 +345,9 @@ class LogicEngine {
} }
if (this.ActiveContainer.Selected?.length > 0) { if (this.ActiveContainer.Selected?.length > 0) {
disableSelectedMenus(false); disableSelectedRCMs(false);
} else { } else {
disableSelectedMenus(true); disableSelectedRCMs(true);
}
}
HideOffCanvasElement() {
let floatingCanvasDiv = document.getElementById("floatCanvas");
floatingCanvasDiv.style.display = "none";
}
DrawOffCanvasElement(evt) {
let rect = this.Canvas.getBoundingClientRect();
let floatingCanvasDiv = document.getElementById("floatCanvas");
let floatingCanvas = floatingCanvasDiv.getElementsByTagName("canvas")[0];
let floatingCtx = floatingCanvas.getContext("2d");
if ((evt.clientX >= (rect.left - (this.ActiveContainer.Selected[0].Width/2)))) {
floatingCanvasDiv.style.display = "none";
} else {
floatingCanvas.width = this.ActiveContainer.Selected[0].Width;
floatingCanvas.height = this.ActiveContainer.Selected[0].Height;
floatingCtx.clearRect(0, 0, floatingCanvas.width, floatingCanvas.height);
//console.log(this.ActiveContainer.Selected[0]);
floatingCtx.drawImage(this.ActiveContainer.Selected[0].StaticCanvas, 0, 0);
floatingCanvasDiv.style.left = (evt.clientX - (this.ActiveContainer.Selected[0].Width / 2)) + "px";
floatingCanvasDiv.style.top = (evt.clientY - (this.ActiveContainer.Selected[0].Height / 2)) + "px";
floatingCanvasDiv.style.display = "block";
} }
} }
@ -385,7 +358,6 @@ class LogicEngine {
if(this.MouseDown) { if(this.MouseDown) {
//console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y); //console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y);
if (this.MovingElement) { if (this.MovingElement) {
if (this.MovingElement.length == 1) this.DrawOffCanvasElement(evt);
if ((performance.now() - this.MouseDownTime) > 100) { if ((performance.now() - this.MouseDownTime) > 100) {
let xOffset = mousePos.x - this.MovingElementMouseStartX; let xOffset = mousePos.x - this.MovingElementMouseStartX;
@ -422,7 +394,6 @@ class LogicEngine {
} }
} else { } else {
this.ActiveContainer.checkMouseBounds(mousePos); this.ActiveContainer.checkMouseBounds(mousePos);
if (!this.MovingElement) this.HideOffCanvasElement();
} }
} }
@ -653,15 +624,13 @@ class LogicEngine {
let FPSOffset = 5 - this.Panning.OffsetX; let FPSOffset = 5 - this.Panning.OffsetX;
if (this.Settings.ShowFPS) { if (this.Settings.ShowFPS) {
ct.drawText(this.Ctx, FPSOffset, 15 - this.Panning.OffsetY, "FPS: " + this.FPS, "12px console", "#00ff00"); ct.drawText(this.Ctx, FPSOffset, 15 - this.Panning.OffsetY, "FPS: " + this.FPS, "12px console", "#00ff00");
ct.drawText(this.Ctx, FPSOffset, 29 - this.Panning.OffsetY, "Draw Speed: " + Math.floor(this.frameTimeUS) + "uS", "12px console", "#00ff00"); ct.drawText(this.Ctx, FPSOffset, 29 - this.Panning.OffsetY, "Potential FPS: " + Math.floor(this.PotentialFPS), "12px console", "#00ff00");
ct.drawText(this.Ctx, FPSOffset, 43 - this.Panning.OffsetY, "Potential FPS: " + Math.floor(this.PotentialFPS), "12px console", "#00ff00");
} }
let timeCheck = performance.now(); let timeCheck = performance.now();
this.FPSCounter++; this.FPSCounter++;
if (!(Math.round(timeCheck - this.LastFPSCheck) % 50)) { if (!(Math.round(timeCheck - this.LastFPSCheck) % 50)) {
let frameTimeUS = (performance.now() - startLoop) * 1000; let frameTimeUS = (performance.now() - startLoop) * 1000;
this.frameTimeUS = frameTimeUS;
let potentialFPS = 1000000 / frameTimeUS; let potentialFPS = 1000000 / frameTimeUS;
this.PotentialFPSAVGs[this.PotentialFPSAVGLoc] = Math.round(potentialFPS); this.PotentialFPSAVGs[this.PotentialFPSAVGLoc] = Math.round(potentialFPS);
this.PotentialFPSAVGLoc++; this.PotentialFPSAVGLoc++;

View File

@ -2,23 +2,444 @@
MatCat BrowserLogic Simulator MatCat BrowserLogic Simulator
*/ */
let Version = "0.4.16"; let Version = "0.4.11";
let spanVersion = document.getElementById("version"); let spanVersion = document.getElementById("version");
spanVersion.innerText = Version; spanVersion.innerText = Version;
// get the canvas and get the engine object going // get the canvas and get the engine object going
let lCanvasElement = document.getElementById("LogicPlane"); let lCanvasElement = document.getElementById("LogicPlane");
let logicEngine = new LogicEngine(lCanvasElement); let logicEngine = new LogicEngine(lCanvasElement);
// Get the game Tick going, set to 1ms but most browsers will min to 4ms // Get the game Tick going, this will be 4ms for now which is the fastest that is supported
setInterval(logicEngine.Scheduler.Tick.bind(logicEngine.Scheduler), 1); // by the HTML5 spec!
setInterval(logicEngine.Scheduler.Tick.bind(logicEngine.Scheduler), 4);
window.addEventListener('resize', function(evt) {
logicEngine.Resize(evt);
}, false);
document.addEventListener('copy', function(evt) {
evt.preventDefault();
let copyObject = GetCopyObject();
if (!copyObject) return;
evt.clipboardData.setData('logicparts/json',JSON.stringify(copyObject));
evt.clipboardData.setData('text',JSON.stringify(copyObject));
});
document.addEventListener('cut', function(evt) {
evt.preventDefault();
let copyObject = GetCopyObject();
if (!copyObject) return;
evt.clipboardData.setData('logicparts/json',JSON.stringify(copyObject));
evt.clipboardData.setData('text',JSON.stringify(copyObject));
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
disableSelectedRCMs(true);
});
document.addEventListener('paste', function(evt) {
evt.preventDefault();
if (evt.clipboardData.getData('logicparts/json')) {
//console.log(evt.clipboardData.getData('logicparts/json'));
loadActiveContainer(JSON.parse(evt.clipboardData.getData('logicparts/json')).Elements);
} else {
// Lets see if they pasted a proper LogicParts format atleast
if (evt.clipboardData.getData('text')) {
let jsonObj = JSON.parse(evt.clipboardData.getData('text'));
if (jsonObj?.LogicParts && jsonObj?.Paste) {
console.log("We got a paste of a general text object that is valid");
loadActiveContainer(jsonObj.Elements);
}
}
}
});
window.addEventListener('keydown', function(evt) {
logicEngine.Key_Press(evt);
}, false);
window.addEventListener('keyup', function(evt) {
logicEngine.Key_Up(evt);
}, false);
window.addEventListener('mouseup', function(evt) {
let rcm = document.getElementById("RightClickMenu");
rcm.style.display = "none";
let tfms = document.getElementsByClassName("top-menu-div");
for (let a = 0; a < tfms.length; a++) {
tfms[a].style.display = "none";
}
}, false);
lCanvasElement.addEventListener('mousedown', function(evt) {
logicEngine.Mouse_Down(evt);
}, false);
lCanvasElement.addEventListener('mouseup', function(evt) {
logicEngine.Mouse_Up(evt);
}, false);
window.addEventListener('mousemove', function(evt) {
logicEngine.Mouse_Move(evt);
}, false);
// Get the engine going // Get the engine going
logicEngine.StartEngine(); logicEngine.StartEngine();
RegisterEvents();
TopMenuListeners();
RightClickMenuListeners();
BuildToolbox(); BuildToolbox();
// Setup interface buttons
let btn_CloseWelcome = document.getElementById("btn_CloseWelcome");
btn_CloseWelcome.addEventListener('click', function(evt) {
let WelcomeScreen = document.getElementById("WelcomeWindow");
let DarkOverlay = document.getElementById("darkout-overlay");
WelcomeScreen.style.display = "none";
DarkOverlay.style.display = "none";
let chk_dontDisplayWelcome = document.getElementById("chk_dontDisplayWelcome");
if (chk_dontDisplayWelcome.checked) {
setCookie("hidewelcomescreen","true",3600);
}
}, false);
let tfm_CreateIC = document.getElementById("tfm_CreateIC");
tfm_CreateIC.addEventListener('click', function(evt) {
if (!tfm_CreateIC.classList.contains("disabled")) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "block";
setTimeout(function () {
hideMenus()
}, 10);
}
});
let rcm_CreateIC = document.getElementById("rcm_CreateIC");
rcm_CreateIC.addEventListener('click', function(evt) {
if (!this.classList.contains("disabled")) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "block";
}
});
let btn_CreateIC_Cancel = document.getElementById("btn_CreateIC_Cancel");
btn_CreateIC_Cancel.addEventListener('click', function(evt) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "none";
});
let btn_CreateIC_Create = document.getElementById("btn_CreateIC_Create");
btn_CreateIC_Create.addEventListener('click', function(evt) {
let CreateICBox = document.getElementById("CreateICBox");
let ICName = document.getElementById("ICName");
let ICDescription = document.getElementById("ICDescription");
createIC(logicEngine.ActiveContainer,ICName.value,ICDescription.value);
CreateICBox.style.display = "none";
});
let ICName = document.getElementById("ICName");
let ICDescription = document.getElementById("ICDescription");
ICName.addEventListener('input', function(evt){
btn_CreateIC_Create.disabled = true;
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
});
ICDescription.addEventListener('input', function(evt){
btn_CreateIC_Create.disabled = true;
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
});
let tfm_New = document.getElementById("tfm_New");
tfm_New.addEventListener('click', function(evt) {
logicEngine.ActiveContainer = new elementContainer();
logicEngine.Ctx.setTransform(1,0,0,1,0,0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
setTimeout(function(){hideMenus()},10);
});
let rcm_New = document.getElementById("rcm_New");
rcm_New.addEventListener('click', function(evt) {
logicEngine.ActiveContainer = new elementContainer();
logicEngine.Ctx.setTransform(1,0,0,1,0,0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
});
let rcm_Delete = document.getElementById("rcm_Delete");
rcm_Delete.addEventListener('click', function(evt) {
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
disableSelectedRCMs(true);
});
let tfm_Cut = document.getElementById("tfm_Cut");
tfm_Cut.addEventListener('click', function(evt) {
document.execCommand('cut');
disableSelectedRCMs(true);
setTimeout(function(){hideMenus()},10);
});
let tfm_Copy = document.getElementById("tfm_Copy");
tfm_Copy.addEventListener('click', function(evt) {
document.execCommand('copy');
disableSelectedRCMs(true);
setTimeout(function(){hideMenus()},10);
});
let tfm_Paste = document.getElementById("tfm_Paste");
tfm_Paste.addEventListener('click', function(evt) {
document.execCommand('paste');
disableSelectedRCMs(true);
setTimeout(function(){hideMenus()},10);
});
let tfm_Delete = document.getElementById("tfm_Delete");
tfm_Delete.addEventListener('click', function(evt) {
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
disableSelectedRCMs(true);
setTimeout(function(){hideMenus()},10);
});
let rcm_Disconect = document.getElementById("rcm_Disconnect");
rcm_Disconect.addEventListener('click', function(evt) {
for (let a = 0; a < logicEngine.ActiveContainer.Selected.length;a++) {
logicEngine.ActiveContainer.Selected[a].Disconnect();
}
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
});
let tfm_Disconect = document.getElementById("tfm_Disconnect");
tfm_Disconect.addEventListener('click', function(evt) {
for (let a = 0; a < logicEngine.ActiveContainer.Selected.length;a++) {
logicEngine.ActiveContainer.Selected[a]?.Disconnect();
}
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
setTimeout(function(){hideMenus()},10);
});
let tfm_SelectAll = document.getElementById("tfm_SelectAll");
tfm_SelectAll.addEventListener('click', function(evt) {
let elements = new Array();
for (let a = 0; a < logicEngine.ActiveContainer.Elements?.length;a++) {
elements.push(logicEngine.ActiveContainer.Elements[a]);
}
logicEngine.ActiveContainer.Selected = elements;
setTimeout(function(){hideMenus()},10);
});
let tfm_Save = document.getElementById("tfm_Save");
tfm_Save.addEventListener('click', function(evt) {
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display="block";
saveWindow.style.left = Math.round((window.innerWidth / 2) - (saveWindow.clientWidth/2)) + "px";
saveWindow.style.top = Math.round((window.innerHeight / 2) - (saveWindow.clientHeight/2)) + "px";
setTimeout(function(){hideMenus()},10);
});
let btn_SaveDesign = document.getElementById("btn_SaveDesign");
btn_SaveDesign.addEventListener('click', function(evt) {
let DesignName = document.getElementById("saveName");
let savestate = createSaveState(logicEngine.ActiveContainer);
savestate.Name = DesignName.value;
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display = "none";
download(savestate.Name + ".LogicParts",savestate);
});
let btn_Save_Cancel = document.getElementById("btn_CancelSave");
btn_Save_Cancel.addEventListener('click', function(evt) {
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display = "none";
});
let file_Load = document.getElementById("file_Load");
let tfm_Open = document.getElementById("tfm_Open");
tfm_Open.addEventListener('click', function(evt) {
setTimeout(function(){hideMenus()},10);
file_Load.click();
});
file_Load.addEventListener('change', function(evt) {
let fread = new FileReader();
fread.onload = (function (theFile) {
return function (e) {
try {
let restoredata = JSON.parse(e.target.result);
loadresult = loadsave(restoredata);
if (!loadresult) {
switch(loadresult) {
case -1:
alert("Invalid LogicParts file!");
break;
case -2:
alert("The version of MatCat BrowserLogic cannot open this save version!");
break;
default:
alert("Bad save file!");
break;
}
}
} catch (ex) {
alert("Bad file! " + ex);
console.log(ex);
}
}
})(evt.target.files[0]);
fread.readAsText(evt.target.files[0]);
}, false);
/*
Generate the top menu item listeners
*/
let tfms = document.getElementsByClassName("top-menu-item");
for (let a = 0; a < tfms.length; a++) {
tfms[a].addEventListener("click", function (evt) {
let tfm = document.getElementById(tfms[a].id + "Menu");
let tfm_rect = tfms[a].getBoundingClientRect();
tfm.style.left = (tfm_rect.left) + "px";
tfm.style.top = (tfm_rect.top + tfm_rect.height) + "px";
tfm.style.display = "block";
});
let tfm = document.getElementById(tfms[a].id + "Menu");
if (!tfm.classList.contains("keybinding-complete")) {
tfm.classList.add("keybinding-complete");
let menuItems = tfm?.getElementsByTagName("li");
for (let b = 0; b < menuItems?.length; b++) {
if (menuItems[b]?.getAttribute("value")) menuItems[b].innerHTML = '<span class="menuitem-label">' + menuItems[b].innerHTML + '</span><span class="menuitem-shortcut">' + (KeybindToString(logicEngine.Settings.Keybindings[menuItems[b].getAttribute("value")])) + '</span>';
}
}
}
let tfm_About = document.getElementById("tfm_About");
tfm_About.addEventListener("click", function (evt) {
let WelcomeScreen = document.getElementById("WelcomeWindow");
WelcomeScreen.style.display = "block";
setTimeout(function(){hideMenus()},10);
});
let tfm_ShowConns = document.getElementById("tfm_ShowConnections");
tfm_ShowConns.addEventListener("click", function (evt) {
if (logicEngine.Settings.HideConnections) {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.HideConnections = false;
} else {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.HideConnections = true;
}
SaveSettings();
setTimeout(function(){hideMenus()},10);
});
let tfm_ConnLayer = document.getElementById("tfm_ConnectionLayer");
tfm_ConnLayer.addEventListener("click", function (evt) {
if (logicEngine.Settings.TopConnections) {
tfm_ConnLayer.innerText = "Connections Above";
logicEngine.Settings.TopConnections = false;
} else {
tfm_ConnLayer.innerText = "Connections Below";
logicEngine.Settings.TopConnections = true;
}
SaveSettings();
setTimeout(function(){hideMenus()},10);
});
let tfm_ShowFPS = document.getElementById("tfm_ShowFPS");
tfm_ShowFPS.addEventListener("click", function (evt) {
if (logicEngine.Settings.ShowFPS) {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.ShowFPS = false;
} else {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.ShowFPS = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function(){hideMenus()},10);
});
let tfm_Pan2Center = document.getElementById("tfm_Pan2Center");
tfm_Pan2Center.addEventListener("click", function (evt) {
logicEngine.Ctx.setTransform(1,0,0,1,0,0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
setTimeout(function(){hideMenus()},10);
});
let tfm_ShowGrid = document.getElementById("tfm_ShowGrid");
tfm_ShowGrid.addEventListener("click", function (evt) {
if (logicEngine.Settings.ShowGrid) {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.ShowGrid = false;
} else {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.ShowGrid = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function(){hideMenus()},10);
});
let tfm_SnapGrid = document.getElementById("tfm_SnapGrid");
tfm_SnapGrid.addEventListener("click", function (evt) {
if (logicEngine.Settings.SnapGrid) {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.SnapGrid = false;
} else {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.SnapGrid = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function(){hideMenus()},10);
});
let in_GridSize = document.getElementById("in_GridSize");
in_GridSize.addEventListener("change", function (evt) {
logicEngine.Settings.GridSize = parseInt(in_GridSize.value);
logicEngine.Resize("");
SaveSettings();
//setTimeout(function(){hideMenus()},10);
});
let tfm_Help = document.getElementById("tfm_Help");
tfm_Help.addEventListener("click", function (evt) {
setTimeout(function(){hideMenus()},10);
ShowHelp();
});
let helpWindow = document.getElementById("HelpWindow");
let helpWindow_Close = helpWindow.getElementsByClassName("CloseWindow")[0];
helpWindow_Close.addEventListener("click", function (evt) {
HideHelp();
});
let leftmenu = document.getElementById("left-menu");
let propwin = document.getElementById("PropertiesBox");
lCanvasElement.addEventListener( "contextmenu", function(evt) {showRCM(evt)});
leftmenu.addEventListener( "contextmenu", function(evt) {showRCM(evt)});
propwin.addEventListener( "contextmenu", function(evt) {showRCM(evt)});
let topbar = document.getElementById("top-bar");
topbar.addEventListener( "contextmenu", function(evt) {
evt.preventDefault();
});
BuildTopMenu(); BuildTopMenu();
CheckForWelcomeCookie(); CheckForWelcomeCookie();

View File

@ -1,212 +0,0 @@
function RegisterEvents() {
/*
DISPLAY AND RESIZING
*/
window.addEventListener('resize', function (evt) {
logicEngine.Resize(evt);
}, false);
/*
SYSTEM EVENTS
*/
document.addEventListener('copy', function (evt) {
evt.preventDefault();
let copyObject = GetCopyObject();
if (!copyObject) return;
evt.clipboardData.setData('logicparts/json', JSON.stringify(copyObject));
evt.clipboardData.setData('text', JSON.stringify(copyObject));
});
document.addEventListener('cut', function (evt) {
evt.preventDefault();
let copyObject = GetCopyObject();
if (!copyObject) return;
evt.clipboardData.setData('logicparts/json', JSON.stringify(copyObject));
evt.clipboardData.setData('text', JSON.stringify(copyObject));
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
disableSelectedMenus(true);
});
document.addEventListener('paste', function (evt) {
evt.preventDefault();
if (evt.clipboardData.getData('logicparts/json')) {
//console.log(evt.clipboardData.getData('logicparts/json'));
loadActiveContainer(JSON.parse(evt.clipboardData.getData('logicparts/json')).Elements);
} else {
// Lets see if they pasted a proper LogicParts format atleast
if (evt.clipboardData.getData('text')) {
let jsonObj = JSON.parse(evt.clipboardData.getData('text'));
if (jsonObj?.LogicParts && jsonObj?.Paste) {
console.log("We got a paste of a general text object that is valid");
loadActiveContainer(jsonObj.Elements);
}
}
}
});
/*
KEYBOARD EVENTS
*/
window.addEventListener('keydown', function (evt) {
logicEngine.Key_Press(evt);
}, false);
window.addEventListener('keyup', function (evt) {
logicEngine.Key_Up(evt);
}, false);
/*
MOUSE EVENTS
*/
window.addEventListener('mouseup', function (evt) {
let rcm = document.getElementById("RightClickMenu");
rcm.style.display = "none";
let tfms = document.getElementsByClassName("top-menu-div");
for (let a = 0; a < tfms.length; a++) {
tfms[a].style.display = "none";
}
}, false);
lCanvasElement.addEventListener('mousedown', function (evt) {
logicEngine.Mouse_Down(evt);
}, false);
lCanvasElement.addEventListener('mouseup', function (evt) {
logicEngine.Mouse_Up(evt);
}, false);
window.addEventListener('mousemove', function (evt) {
logicEngine.Mouse_Move(evt);
}, false);
/*
WINDOW CONTROLS
*/
let btn_CloseWelcome = document.getElementById("btn_CloseWelcome");
btn_CloseWelcome.addEventListener('click', function (evt) {
let WelcomeScreen = document.getElementById("WelcomeWindow");
let DarkOverlay = document.getElementById("darkout-overlay");
WelcomeScreen.style.display = "none";
DarkOverlay.style.display = "none";
let chk_dontDisplayWelcome = document.getElementById("chk_dontDisplayWelcome");
if (chk_dontDisplayWelcome.checked) {
setCookie("hidewelcomescreen", "true", 3600);
}
}, false);
let btn_CreateIC_Cancel = document.getElementById("btn_CreateIC_Cancel");
btn_CreateIC_Cancel.addEventListener('click', function (evt) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "none";
});
let btn_CreateIC_Create = document.getElementById("btn_CreateIC_Create");
btn_CreateIC_Create.addEventListener('click', function (evt) {
let CreateICBox = document.getElementById("CreateICBox");
let ICName = document.getElementById("ICName");
let ICDescription = document.getElementById("ICDescription");
createIC(logicEngine.ActiveContainer, ICName.value, ICDescription.value);
CreateICBox.style.display = "none";
});
let ICName = document.getElementById("ICName");
let ICDescription = document.getElementById("ICDescription");
ICName.addEventListener('input', function (evt) {
btn_CreateIC_Create.disabled = true;
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
});
ICDescription.addEventListener('input', function (evt) {
btn_CreateIC_Create.disabled = true;
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
});
let btn_SaveDesign = document.getElementById("btn_SaveDesign");
btn_SaveDesign.addEventListener('click', function (evt) {
let DesignName = document.getElementById("saveName");
let savestate = createSaveState(logicEngine.ActiveContainer);
savestate.Name = DesignName.value;
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display = "none";
download(savestate.Name + ".LogicParts", savestate);
});
let btn_Save_Cancel = document.getElementById("btn_CancelSave");
btn_Save_Cancel.addEventListener('click', function (evt) {
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display = "none";
});
let file_Load = document.getElementById("file_Load");
let tfm_Open = document.getElementById("tfm_Open");
file_Load.addEventListener('change', function (evt) {
let fread = new FileReader();
fread.onload = (function (theFile) {
return function (e) {
try {
let restoredata = JSON.parse(e.target.result);
loadresult = loadsave(restoredata);
if (!loadresult) {
switch (loadresult) {
case -1:
alert("Invalid LogicParts file!");
break;
case -2:
alert("The version of MatCat BrowserLogic cannot open this save version!");
break;
default:
alert("Bad save file!");
break;
}
}
} catch (ex) {
alert("Bad file! " + ex);
console.log(ex);
}
}
})(evt.target.files[0]);
fread.readAsText(evt.target.files[0]);
}, false);
let in_GridSize = document.getElementById("in_GridSize");
in_GridSize.addEventListener("change", function (evt) {
logicEngine.Settings.GridSize = parseInt(in_GridSize.value);
logicEngine.Resize("");
SaveSettings();
//setTimeout(function(){hideMenus()},10);
});
let helpWindow = document.getElementById("HelpWindow");
let helpWindow_Close = helpWindow.getElementsByClassName("CloseWindow")[0];
helpWindow_Close.addEventListener("click", function (evt) {
HideHelp();
});
let leftmenu = document.getElementById("left-menu");
let propwin = document.getElementById("PropertiesBox");
lCanvasElement.addEventListener("contextmenu", function (evt) {
showRCM(evt)
});
leftmenu.addEventListener("contextmenu", function (evt) {
showRCM(evt)
});
propwin.addEventListener("contextmenu", function (evt) {
showRCM(evt)
});
let topbar = document.getElementById("top-bar");
topbar.addEventListener("contextmenu", function (evt) {
evt.preventDefault();
});
}

View File

@ -1,56 +0,0 @@
function disableSelectedRCMs(bool) {
let rcm_Delete = document.getElementById("rcm_Delete");
let rcm_Disconnect = document.getElementById("rcm_Disconnect");
if (bool) {
rcm_Delete.classList.add("disabled");
rcm_Disconnect.classList.add("disabled");
} else {
rcm_Delete.classList.remove("disabled");
rcm_Disconnect.classList.remove("disabled");
}
}
function showRCM(evt) {
evt.preventDefault();
let rcm = document.getElementById("RightClickMenu");
rcm.style.left = (evt.clientX-40) + "px";
rcm.style.top = (evt.clientY-25) + "px";
rcm.style.display = "block";
}
function RightClickMenuListeners() {
let rcm_CreateIC = document.getElementById("rcm_CreateIC");
rcm_CreateIC.addEventListener('click', function (evt) {
if (!this.classList.contains("disabled")) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "block";
}
});
let rcm_New = document.getElementById("rcm_New");
rcm_New.addEventListener('click', function (evt) {
logicEngine.ActiveContainer = new elementContainer();
logicEngine.Ctx.setTransform(1, 0, 0, 1, 0, 0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
HidePropertiesWindow();
disableSelectedMenus(true);
});
let rcm_Delete = document.getElementById("rcm_Delete");
rcm_Delete.addEventListener('click', function (evt) {
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
HidePropertiesWindow();
disableSelectedMenus(true);
});
let rcm_Disconect = document.getElementById("rcm_Disconnect");
rcm_Disconect.addEventListener('click', function (evt) {
for (let a = 0; a < logicEngine.ActiveContainer.Selected.length; a++) {
logicEngine.ActiveContainer.Selected[a].Disconnect();
}
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
});
}

View File

@ -1,304 +0,0 @@
function BuildTopMenu() {
// Make sure settings are set correct
let tfm_ShowConns = document.getElementById("tfm_ShowConnections");
let tfm_ConnLayer = document.getElementById("tfm_ConnectionLayer");
if (logicEngine.Settings.HideConnections) {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.TopConnections) {
tfm_ConnLayer.innerHTML = '<span class="blankbox">&nbsp;</span>Connections Above';
} else {
tfm_ConnLayer.innerHTML = '<span class="blankbox">&nbsp;</span>Connections Below';
}
if (!logicEngine.Settings.ShowFPS) {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.ShowGrid) {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
if (!logicEngine.Settings.SnapGrid) {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
} else {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
}
in_GridSize.value = logicEngine.Settings.GridSize;
}
function disableSelectedTFMs(bool) {
let tfm_Delete = document.getElementById("tfm_Delete");
let tfm_Disconnect = document.getElementById("tfm_Disconnect");
if (bool) {
tfm_Delete.classList.add("disabled");
tfm_Disconnect.classList.add("disabled");
} else {
tfm_Delete.classList.remove("disabled");
tfm_Disconnect.classList.remove("disabled");
}
}
function hideMenus() {
let tds = document.getElementsByClassName("top-menu-div");
for (let a = 0; a < tds.length; a++) {
tds[a].setAttribute('style','display: none;');
}
}
function TopMenuListeners() {
/*
All the listeners for the top menu
*/
let tfm_CreateIC = document.getElementById("tfm_CreateIC");
tfm_CreateIC.addEventListener('click', function (evt) {
if (!tfm_CreateIC.classList.contains("disabled")) {
let CreateICBox = document.getElementById("CreateICBox");
CreateICBox.style.display = "block";
setTimeout(function () {
hideMenus()
}, 10);
}
});
let tfm_New = document.getElementById("tfm_New");
tfm_New.addEventListener('click', function (evt) {
logicEngine.ActiveContainer = new elementContainer();
logicEngine.Ctx.setTransform(1, 0, 0, 1, 0, 0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
HidePropertiesWindow();
disableSelectedMenus(true);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Cut = document.getElementById("tfm_Cut");
tfm_Cut.addEventListener('click', function (evt) {
document.execCommand('cut');
disableSelectedMenus(true);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Copy = document.getElementById("tfm_Copy");
tfm_Copy.addEventListener('click', function (evt) {
document.execCommand('copy');
disableSelectedMenus(true);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Paste = document.getElementById("tfm_Paste");
tfm_Paste.addEventListener('click', function (evt) {
document.execCommand('paste');
disableSelectedMenus(true);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Delete = document.getElementById("tfm_Delete");
tfm_Delete.addEventListener('click', function (evt) {
logicEngine.Key_Press({ctrlKey: false, key: "Delete"});
HidePropertiesWindow();
disableSelectedMenus(true);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Disconect = document.getElementById("tfm_Disconnect");
tfm_Disconect.addEventListener('click', function (evt) {
for (let a = 0; a < logicEngine.ActiveContainer.Selected.length; a++) {
logicEngine.ActiveContainer.Selected[a]?.Disconnect();
}
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_SelectAll = document.getElementById("tfm_SelectAll");
tfm_SelectAll.addEventListener('click', function (evt) {
let elements = new Array();
for (let a = 0; a < logicEngine.ActiveContainer.Elements?.length; a++) {
elements.push(logicEngine.ActiveContainer.Elements[a]);
}
logicEngine.ActiveContainer.Selected = elements;
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Save = document.getElementById("tfm_Save");
tfm_Save.addEventListener('click', function (evt) {
let saveWindow = document.getElementById("SaveWindow");
saveWindow.style.display = "block";
saveWindow.style.left = Math.round((window.innerWidth / 2) - (saveWindow.clientWidth / 2)) + "px";
saveWindow.style.top = Math.round((window.innerHeight / 2) - (saveWindow.clientHeight / 2)) + "px";
setTimeout(function () {
hideMenus()
}, 10);
});
tfm_Open.addEventListener('click', function (evt) {
setTimeout(function () {
hideMenus()
}, 10);
file_Load.click();
});
/*
Generate the top menu item listeners
*/
let tfms = document.getElementsByClassName("top-menu-item");
for (let a = 0; a < tfms.length; a++) {
tfms[a].addEventListener("click", function (evt) {
let tfm = document.getElementById(tfms[a].id + "Menu");
let tfm_rect = tfms[a].getBoundingClientRect();
tfm.style.left = (tfm_rect.left) + "px";
tfm.style.top = (tfm_rect.top + tfm_rect.height) + "px";
tfm.style.display = "block";
});
let tfm = document.getElementById(tfms[a].id + "Menu");
if (!tfm.classList.contains("keybinding-complete")) {
tfm.classList.add("keybinding-complete");
let menuItems = tfm?.getElementsByTagName("li");
for (let b = 0; b < menuItems?.length; b++) {
if (menuItems[b]?.getAttribute("value")) menuItems[b].innerHTML = '<span class="menuitem-label">' + menuItems[b].innerHTML + '</span><span class="menuitem-shortcut">' + (KeybindToString(logicEngine.Settings.Keybindings[menuItems[b].getAttribute("value")])) + '</span>';
}
}
}
let tfm_About = document.getElementById("tfm_About");
tfm_About.addEventListener("click", function (evt) {
let WelcomeScreen = document.getElementById("WelcomeWindow");
WelcomeScreen.style.display = "block";
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_ShowConns = document.getElementById("tfm_ShowConnections");
tfm_ShowConns.addEventListener("click", function (evt) {
if (logicEngine.Settings.HideConnections) {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.HideConnections = false;
} else {
let sgSpan = tfm_ShowConns.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.HideConnections = true;
}
SaveSettings();
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_ConnLayer = document.getElementById("tfm_ConnectionLayer");
tfm_ConnLayer.addEventListener("click", function (evt) {
if (logicEngine.Settings.TopConnections) {
tfm_ConnLayer.innerText = "Connections Above";
logicEngine.Settings.TopConnections = false;
} else {
tfm_ConnLayer.innerText = "Connections Below";
logicEngine.Settings.TopConnections = true;
}
SaveSettings();
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_ShowFPS = document.getElementById("tfm_ShowFPS");
tfm_ShowFPS.addEventListener("click", function (evt) {
if (logicEngine.Settings.ShowFPS) {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.ShowFPS = false;
} else {
let sgSpan = tfm_ShowFPS.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.ShowFPS = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Pan2Center = document.getElementById("tfm_Pan2Center");
tfm_Pan2Center.addEventListener("click", function (evt) {
logicEngine.Ctx.setTransform(1, 0, 0, 1, 0, 0);
logicEngine.Panning.OffsetX = 0;
logicEngine.Panning.OffsetY = 0;
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_ShowGrid = document.getElementById("tfm_ShowGrid");
tfm_ShowGrid.addEventListener("click", function (evt) {
if (logicEngine.Settings.ShowGrid) {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.ShowGrid = false;
} else {
let sgSpan = tfm_ShowGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.ShowGrid = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_SnapGrid = document.getElementById("tfm_SnapGrid");
tfm_SnapGrid.addEventListener("click", function (evt) {
if (logicEngine.Settings.SnapGrid) {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerHTML = "&nbsp;";
logicEngine.Settings.SnapGrid = false;
} else {
let sgSpan = tfm_SnapGrid.getElementsByClassName("checkbox")[0];
sgSpan.innerText = "✓";
logicEngine.Settings.SnapGrid = true;
}
SaveSettings();
logicEngine.Resize("");
setTimeout(function () {
hideMenus()
}, 10);
});
let tfm_Help = document.getElementById("tfm_Help");
tfm_Help.addEventListener("click", function (evt) {
setTimeout(function () {
hideMenus()
}, 10);
ShowHelp();
});
}