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
### 0.2.6
* Added background grid
* Logic elements now have proper logic shapes
### 0.2.5
* Fixed clock sync issue when disabled
* Added recursive detection on logic to prevent runaway oscillations

View File

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

View File

@ -42,6 +42,7 @@
<input type="button" id="btn_Delete" value="🗑 Delete"/>
</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>
<div id="PropertiesBox">
<div id="PropertiesBoxTitle">

View File

@ -32,6 +32,7 @@ class LogicEngineSettings {
this.LinkingConnectionColor = "#aabbbb";
this.LinkingWidth = "3";
this.LinkingDash = [2,2];
this.ShadowColor = "#222";
}
}
class Task {
@ -112,13 +113,21 @@ class CanvasTools {
};
}
drawBorderBox(ctx,x,y,drawWidth,drawHeight,borderWidth=1,borderColor="#000",fillColor="#f7e979") {
let old_fillStyle = ctx.fillStyle;
drawBorderBox(ctx,x,y,drawWidth,drawHeight,borderWidth=1,borderColor="#000",fillColor="#f7e979",shadowColor = "transparent") {
ctx.save();
ctx.beginPath();
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.fillStyle = fillColor;
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") {
@ -488,8 +497,9 @@ class ClockElement extends Element {
}
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,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
@ -534,8 +544,9 @@ class InputSwitch extends inputElement {
}
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.drawTextCentered(ctx,x,y+(this.Height-14),this.Width-(this.outputCircleRadius*2),12,this.Designator,"12px Console","#000");
this.drawOutputs(ctx,x,y);
}
}
@ -554,8 +565,27 @@ class LogicAND extends Element {
return ANDResult;
}
drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x+10,y,this.Width-20,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"|⊃");
//this.drawBorderBox(ctx, x+10,y,this.Width-20,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.drawOutputs(ctx,x,y);
}
@ -565,6 +595,7 @@ class LogicNAND extends LogicAND {
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "NAND";
this.Width = this.Width + 10;
}
getOutput() {
if (super.getOutput()) {
@ -574,8 +605,36 @@ class LogicNAND extends LogicAND {
}
}
drawElement(x,y,ctx) {
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*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.drawOutputs(ctx,x,y);
}
@ -597,9 +656,29 @@ class LogicOR extends Element {
drawElement(x,y,ctx) {
let drawWidth = this.Width;
let drawHeight = this.Height;
let xOffset = 20;
let shadowColor = this.LogicEngine.Settings.ShadowColor;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,")⊃");
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.restore();
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Designator,"12px Console","#000");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
@ -609,6 +688,7 @@ class LogicNOR extends LogicOR {
constructor(logicengine,Inputs) {
super(logicengine,Inputs);
this.Name = "NOR";
this.Width = this.Width + 10;
}
getOutput() {
if (super.getOutput()) {
@ -618,8 +698,38 @@ class LogicNOR extends LogicOR {
}
}
drawElement(x,y,ctx) {
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/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.drawOutputs(ctx,x,y);
}
@ -642,8 +752,43 @@ class LogicXOR extends Element {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃");
let xOffset = 20;
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.drawOutputs(ctx,x,y);
}
@ -654,6 +799,7 @@ class LogicXNOR extends Element {
super(logicengine,2); // Only 2 inputs on XOR
this.Name = "XNOR";
this.removeProperty("Inputs");
this.Width += 10;
}
getOutput() {
@ -666,8 +812,53 @@ class LogicXNOR extends Element {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃🞄");
let xOffset = 20;
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.drawOutputs(ctx,x,y);
}
@ -678,6 +869,7 @@ class LogicNOT extends Element {
super(logicengine,1); // Only 1 inputs on NOT
this.Name = "NOT";
this.removeProperty("Inputs");
this.Width += 10;
}
getOutput() {
@ -689,8 +881,34 @@ class LogicNOT extends Element {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x+10,y,drawWidth-20,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"|>🞄");
let xOffset = 20;
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.drawOutputs(ctx,x,y);
}
@ -757,7 +975,7 @@ class elementContainer {
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;
@ -812,6 +1030,30 @@ class LogicEngine {
this.Canvas.width = window.innerWidth - 205;
this.Canvas.height = window.innerHeight - 50;
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) {
@ -940,6 +1182,7 @@ class LogicEngine {
}
let startLoop = performance.now();
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
if (this.ActiveLink) {
this.Ctx.save();
this.Ctx.strokeStyle = this.Settings.LinkingConnectionColor;

View File

@ -2,7 +2,7 @@
MatCat BrowserLogic Simulator
*/
let Version = "0.2.5";
let Version = "0.2.6";
let spanVersion = document.getElementById("version");
spanVersion.innerText = Version;
// get the canvas and get the engine object going