Update to 0.2.0, dark theme, click linking, and properties

This commit is contained in:
MatCat 2021-02-21 01:51:21 -08:00
parent be4aa54aaf
commit 0a38839418
5 changed files with 450 additions and 143 deletions

View File

@ -12,5 +12,11 @@ To be decided, but at this moment this code is open source and free to use for n
## Changelog
### 0.2.0
* Switched to a dark theme
* Added left hand toolbar
* Linking can now be done by clicking on an output then an input
* Added new element: Clock
### 0.1.0
Initial public release.

View File

@ -10,9 +10,12 @@
/* ==========================================================================
Base styles: opinionated defaults
========================================================================== */
body {
background-color: #454550;
}
html {
color: #222;
color: #ddd;
font-size: 1em;
line-height: 1.4;
}
@ -261,3 +264,51 @@ textarea {
}
}
#left-menu {
width: 200px;
max-width: 200px;
height: 100vh;
display: inline-block;
border: 1px solid black;
margin: 0px;
padding: 0px;
}
#top-bar {
height: 50px;
overflow: auto;
margin: 0px;
padding: 0px;
background-color: #222;
font-size: 2em;
}
#PropertiesBox {
display: none;
position: absolute;
right: 20px;
top: 50px;
width: 300px;
height: 200px;
background-color: #444455;
border: 1px solid black;
}
#PropertiesBoxTitle {
text-align: center;
background-color: #222222;
font-size: 1.5em;
}
#PropertiesBoxContent {
padding: 5px;
}
#LogicPlane {
outline: none;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0); /* mobile webkit */
}
#propertiesTable {
width: 100%;
}

View File

@ -12,7 +12,6 @@
<meta property="og:url" content="">
<meta property="og:image" content="">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="icon.png">
<!-- Place favicon.ico in the root directory -->
@ -26,20 +25,31 @@
<!-- Add your site or application content here -->
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
<div style="height: 50px; overflow: auto; margin: 0px; padding: 0px;">
MatCat BrowserLogic <span id="version">0.1.0</span>
<input type="button" id="btn_Link" value="<->"/>
<input type="button" id="btn_AddAND" value="&"/>
<input type="button" id="btn_AddNAND" value="!&"/>
<input type="button" id="btn_AddOR" value="|"/>
<input type="button" id="btn_AddNOR" value="!|"/>
<input type="button" id="btn_AddXOR" value="^"/>
<input type="button" id="btn_AddXNOR" value="!^"/>
<input type="button" id="btn_AddBTN" value="[]"/>
<input type="button" id="btn_Delete" value="Delete"/>
<div id="top-bar">
MatCat BrowserLogic <span id="version"> </span>
</div>
<div id="left-menu">
<div style="margin: 5px;">
<input type="button" id="btn_AddAND" value="& AND"/><br />
<input type="button" id="btn_AddNAND" value="!& NAND"/><br />
<input type="button" id="btn_AddOR" value="| OR"/><br />
<input type="button" id="btn_AddNOR" value="!| NOR"/><br />
<input type="button" id="btn_AddXOR" value="^ XOR"/><br />
<input type="button" id="btn_AddXNOR" value="!^ XNOR"/><br />
<input type="button" id="btn_AddSWITCH" value="|- SWITCH"/><br />
<input type="button" id="btn_AddCLK" value="🕑 Clock"/><br />
<input type="button" id="btn_Delete" value="🗑 Delete"/>
</div>
</div>
<canvas id="LogicPlane" width="400" height="300" style="margin: 0px; padding: 0px; position: absolute; top: 50px; left: 202px;"></canvas>
<div id="PropertiesBox">
<div id="PropertiesBoxTitle">
Properties
</div>
<div id="PropertiesBoxContent">
Content
</div>
</div>
<canvas id="LogicPlane" width="400" height="300" style="margin: 0px; padding: 0px;"></canvas>
<script src="js/logicengine.js"></script>
<script src="js/main.js"></script>

View File

