diff --git a/README.md b/README.md
index 280e324..b44211e 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,12 @@ To be decided, but at this moment this code is open source and free to use for n
## Changelog
+### 0.2.9
+* Active linking is now drawn with quadratic curves
+* Links can now be deleted by simply trying to link the same link again
+* Added pulse element
+* Clock element now shows countdown in ms to next state change
+
### 0.2.8
* New elements now spawn in the center
* Added button element
diff --git a/index.html b/index.html
index 33be2e5..38cbb20 100644
--- a/index.html
+++ b/index.html
@@ -45,6 +45,7 @@
+
diff --git a/js/logicengine.js b/js/logicengine.js
index 002be1e..a563343 100644
--- a/js/logicengine.js
+++ b/js/logicengine.js
@@ -24,7 +24,6 @@ function getCookie(cname) {
}
}
return localStorage.getItem(cname);
- return "";
}
function getMousePos(canvas, evt) {
@@ -330,6 +329,15 @@ class Element extends CanvasTools {
}
addConnection(container, element, input) {
+ for (let a = 0; a < this.OutputConnections.length; a++) {
+ if (this.OutputConnections[a].Element == element && this.OutputConnections[a].Input == input) {
+ // Already existing link, we will remove it instead
+ this.LogicEngine.RecursionCount = 0;
+ element.setInput(input,false);
+ this.OutputConnections.splice(a,1);
+ return;
+ }
+ }
let newConnection = new ElementConnection(container,element,input);
this.OutputConnections.push(newConnection);
this.LogicEngine.RecursionCount = 0;
@@ -534,12 +542,78 @@ class ClockElement extends Element {
drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height,1,"#000","#f7e979",this.LogicEngine.Settings.ShadowColor);
this.drawTextCentered(ctx,x,y+5,this.Width,12,this.Period + "ms " + (this.Duty * 100) + "%","10px Console");
+ if (this.Task.Enabled) this.drawTextCentered(ctx,x,y+this.Height-16,this.Width,12,(this.Task.Time - (Date.now() - this.Task.LastCall)) + "ms","10px Console");
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
+class PulseElement extends Element {
+ ClockTick() {
+ this.Output = false;
+ this.Task.Enabled = false;
+ this.Task.LastCall = Date.now();
+ for (let a = 0; a < this.OutputConnections.length; a++) {
+ this.LogicEngine.RecursionCount = 0;
+ this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput());
+ }
+ }
+
+ Delete() {
+ super.Delete();
+ this.LogicEngine.Scheduler.deleteTask(this.Task);
+ }
+
+ getOutput() {
+ return this.Output;
+ }
+
+ setInput(Input, Value) {
+ if (Input > 0) return;
+ //super.setInput(Input, Value);
+ this.Inputs[Input] = Value;
+ if (this.Inputs[0] && !this.Task.Enabled) {
+ this.Output = true;
+ for (let a = 0; a < this.OutputConnections.length;a++) {
+ this.LogicEngine.RecursionCount = 0;
+ this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
+ }
+ this.Task.LastCall = Date.now();
+ this.Task.Enabled = true;
+ }
+ }
+
+ constructor(logicengine) {
+ super(logicengine,1);
+ this.removeProperty("Inputs");
+ this.Name = "Pulse";
+ this.Period = 100;
+ this.Output = false;
+ this.Width = 100;
+ this.Task = new Task("PulseTask","CLOCK",0,this.Period,this.ClockTick.bind(this));
+ this.removeProperty("Inputs");
+ let periodProperty = new ElementProperty("Period","int",{CBObject: this,CBFunction: "setPeriod"},100,false,false,4,999999);
+ this.Properties.push(periodProperty);
+ }
+
+ setPeriod(period) {
+ this.Period = parseInt(period);
+ this.Task.Time = parseInt(period);
+ this.getProperty("Period").CurrentValue = parseInt(period);
+ }
+
+ drawElement(x, y, ctx) {
+ this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height,1,"#000","#f7e979",this.LogicEngine.Settings.ShadowColor);
+ this.drawTextCentered(ctx,x,y+5,this.Width,12,this.Period + "ms","10px Console");
+ if (this.Task.Enabled) this.drawTextCentered(ctx,x,y+this.Height-16,this.Width,12,(this.Task.Time - (Date.now() - this.Task.LastCall)) + "ms","10px Console");
+ this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
+ this.drawInputs(ctx,x,y);
+ this.drawOutputs(ctx,x,y);
+ }
+}
+
+
class inputElement extends Element {
constructor(logicengine) {
super(logicengine,0);
@@ -1267,18 +1341,30 @@ class LogicEngine {
let startLoop = performance.now();
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
+ this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
if (this.ActiveLink) {
+ let startX = this.ActiveLink.X + this.ActiveLink.Width;
+ let startY = this.ActiveLink.Y+(this.ActiveLink.Height/2);
+ let endX = this.Mouse.x;
+ let endY = this.Mouse.y;
+ let startMidX = startX + ((endX - startX)/2);
+ let startMidY = startY;
+ let midX = startMidX;
+ let midY = startY + ((endY - startY)/2);
+ let endMidX = startMidX;
+ let endMidY = endY;
+
this.Ctx.save();
this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor;
this.Ctx.lineWidth = this.Settings.LinkingWidth;
this.Ctx.setLineDash(this.Settings.LinkingDash);
this.Ctx.beginPath();
- this.Ctx.moveTo(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.moveTo(startX, startY);
+ this.Ctx.quadraticCurveTo(startMidX,startMidY,midX,midY);
+ this.Ctx.quadraticCurveTo(endMidX,endMidY,endX,endY);
this.Ctx.stroke();
this.Ctx.restore();
}
- 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", "#00ff00");
diff --git a/js/main.js b/js/main.js
index f330c14..78496b7 100644
--- a/js/main.js
+++ b/js/main.js
@@ -2,7 +2,7 @@
MatCat BrowserLogic Simulator
*/
-let Version = "0.2.8";
+let Version = "0.2.9";
let spanVersion = document.getElementById("version");
spanVersion.innerText = Version;
// get the canvas and get the engine object going
@@ -135,6 +135,15 @@ btn_AddCLK.addEventListener('click', function(evt) {
logicEngine.Scheduler.addTask(newCLK.Task);
}, false);
+let btn_AddPulse = document.getElementById("btn_AddPULSE");
+btn_AddPulse.addEventListener('click', function(evt) {
+ let newPulse = new PulseElement(logicEngine);
+ newPulse.X = logicEngine.Canvas.width/2;
+ newPulse.Y = logicEngine.Canvas.height/2;
+ logicEngine.ActiveContainer.AddElement(newPulse);
+ logicEngine.Scheduler.addTask(newPulse.Task);
+}, false);
+
function CheckForWelcomeCookie() {
if (getCookie("hidewelcomescreen")) {
let WelcomeScreen = document.getElementById("WelcomeWindow");