diff --git a/README.md b/README.md
index 0bec4d9..d3565bb 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/css/main.css b/css/main.css
index 416a37e..b519912 100644
--- a/css/main.css
+++ b/css/main.css
@@ -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%;
+}
diff --git a/index.html b/index.html
index 2a83329..057b4fe 100644
--- a/index.html
+++ b/index.html
@@ -12,7 +12,6 @@
-
@@ -26,20 +25,31 @@
-
- MatCat BrowserLogic
0.1.0
-
-
-
-
-
-
-
-
-
+
+ MatCat BrowserLogic
+
+
+
+
+
+ Properties
+
+
+ Content
+
-
-
diff --git a/js/logicengine.js b/js/logicengine.js
index e05d257..67aae09 100644
--- a/js/logicengine.js
+++ b/js/logicengine.js
@@ -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() {
- this.Output = ~this.Output;
- for (let a = 0; a < this.OutputConnections.length;a++) {
- this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
+ 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());
+ }
}
}
@@ -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 = "
";
+ for (let a = 0; a < this.Selected.Properties.length;a++) {
+ contentString += "| " + this.Selected.Properties[a].Name + " | ";
+ switch (this.Selected.Properties[a].Type) {
+ case "int":
+ contentString += "";
+ break;
+ }
+ contentString += " |
";
+ }
+ 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++;
diff --git a/js/main.js b/js/main.js
index 24a721e..32b801d 100644
--- a/js/main.js
+++ b/js/main.js
@@ -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);
-*/