@ -13,10 +13,88 @@ function averageArray(arr) {
return arr.reduce((a, b) => (a + b)) / arr.length;
}
function length2D(x1,y1,x2,y2) {
let xDist = x1 - x2;
let yDist = y1 - y2;
return Math.sqrt(xDist*xDist + yDist * yDist);
}
/*
Now we can get into the classes
*/
class LogicEngineSettings {
constructor() {
this.ActiveConnectionColor = "#aabbaa";
this.InactiveConnectionColor = "#bbaaaa";
this.LinkWidth = "2";
this.LinkDash = [];
this.LinkingConnectionColor = "#aabbbb";
this.LinkingWidth = "3";
this.LinkingDash = [2,2];
}
}
class Task {
constructor(taskname,taskdescription,tasktype,tasktime,callback,deleteonrun = false) {
// tasktype: 0: interval, 1: fixed time
this.Name = taskname;
this.Description = taskdescription;
this.Type = tasktype;
this.Enabled = true;
this.Time = tasktime;
this.LastCall = Date.now();
this.CallCount = 0;
this.DeleteOnRun = false;
if (deleteonrun) this.DeleteOnRun = true;
this.Callback = callback;
if (!(tasktype >= 0 && tasktype <= 1)) this.Type = 0;
}
CheckTime() {
let time = this.Time;
if (this.Type == 0) time = this.LastCall + this.Time;
if (this.Enabled && (Date.now() >= time)) {
this.LastCall = Date.now();
this.CallCount++;
if (this.Type == 1 || this.DeleteOnRun == true) this.Enabled = false;
this.Callback();
return true;
}
return false;
}
}
class ScheduleEngine {
constructor() {
this.Tasks = new Array();
}
addTask(task) {
this.Tasks.push(task);
}
deleteTask(task) {
for (let a = 0; a < this.Tasks.length; a++) {
if (this.Tasks[a] == task) {
this.Tasks.splice(a,1);
return true;
}
}
return false;
}
Tick() {
for (let a = 0; a < this.Tasks.length; a++) {
this.Tasks[a].CheckTime();
if (!this.Tasks[a].Enabled && this.Tasks[a].DeleteOnRun) {
this.Tasks.splice(a,1);
a--;
}
}
}
}
class CanvasTools {
constructor() {
@ -68,6 +146,38 @@ class CanvasTools {
}
class ElementProperty {
constructor(name,type,callback,defaultValue,currentValue = false,values=false,min=0,max=12) {
/*
Types
---------------------------------------
bool Boolean Values
int Integer Value
string String Value
list Dropdown box of values
Callback is an object of:
---------------------------------------
CBObject Object to call function on
CBFunction The function
*/
this.Name = name;
this.Type = type;
this.Callback = callback;
this.DefaultValue = defaultValue;
if (!currentValue) currentValue = defaultValue;
this.CurrentValue = currentValue;
this.Values = values;
if (!values) this.Values = new Array();
this.Minimium = min;
this.Maximium = max;
}
Call(value) {
this.Callback.CBObject[this.Callback.CBFunction](value);
}
}
class ElementConnection {
constructor(elementContainer,element,input) {
this.Container = elementContainer;
@ -78,12 +188,11 @@ class ElementConnection {
class Element extends CanvasTools {
constructor(Inputs) {
constructor(logicengine,Inputs) {
super();
this.Name = "Element";
this.Designator = "";
this.Inputs = new Array(Inputs);
this.totalInputs = Inputs;
this.Width = 150;
this.Height = 100;
this.inputCircleRadius = 10;
@ -91,6 +200,40 @@ class Element extends CanvasTools {
this.X = 0;
this.Y = 0;
this.OutputConnections = new Array();
this.MouseOver = false;
this.MousePosition = {x: 0, y: 0};
this.Properties = new Array();
this.LogicEngine = logicengine;
let inputProperty = new ElementProperty("Inputs","int",{CBObject: this,CBFunction: "ChangeInputs"},2,Inputs);
this.Properties.push(inputProperty);
}
getProperty(property) {
for (let a = 0; a < this.Properties.length;a++) {
if (this.Properties[a].Name == property) return this.Properties[a];
}
return false;
}
removeProperty(property) {
for (let a = 0; a < this.Properties.length;a++) {
if (this.Properties[a].Name == property) {
this.Properties.splice(a,1);
return true;
}
}
return false;
}
totalInputs() {
return this.Inputs.length;
}
ChangeInputs(inputs) {
inputs = parseInt(inputs,10);
this.Inputs = new Array(inputs);
this.getProperty("Inputs").CurrentValue = inputs;
}
Delete() {
@ -99,13 +242,40 @@ class Element extends CanvasTools {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,false);
}
}
MouseClick() {
// Function for if mouse is clicked
MouseClick(mousePos) {
let mouseDistOutput = length2D(this.X+(this.Width-20),
this.Y+(this.Height/2),
this.MousePosition.x,
this.MousePosition.y);
if (this.LogicEngine.ActiveLink) {
// We need to see if an input is being clicked on to be linked to
let foundInput = false;
for (let a = 0; a < this.Inputs.length;a++) {
let mouseDist = length2D(this.X+20,
this.Y+(this.inputCircleRadius + 2)+(((a*(4+(this.inputCircleRadius*2))))-2)+(this.inputCircleRadius/2),
this.MousePosition.x,
this.MousePosition.y);
if (mouseDist <= (this.inputCircleRadius)) {
this.LogicEngine.Link(a);
foundInput = true;
break;
}
}
} else {
if (mouseDistOutput <= (this.outputCircleRadius)) {
// Clicked on output, let us start a link
this.LogicEngine.Link();
}
}
}
mouseInside(mousePos) {
if (((mousePos.x >= this.X ) && (mousePos.x <= (this.X + this.Width))) & ((mousePos.y >= this.Y ) && (mousePos.y <= (this.Y + this.Height)))) return true;
return false;
this.MouseOver = false;
if (((mousePos.x >= this.X ) && (mousePos.x <= (this.X + this.Width))) & ((mousePos.y >= this.Y ) && (mousePos.y <= (this.Y + this.Height)))) this.MouseOver = true;
this.MousePosition = mousePos;
return this.MouseOver;
}
addConnection(container, element, input) {
@ -114,19 +284,23 @@ class Element extends CanvasTools {
element.setInput(input,this.getOutput());
}
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00") {
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover = "#00ffff") {
let old_strokeStyle = ctx.strokeStyle;
let old_fillStyle = ctx.fillStyle;
if ((this.totalInputs * ((this.inputCircleRadius*2)+4)) > (this.Height-2)) {
this.inputCircleRadius = ((this.Height-(2 + this.totalInputs * 4)) / this.totalInputs)/2;
if ((this.totalInputs() * ((this.inputCircleRadius*2)+4)) > (this.Height-2)) {
this.inputCircleRadius = ((this.Height-(2 + this.totalInputs() * 4)) / this.totalInputs())/2;
} else {
this.inputCircleRadius = 10;
}
for (let a = 0; a < this.totalInputs;a++) {
for (let a = 0; a < this.totalInputs();a++) {
let mouseDist = length2D(x+20,y+(this.inputCircleRadius + 2)+(((a*(4+(this.inputCircleRadius*2))))-2)+(this.inputCircleRadius/2),this.MousePosition.x,this.MousePosition.y);
ctx.beginPath();
ctx.arc(x+20,y+(this.inputCircleRadius + 2)+(((a*(4+(this.inputCircleRadius*2))))-2)+(this.inputCircleRadius/2),this.inputCircleRadius,0,2*Math.PI);
ctx.strokeStyle = borderColor;
ctx.fillStyle = circleColorFalse;
if (this.Inputs[a]) ctx.fillStyle = circleColorTrue;
if ((mouseDist <= (this.inputCircleRadius)) && this.LogicEngine.ActiveLink) ctx.fillStyle = circleColorHover;
ctx.fill();
ctx.stroke();
}
@ -134,21 +308,23 @@ class Element extends CanvasTools {
ctx.fillStyle = old_fillStyle;
}
drawOutputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00") {
drawOutputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover="#00ffff") {
let old_strokeStyle = ctx.strokeStyle;
let old_fillStyle = ctx.fillStyle;
let mouseDist = length2D(x+(this.Width-20),y+(this.Height/2),this.MousePosition.x,this.MousePosition.y);
ctx.beginPath();
ctx.arc(x+(this.Width-20),y+(this.Height/2),this.outputCircleRadius,0,2*Math.PI);
ctx.strokeStyle = borderColor;
ctx.fillStyle = circleColorFalse;
if (this.getOutput()) ctx.fillStyle = circleColorTrue;
if ((mouseDist <= (this.outputCircleRadius)) && !this.LogicEngine.ActiveLink) ctx.fillStyle = circleColorHover;
ctx.fill();
ctx.stroke();
ctx.strokeStyle = old_strokeStyle;
ctx.fillStyle = old_fillStyle;
}
drawConnections(ctx) {
drawConnections(ctx,settings) {
ctx.save();
for (let a = 0; a < this.OutputConnections.length;a++) {
if (!this.OutputConnections[a].Container.HasElement(this.OutputConnections[a].Element)) {
@ -157,9 +333,12 @@ class Element extends CanvasTools {
a--;
} else {
ctx.beginPath();
ctx.lineWidth = settings.LinkWidth;
ctx.setLineDash(settings.LinkDash);
ctx.moveTo((this.X + this.Width) - 20, this.Y + (this.Height / 2));
ctx.lineTo(this.OutputConnections[a].Element.X + 20, this.OutputConnections[a].Element.Y + 20);
ctx.strokeStyle = "#555";
ctx.strokeStyle = settings.ActiveConnectionColor;
if (!this.getOutput()) ctx.strokeStyle = settings.InactiveConnectionColor;
ctx.stroke();
}
}
@ -173,7 +352,7 @@ class Element extends CanvasTools {
} else {
Value = false;
}
if (Input < this.totalInputs) {
if (Input < this.totalInputs()) {
this.Inputs[Input] = Value;
}
if (this.getOutput() != oldOutput) {
@ -203,12 +382,78 @@ class Element extends CanvasTools {
}
class inputElement extends Element {
constructor() {
super(0);
class ClockElement extends Element {
ClockTick() {
if (this.Inputs[0]) {
this.Output = ~this.Output;
if (this.Output) {
this.Task.Time = Math.round(this.Period * this.Duty);
} else {
this.Task.Time = this.Period - Math.round(this.Period * this.Duty);
}
for (let a = 0; a < this.OutputConnections.length; a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput());
}
}
}
getOutput() {
return this.Output;
}
setInput(Input, Value) {
super.setInput(Input, Value);
if (!this.Inputs[0]) {
this.Output = false;
for (let a = 0; a < this.OutputConnections.length;a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
}
}
}
constructor(logicengine) {
super(logicengine,1);
this.removeProperty("Inputs");
this.Name = "Clock";
this.Period = 1000;
this.Duty = 0.5;
this.Output = false;
this.Width = 100;
this.Task = new Task("ClockTask","CLOCK",0,Math.round(this.Period * this.Duty),this.ClockTick.bind(this));
this.setInput(0,true);
this.removeProperty("Inputs");
let periodProperty = new ElementProperty("Period","int",{CBObject: this,CBFunction: "setPeriod"},1000,false,false,4,999999);
let dutyProperty = new ElementProperty("Duty","int",{CBObject: this,CBFunction: "setDuty"},50,false,false,0,100);
this.Properties.push(periodProperty);
this.Properties.push(dutyProperty);
}
setPeriod(period) {
this.Period = period;
this.Task.LastCall = 0;
this.getProperty("Period").CurrentValue = period;
}
setDuty(duty) {
this.Duty = duty/100;
this.Task.LastCall = 0;
this.getProperty("Duty").CurrentValue = duty;
}
drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,(this.Height+(this.Height/2)),this.Period + "ms " + (this.Duty * 100) + "%","10px Console");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class inputElement extends Element {
constructor(logicengine) {
super(logicengine,0);
this.Name = "InputElement";
this.Output = false;
this.Width = 100;
}
getOutput() {
@ -222,16 +467,19 @@ class inputElement extends Element {
}
}
class inputButton extends inputElement {
constructor() {
super();
this.Name = "Button";
class InputSwitch extends inputElement {
constructor(logicengine) {
super(logicengine);
this.Name = "Switch";
}
MouseClick() {
MouseClick(mousePos) {
super.MouseClick(mousePos);
if ((mousePos.x >= (this.X + 10)) && (mousePos.x <= (this.X + 60)) && (mousePos.y >= (this.Y + 25)) && (mousePos.y <= (this.Y + 75))) {
this.Output = ~this.Output;
for (let a = 0; a < this.OutputConnections.length;a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
for (let a = 0; a < this.OutputConnections.length; a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput());
}
}
}
@ -243,14 +491,14 @@ class inputButton extends inputElement {
}
class LogicAND extends Element {
constructor(Inputs) {
super(Inputs);
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "AND";
}
getOutput() {
let ANDResult = true;
for (let a = 0; a < this.totalInputs;a++) {
for (let a = 0; a < this.totalInputs();a++) {
if (!this.Inputs[a]) ANDResult = false;
}
return ANDResult;
@ -264,8 +512,8 @@ class LogicAND extends Element {
}
class LogicNAND extends LogicAND {
constructor(Inputs) {
super(Inputs);
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "NAND";
}
getOutput() {
@ -284,14 +532,14 @@ class LogicNAND extends LogicAND {
}
class LogicOR extends Element {
constructor(Inputs) {
super(Inputs);
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "OR";
}
getOutput() {
let ORResult = false;
for (let a = 0; a < this.totalInputs;a++) {
for (let a = 0; a < this.totalInputs();a++) {
if (this.Inputs[a]) ORResult = true;
}
return ORResult;
@ -308,8 +556,8 @@ class LogicOR extends Element {
}
class LogicNOR extends LogicOR {
constructor(Inputs) {
super(Inputs);
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "NOR";
}
getOutput() {
@ -328,8 +576,8 @@ class LogicNOR extends LogicOR {
}
class LogicXOR extends Element {
constructor() {
super(2); // Only 2 inputs on XOR
constructor(logicengine) {
super(logicengine,2); // Only 2 inputs on XOR
this.Name = "XOR";
}
@ -351,8 +599,8 @@ class LogicXOR extends Element {
}
class LogicXNOR extends Element {
constructor() {
super(2); // Only 2 inputs on XOR
constructor(logicengine) {
super(logicengine,2); // Only 2 inputs on XOR
this.Name = "XNOR";
}
@ -423,31 +671,51 @@ class elementContainer {
return false;
}
DrawAll(ctx) {
for (let a = 0;a < this.Elements.length;a++) {
DrawAll(ctx,settings) {
for (let a = 0; a < this.Elements.length; a++) {
// Not ideal to loop twice but we need the connections drawn first
this.Elements[a].drawConnections(ctx);
this.Elements[a].drawConnections(ctx, settings);
}
for (let a = 0;a < this.Elements.length;a++) {
if (this.Elements[a] == this.Selected) this.Elements[a].drawBorderBox(ctx,this.Elements[a].X - 2,this.Elements[a].Y - 2,this.Elements[a].Width+4,this.Elements[a].Height+4,2,"#5555FF","#5555ff");
this.Elements[a].drawElement(this.Elements[a].X,this.Elements[a].Y,ctx);
for (let a = 0; a < this.Elements.length; a++) {
if (this.Elements[a] == this.Selected) this.Elements[a].drawBorderBox(ctx, this.Elements[a].X - 2, this.Elements[a].Y - 2, this.Elements[a].Width + 4, this.Elements[a].Height + 4, 2, "#5555FF", "#5555ff");
this.Elements[a].drawElement(this.Elements[a].X, this.Elements[a].Y, ctx);
let old_font = ctx.font;
let old_fillStyle = ctx.fillStyle;
ctx.font = "10px Console";
let x = this.Elements[a].X;
let y = this.Elements[a].Y + (this.Elements[a].Height-12);
let y = this.Elements[a].Y + (this.Elements[a].Height - 12);
let x2 = this.Elements[a].Width;
let y2 = 10;
this.Elements[a].drawTextCentered(ctx,x,y,x2,y2,this.Elements[a].Designator,ctx.font,"#000");
this.Elements[a].drawTextCentered(ctx, x, y, x2, y2, this.Elements[a].Designator, ctx.font, "#000");
ctx.font = old_font;
ctx.fillStyle = old_fillStyle;
}
if (!this.Selected) {
let PropertiesBox = document.getElementById("PropertiesBox");
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
}
}
Select(element) {
this.Selected = element;
let PropertiesBox = document.getElementById("PropertiesBox");
let PropertiesBoxTitle = document.getElementById("PropertiesBoxTitle");
let PropertiesBoxContent = document.getElementById("PropertiesBoxContent");
PropertiesBoxTitle.innerText = this.Selected.Designator + " Properties";
let contentString = "<table id='propertiesTable'>";
for (let a = 0; a < this.Selected.Properties.length;a++) {
contentString += "<tr><td>" + this.Selected.Properties[a].Name + "</td><td>";
switch (this.Selected.Properties[a].Type) {
case "int":
contentString += "<input type='number' id='prop_" + this.Selected.Properties[a].Name + "' min='" + this.Selected.Properties[a].Minimium + "' max='" + this.Selected.Properties[a].Maximium + "' value='" + this.Selected.Properties[a].CurrentValue + "' onchange='logicEngine.PropertyChange(" + String.fromCharCode(34) + this.Selected.Properties[a].Name + String.fromCharCode(34) +");'>";
break;
}
contentString += "</td></tr>";
}
PropertiesBoxContent.innerHTML = contentString;
PropertiesBox.style.display = "block";
}
checkMouseBounds(mousePos) {
@ -463,11 +731,19 @@ class elementContainer {
class LogicEngine {
Resize(evt) {
this.Canvas.width = window.innerWidth;
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;
}
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.MouseDown = true;
@ -480,29 +756,28 @@ class LogicEngine {
this.MovingElementStartY = element.Y;
this.MovingElementMouseStartX = mousePos.x;
this.MovingElementMouseStartY = mousePos.y;
} else {
this.ActiveLink = false;
}
}
Mouse_Up(evt) {
let mousePos = getMousePos(this.Canvas, evt);
this.MouseDown = false;
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.ActiveContainer.Select(this.MovingElement);
if (this.ActiveLink) {
this.Link();
} else {
this.MovingElement.MouseClick();
}
this.MovingElement.MouseClick(mousePos);
}
//console.log("Mouse Up");
}
if (!this.MovingElement) this.ActiveContainer.Selected = false;
this.ActiveLink = false;
this.MovingElement = false;
}
Mouse_Move(evt) {
this.Canvas.focus();
let mousePos = getMousePos(this.Canvas, evt);
this.Mouse = mousePos;
if(this.MouseDown) {
@ -518,6 +793,8 @@ class LogicEngine {
this.MovingElement.Y = (this.MovingElementMouseStartY + yOffset) - diffyOffset;
}
}
} else {
this.ActiveContainer.checkMouseBounds(mousePos);
}
}
@ -541,6 +818,7 @@ class LogicEngine {
this.Canvas = canvas;
this.Ctx = canvas.getContext("2d");
this.Settings = new LogicEngineSettings;
this.FPSCounter = 0;
this.FPS = 0;
this.PotentialFPS = 0;
@ -557,18 +835,15 @@ class LogicEngine {
this.MovingElementMouseStartY = 0;
this.ActiveContainer = new elementContainer();
this.ActiveLink = false;
this.Scheduler = new ScheduleEngine();
this.Canvas.setAttribute('tabindex','0');
}
Link() {
Link(input = 0) {
if (this.ActiveLink) {
if (this.ActiveContainer.Selected && (this.ActiveContainer.Selected != this.ActiveLink)) {
let input = parseInt(prompt("Please enter the input number (0 - x)"));
while (input == NaN) {
input = parseInt(prompt("Please enter the input number (0 - x)"));
}
this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected,input);
this.ActiveLink = false;
} else {
@ -582,26 +857,25 @@ class LogicEngine {
}
DrawLoop() {
let startLoop = performance.now();
this.Canvas.focus();
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
if (this.ActiveLink) {
this.Ctx.save();
this.Ctx.strokeStyle = "#5555AA";
this.Ctx.lineWidth = 5;
this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor;
this.Ctx.lineWidth = this.Settings.LinkingWidth;
this.Ctx.setLineDash(this.Settings.LinkingDash);
this.Ctx.beginPath();
this.Ctx.moveTo(this.ActiveLink.X + (this.ActiveLink.Width/2), this.ActiveLink.Y + (this.ActiveLink.Height/2));
this.Ctx.lineTo(this.Mouse.x, this.Mouse.y);
this.Ctx.stroke();
this.Ctx.restore();
}
this.ActiveContainer.DrawAll(this.Ctx);
this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
let ct = new CanvasTools();
let FPSOffset = this.Canvas.width - 150;
ct.drawText(this.Ctx,FPSOffset,650,"FPS: " + this.FPS,"12px console", "#005500");
ct.drawText(this.Ctx,FPSOffset,670,"Potential FPS: " + this.PotentialFPS,"12px console", "#005500");
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++;

View File

@ -2,10 +2,17 @@
MatCat BrowserLogic Simulator
*/
let Version = "0.2.0";
let spanVersion = document.getElementById("version");
spanVersion.innerText = Version;
// get the canvas and get the engine object going
let lCanvasElement = document.getElementById("LogicPlane");
let logicEngine = new LogicEngine(lCanvasElement);
// Get the game Tick going, this will be 4ms for now which is the fastest that is supported
// by the HTML5 spec!
setInterval(logicEngine.Scheduler.Tick.bind(logicEngine.Scheduler), 4);
// Sadly this doesn't work well inside of the class so we will do it here real fast
window.addEventListener('resize', function(evt) {
logicEngine.Resize(evt);
@ -31,11 +38,6 @@ lCanvasElement.addEventListener('mousemove', function(evt) {
logicEngine.StartEngine();
// Setup interface buttons
let btn_Link = document.getElementById("btn_Link");
btn_Link.addEventListener('click', function(evt) {
logicEngine.Link();
}, false);
let btn_Delete = document.getElementById("btn_Delete");
btn_Delete.addEventListener('click', function(evt) {
logicEngine.Key_Press({key: "Delete"});
@ -43,7 +45,7 @@ btn_Delete.addEventListener('click', function(evt) {
let btn_AddAND = document.getElementById("btn_AddAND");
btn_AddAND.addEventListener('click', function(evt) {
let newAND = new LogicAND(2);
let newAND = new LogicAND(logicEngine,2);
newAND.X = 20;
newAND.Y = 20;
logicEngine.ActiveContainer.AddElement(newAND);
@ -51,7 +53,7 @@ btn_AddAND.addEventListener('click', function(evt) {
let btn_AddNAND = document.getElementById("btn_AddNAND");
btn_AddNAND.addEventListener('click', function(evt) {
let newNAND = new LogicNAND(2);
let newNAND = new LogicNAND(logicEngine,2);
newNAND.X = 20;
newNAND.Y = 20;
logicEngine.ActiveContainer.AddElement(newNAND);
@ -59,7 +61,7 @@ btn_AddNAND.addEventListener('click', function(evt) {
let btn_AddOR = document.getElementById("btn_AddOR");
btn_AddOR.addEventListener('click', function(evt) {
let newOR = new LogicOR(2);
let newOR = new LogicOR(logicEngine,2);
newOR.X = 20;
newOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newOR);
@ -67,7 +69,7 @@ btn_AddOR.addEventListener('click', function(evt) {
let btn_AddNOR = document.getElementById("btn_AddNOR");
btn_AddNOR.addEventListener('click', function(evt) {
let newNOR = new LogicNOR(2);
let newNOR = new LogicNOR(logicEngine,2);
newNOR.X = 20;
newNOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newNOR);
@ -75,7 +77,7 @@ btn_AddNOR.addEventListener('click', function(evt) {
let btn_AddXOR = document.getElementById("btn_AddXOR");
btn_AddXOR.addEventListener('click', function(evt) {
let newXOR = new LogicXOR();
let newXOR = new LogicXOR(logicEngine);
newXOR.X = 20;
newXOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newXOR);
@ -83,62 +85,26 @@ btn_AddXOR.addEventListener('click', function(evt) {
let btn_AddXNOR = document.getElementById("btn_AddXNOR");
btn_AddXNOR.addEventListener('click', function(evt) {
let newXNOR = new LogicXNOR();
let newXNOR = new LogicXNOR(logicEngine);
newXNOR.X = 20;
newXNOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newXNOR);
}, false);
let btn_AddBTN = document.getElementById("btn_AddBTN");
btn_AddBTN.addEventListener('click', function(evt) {
let newBTN = new inputButton();
newBTN.X = 20;
newBTN.Y = 20;
logicEngine.ActiveContainer.AddElement(newBTN);
let btn_AddSWITCH = document.getElementById("btn_AddSWITCH");
btn_AddSWITCH.addEventListener('click', function(evt) {
let newSWITCH = new InputSwitch(logicEngine);
newSWITCH.X = 20;
newSWITCH.Y = 20;
logicEngine.ActiveContainer.AddElement(newSWITCH);
}, false);
let btn_AddCLK = document.getElementById("btn_AddCLK");
btn_AddCLK.addEventListener('click', function(evt) {
let newCLK = new ClockElement(logicEngine);
newCLK.X = 20;
newCLK.Y = 20;
logicEngine.ActiveContainer.AddElement(newCLK);
logicEngine.Scheduler.addTask(newCLK.Task);
}, false);
/*
let AND1 = new LogicAND(2);
AND1.X = 430;
AND1.Y = 70;
logicEngine.ActiveContainer.AddElement(AND1);
let OR1 = new LogicOR(6);
OR1.X = 220;
OR1.Y = 20;
OR1.addConnection(logicEngine.ActiveContainer,AND1,0);
logicEngine.ActiveContainer.AddElement(OR1);
let NAND1 = new LogicNAND(2);
NAND1.X = 220;
NAND1.Y = 140;
NAND1.addConnection(logicEngine.ActiveContainer,AND1,1);
logicEngine.ActiveContainer.AddElement(NAND1);
let AND2 = new LogicAND(2);
AND2.X = 630;
AND2.Y = 120;
AND1.addConnection(logicEngine.ActiveContainer,AND2,0);
logicEngine.ActiveContainer.AddElement(AND2);
let NOR1 = new LogicNOR(2);
NOR1.X = 430;
NOR1.Y = 250;
NOR1.addConnection(logicEngine.ActiveContainer,AND2,1);
logicEngine.ActiveContainer.AddElement(NOR1);
let Button1 = new inputButton();
Button1.X = 20;
Button1.Y = 20;
Button1.addConnection(logicEngine.ActiveContainer,OR1,1);
logicEngine.ActiveContainer.AddElement(Button1);
let Button2 = new inputButton();
Button2.X = 20;
Button2.Y = 130;
Button2.addConnection(logicEngine.ActiveContainer,NAND1,0);
logicEngine.ActiveContainer.AddElement(Button2);
let Button3 = new inputButton();
Button3.X = 20;
Button3.Y = 240;
Button3.addConnection(logicEngine.ActiveContainer,NAND1,1);
logicEngine.ActiveContainer.AddElement(Button3);
*/