0.2.6: Background grid and logic elements now have SHAPES

This commit is contained in:
MatCat 2021-02-21 22:05:17 -08:00
parent 6f50294e8d
commit 779a54269f
5 changed files with 271 additions and 22 deletions

View File

@ -12,6 +12,11 @@ To be decided, but at this moment this code is open source and free to use for n
## Changelog ## Changelog
### 0.2.6
* Added background grid
* Logic elements now have proper logic shapes
### 0.2.5 ### 0.2.5
* Fixed clock sync issue when disabled * Fixed clock sync issue when disabled
* Added recursive detection on logic to prevent runaway oscillations * Added recursive detection on logic to prevent runaway oscillations

View File

@ -11,7 +11,7 @@
Base styles: opinionated defaults Base styles: opinionated defaults
========================================================================== */ ========================================================================== */
body { body {
background-color: #454550; background-color: #54545d;
} }
html { html {

View File

@ -42,6 +42,7 @@
<input type="button" id="btn_Delete" value="🗑 Delete"/> <input type="button" id="btn_Delete" value="🗑 Delete"/>
</div> </div>
</div> </div>
<canvas id="GridPlane" width="400" height="300" style="position: absolute; top: 50px; left 202px;"></canvas>
<canvas id="LogicPlane" width="400" height="300" style="margin: 0px; padding: 0px; position: absolute; top: 50px; left: 202px;"></canvas> <canvas id="LogicPlane" width="400" height="300" style="margin: 0px; padding: 0px; position: absolute; top: 50px; left: 202px;"></canvas>
<div id="PropertiesBox"> <div id="PropertiesBox">
<div id="PropertiesBoxTitle"> <div id="PropertiesBoxTitle">

View File

@ -32,6 +32,7 @@ class LogicEngineSettings {
this.LinkingConnectionColor = "#aabbbb"; this.LinkingConnectionColor = "#aabbbb";
this.LinkingWidth = "3"; this.LinkingWidth = "3";
this.LinkingDash = [2,2]; this.LinkingDash = [2,2];
this.ShadowColor = "#222";
} }
} }
class Task { class Task {
@ -112,13 +113,21 @@ class CanvasTools {
}; };
} }
drawBorderBox(ctx,x,y,drawWidth,drawHeight,borderWidth=1,borderColor="#000",fillColor="#f7e979") { drawBorderBox(ctx,x,y,drawWidth,drawHeight,borderWidth=1,borderColor="#000",fillColor="#f7e979",shadowColor = "transparent") {
let old_fillStyle = ctx.fillStyle; ctx.save();
ctx.beginPath();
ctx.fillStyle = borderColor; ctx.fillStyle = borderColor;
if (shadowColor != "transparent") {
ctx.shadowBlur = "6";
ctx.shadowColor = shadowColor;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
}
ctx.fillRect(x,y,drawWidth,drawHeight); ctx.fillRect(x,y,drawWidth,drawHeight);
ctx.fillStyle = fillColor; ctx.fillStyle = fillColor;
ctx.fillRect(x+borderWidth,y+borderWidth,drawWidth-(borderWidth*2),drawHeight-(borderWidth*2)); ctx.fillRect(x+borderWidth,y+borderWidth,drawWidth-(borderWidth*2),drawHeight-(borderWidth*2));
ctx.fillStyle = old_fillStyle; ctx.restore();
} }
drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555") { drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555") {
@ -488,8 +497,9 @@ class ClockElement extends Element {
} }
drawElement(x, y, ctx) { drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height); 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"); this.drawTextCentered(ctx,x,y+5,this.Width,12,this.Period + "ms " + (this.Duty * 100) + "%","10px Console");
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -534,8 +544,9 @@ class InputSwitch extends inputElement {
} }
drawElement(x, y, ctx) { drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x,y,this.Width-10,this.Height); this.drawBorderBox(ctx, x,y,this.Width-20,this.Height,1,"#000","#f7e979",this.LogicEngine.Settings.ShadowColor);
this.drawBorderBox(ctx,x+5,y+5,50,50,1,"#ccc","#777"); this.drawBorderBox(ctx,x+5,y+5,50,50,1,"#ccc","#777");
this.drawTextCentered(ctx,x,y+(this.Height-14),this.Width-(this.outputCircleRadius*2),12,this.Designator,"12px Console","#000");
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
} }
@ -554,8 +565,27 @@ class LogicAND extends Element {
return ANDResult; return ANDResult;
} }
drawElement(x,y,ctx) { drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height); //this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"|⊃"); let xOffset = 20;
let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.moveTo(x+xOffset,y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - xOffset),y,x+(this.Width-xOffset),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - xOffset),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+xOffset,y+this.Height);
ctx.lineTo(x+xOffset,y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -565,6 +595,7 @@ class LogicNAND extends LogicAND {
constructor(logicengine,Inputs) { constructor(logicengine,Inputs) {
super(logicengine,Inputs); super(logicengine,Inputs);
this.Name = "NAND"; this.Name = "NAND";
this.Width = this.Width + 10;
} }
getOutput() { getOutput() {
if (super.getOutput()) { if (super.getOutput()) {
@ -574,8 +605,36 @@ class LogicNAND extends LogicAND {
} }
} }
drawElement(x,y,ctx) { drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height); let xOffset = 20;
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"|⊃🞄"); let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.moveTo(x+xOffset,y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - (xOffset*1.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - (xOffset*1.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+xOffset,y+this.Height);
ctx.lineTo(x+xOffset,y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.strokeStyle = "#000000";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.lineWidth = "1";
ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI);
ctx.stroke();
ctx.fill();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width-xOffset,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -597,9 +656,29 @@ class LogicOR extends Element {
drawElement(x,y,ctx) { drawElement(x,y,ctx) {
let drawWidth = this.Width; let drawWidth = this.Width;
let drawHeight = this.Height; let drawHeight = this.Height;
let xOffset = 20;
let shadowColor = this.LogicEngine.Settings.ShadowColor;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight); ctx.save();
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,")⊃"); ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y,x+(this.Width-xOffset),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -609,6 +688,7 @@ class LogicNOR extends LogicOR {
constructor(logicengine,Inputs) { constructor(logicengine,Inputs) {
super(logicengine,Inputs); super(logicengine,Inputs);
this.Name = "NOR"; this.Name = "NOR";
this.Width = this.Width + 10;
} }
getOutput() { getOutput() {
if (super.getOutput()) { if (super.getOutput()) {
@ -618,8 +698,38 @@ class LogicNOR extends LogicOR {
} }
} }
drawElement(x,y,ctx) { drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height); let xOffset = 20;
this.drawTextCentered(ctx,x,y,this.Width,this.Height,")⊃🞄"); let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.lineWidth = "1";
ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI);
ctx.stroke();
ctx.fill();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width-xOffset,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -642,8 +752,43 @@ class LogicXOR extends Element {
let drawWidth = this.Width; let drawWidth = this.Width;
let drawHeight = this.Height; let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight); let xOffset = 20;
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃"); let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y,x+(this.Width-xOffset),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.lineWidth = "2";
ctx.beginPath();
ctx.shadowColor = "transparent";
ctx.moveTo(x+(xOffset/4)+10,y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height - (this.Height/32)),x+xOffset+10,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height/32),x+(xOffset/4)+10,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.stroke();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -654,6 +799,7 @@ class LogicXNOR extends Element {
super(logicengine,2); // Only 2 inputs on XOR super(logicengine,2); // Only 2 inputs on XOR
this.Name = "XNOR"; this.Name = "XNOR";
this.removeProperty("Inputs"); this.removeProperty("Inputs");
this.Width += 10;
} }
getOutput() { getOutput() {
@ -666,8 +812,53 @@ class LogicXNOR extends Element {
let drawWidth = this.Width; let drawWidth = this.Width;
let drawHeight = this.Height; let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight); let xOffset = 20;
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃🞄"); let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.save();
ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y);
ctx.lineTo((x+xOffset)+ this.Width/4,y);
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y,x+(this.Width-(xOffset*1.5)),y+(this.Height/2));
ctx.quadraticCurveTo(x+(this.Width - (xOffset*2.5)),y+this.Height,(x+xOffset)+ this.Width/4,y+this.Height);
ctx.lineTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.lineWidth = "1";
ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI);
ctx.stroke();
ctx.fill();
ctx.lineWidth = "2";
ctx.beginPath();
ctx.shadowColor = "transparent";
ctx.moveTo(x+(xOffset/4)+10,y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height - (this.Height/32)),x+xOffset+10,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+10),y+(this.Height/32),x+(xOffset/4)+10,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x+(xOffset/4),y+this.Height);
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height - (this.Height/32)),x+xOffset+5,y+(this.Height/2));
ctx.quadraticCurveTo(x+(xOffset+5),y+(this.Height/32),x+(xOffset/4),y);
ctx.stroke();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width-(xOffset/2),this.Height,this.Designator,"10px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -678,6 +869,7 @@ class LogicNOT extends Element {
super(logicengine,1); // Only 1 inputs on NOT super(logicengine,1); // Only 1 inputs on NOT
this.Name = "NOT"; this.Name = "NOT";
this.removeProperty("Inputs"); this.removeProperty("Inputs");
this.Width += 10;
} }
getOutput() { getOutput() {
@ -689,8 +881,34 @@ class LogicNOT extends Element {
let drawWidth = this.Width; let drawWidth = this.Width;
let drawHeight = this.Height; let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight); let xOffset = 20;
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"|>🞄"); let shadowColor = this.LogicEngine.Settings.ShadowColor;
ctx.save();
ctx.beginPath();
ctx.moveTo(x+xOffset,y);
ctx.lineTo(x+(this.Width-(xOffset+10)),y+(this.Height/2));
ctx.lineTo(x+xOffset,y+this.Height);
ctx.lineTo(x+xOffset,y);
ctx.lineWidth = "3";
ctx.fillStyle = "#f7e979";
ctx.shadowColor = shadowColor;
ctx.shadowBlur = "6";
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.lineWidth = "1";
ctx.arc(x + (this.Width - 25),y + (this.Height/2),5,0,2*Math.PI);
ctx.stroke();
ctx.fill();
ctx.restore();
this.drawTextCentered(ctx,x,y,this.Width-(xOffset),this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y); this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y); this.drawOutputs(ctx,x,y);
} }
@ -757,7 +975,7 @@ class elementContainer {
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 x2 = this.Elements[a].Width;
let y2 = 10; 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.font = old_font;
ctx.fillStyle = old_fillStyle; ctx.fillStyle = old_fillStyle;
@ -812,6 +1030,30 @@ class LogicEngine {
this.Canvas.width = window.innerWidth - 205; this.Canvas.width = window.innerWidth - 205;
this.Canvas.height = window.innerHeight - 50; this.Canvas.height = window.innerHeight - 50;
this.Mouse = false; this.Mouse = false;
let gridPlane = document.getElementById("GridPlane");
gridPlane.width = this.Canvas.width;
gridPlane.height = this.Canvas.height;
let Ctx = gridPlane.getContext("2d");
Ctx.save();
let gridWidth = 20;
for (let x = gridWidth;x < (this.Canvas.width); x+= gridWidth) {
Ctx.beginPath();
Ctx.moveTo(x,0);
Ctx.lineTo(x,this.Canvas.height);
Ctx.strokeStyle = "#777";
Ctx.lineWidth = "1";
Ctx.stroke();
}
for (let y = gridWidth;y < (this.Canvas.width); y+= gridWidth) {
Ctx.beginPath();
Ctx.moveTo(0,y);
Ctx.lineTo(this.Canvas.width,y);
Ctx.lineWidth = "1";
Ctx.strokeStyle = "#777";
Ctx.stroke();
}
Ctx.restore();
} }
PropertyChange(property) { PropertyChange(property) {
@ -940,6 +1182,7 @@ class LogicEngine {
} }
let startLoop = performance.now(); let startLoop = performance.now();
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height); this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
if (this.ActiveLink) { if (this.ActiveLink) {
this.Ctx.save(); this.Ctx.save();
this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor; this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor;

View File

@ -2,7 +2,7 @@
MatCat BrowserLogic Simulator MatCat BrowserLogic Simulator
*/ */
let Version = "0.2.5"; let Version = "0.2.6";
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