0.3.0: Loading and Saving, new buffer element, fixed bug on grid draw
This commit is contained in:
parent
86fb2873fb
commit
a50c655670
@ -12,6 +12,12 @@ To be decided, but at this moment this code is open source and free to use for n
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### 0.3.0
|
||||||
|
* Saving / Loading of designs
|
||||||
|
* New Element: Buffer, allows for construction of circuits that would otherwise be recursive
|
||||||
|
* Added pulse count to the delay block printout
|
||||||
|
* Fixed grid draw bug
|
||||||
|
|
||||||
### 0.2.12
|
### 0.2.12
|
||||||
* Fixed floating active link when deleting an element while linking
|
* Fixed floating active link when deleting an element while linking
|
||||||
* Fixed the delay element so that it properly buffers all input pulses
|
* Fixed the delay element so that it properly buffers all input pulses
|
||||||
|
10
index.html
10
index.html
@ -42,12 +42,16 @@
|
|||||||
<input type="button" id="btn_AddXOR" value="^ XOR"/><br />
|
<input type="button" id="btn_AddXOR" value="^ XOR"/><br />
|
||||||
<input type="button" id="btn_AddXNOR" value="!^ XNOR"/><br />
|
<input type="button" id="btn_AddXNOR" value="!^ XNOR"/><br />
|
||||||
<input type="button" id="btn_AddNOT" value="! NOT"/><br />
|
<input type="button" id="btn_AddNOT" value="! NOT"/><br />
|
||||||
|
<input type="button" id="btn_AddBUFFER" value="|> BUFFER"/><br />
|
||||||
<input type="button" id="btn_AddSWITCH" value="|- SWITCH"/><br />
|
<input type="button" id="btn_AddSWITCH" value="|- SWITCH"/><br />
|
||||||
<input type="button" id="btn_AddBTN" value="[o] BUTTON"/><br />
|
<input type="button" id="btn_AddBTN" value="[o] BUTTON"/><br />
|
||||||
<input type="button" id="btn_AddCLK" value="🕑 Clock"/><br />
|
<input type="button" id="btn_AddCLK" value="🕑 Clock"/><br />
|
||||||
<input type="button" id="btn_AddPULSE" value="|\__ Pulse"/><br />
|
<input type="button" id="btn_AddPULSE" value="|\__ Pulse"/><br />
|
||||||
<input type="button" id="btn_AddDELAY" value="__|\ Delay"/><br />
|
<input type="button" id="btn_AddDELAY" value="__|\ Delay"/><br />
|
||||||
<input type="button" id="btn_Delete" value="🗑 Delete"/>
|
<input type="button" id="btn_Delete" value="🗑 Delete"/><br /><br />
|
||||||
|
<input type="button" id="btn_Save" value="Save"/><br />
|
||||||
|
<input type="button" id="btn_Load" value="Load"/>
|
||||||
|
<input type="file" id="file_Load" style="display: none;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="GridPlane" width="400" height="300" style="position: absolute; top: 50px; left 202px;"></canvas>
|
<canvas id="GridPlane" width="400" height="300" style="position: absolute; top: 50px; left 202px;"></canvas>
|
||||||
@ -61,6 +65,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="darkout-overlay"></div>
|
<div id="darkout-overlay"></div>
|
||||||
|
<script src="js/globalfunctions.js"></script>
|
||||||
|
<script src="js/baseclasses.js"></script>
|
||||||
|
<script src="js/scheduler.js"></script>
|
||||||
|
<script src="js/elements.js"></script>
|
||||||
<script src="js/logicengine.js"></script>
|
<script src="js/logicengine.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
|
|
||||||
|
225
js/baseclasses.js
Normal file
225
js/baseclasses.js
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
class CanvasTools {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
textSize(ctx,text,fontStyle) {
|
||||||
|
ctx.save();
|
||||||
|
ctx.font = fontStyle;
|
||||||
|
let tHeight = Math.round(ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent);
|
||||||
|
let tWidth = Math.round(ctx.measureText(text).width);
|
||||||
|
ctx.restore();
|
||||||
|
return {
|
||||||
|
width: tWidth,
|
||||||
|
height: tHeight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555") {
|
||||||
|
let old_fillStyle = ctx.fillStyle;
|
||||||
|
let old_font = ctx.font;
|
||||||
|
ctx.font = fontStyle;
|
||||||
|
ctx.fillStyle = fontColor;
|
||||||
|
let tHeight = ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent;
|
||||||
|
let tX = x+((x2/2)-(ctx.measureText(text).width/2));
|
||||||
|
let tY = y+tHeight+((y2/2)-(tHeight/2));
|
||||||
|
ctx.fillText(text,tX,tY);
|
||||||
|
ctx.fillStyle = old_fillStyle;
|
||||||
|
ctx.font = old_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawText(ctx,x,y,text,fontStyle="24px Console",fontColor = "#555") {
|
||||||
|
let old_fillStyle = ctx.fillStyle;
|
||||||
|
let old_font = ctx.font;
|
||||||
|
ctx.font = fontStyle;
|
||||||
|
ctx.fillStyle = fontColor;
|
||||||
|
ctx.fillText(text,x,y);
|
||||||
|
ctx.fillStyle = old_fillStyle;
|
||||||
|
ctx.font = old_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class elementContainer {
|
||||||
|
constructor() {
|
||||||
|
this.Elements = new Array();
|
||||||
|
this.Selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(key) {
|
||||||
|
let elements = new Array();
|
||||||
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
elements.push(this.Elements[a].toJSON());
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(element) {
|
||||||
|
let designatorNumber = 1;
|
||||||
|
let designatorTest = element.Name + designatorNumber;
|
||||||
|
let unused = false;
|
||||||
|
|
||||||
|
while (!unused) {
|
||||||
|
let foundMatch = false;
|
||||||
|
for (let a=0;a < this.Elements.length;a++) {
|
||||||
|
if (this.Elements[a].Designator == designatorTest) foundMatch = true;
|
||||||
|
}
|
||||||
|
if (foundMatch) {
|
||||||
|
designatorNumber++;
|
||||||
|
designatorTest = element.Name + designatorNumber;
|
||||||
|
} else {
|
||||||
|
unused = true;
|
||||||
|
element.Designator = designatorTest;
|
||||||
|
this.Elements.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteElement(element) {
|
||||||
|
// Can pass object or Designator
|
||||||
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
if ((this.Elements[a] == element) || (this.Elements[a].Designator == element)) {
|
||||||
|
this.Elements[a].Delete();
|
||||||
|
this.Elements.splice(a,1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HasElement(element) {
|
||||||
|
// Can pass object or Designator
|
||||||
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
if ((this.Elements[a] == element) || (this.Elements[a].Designator == element)) {
|
||||||
|
return this.Elements[a];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawAll(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, 1, "rgba(100,200,255,0.25)", "rgba(100,200,255,0.25)");
|
||||||
|
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 x2 = this.Elements[a].Width;
|
||||||
|
let y2 = 10;
|
||||||
|
//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";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
// Not ideal to loop twice but we need the connections drawn all at once to prevent layer issues
|
||||||
|
this.Elements[a].drawConnections(ctx, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// We go backwards so that the newest (highest drawn) element is clicked before one lower.
|
||||||
|
for (let a = (this.Elements.length - 1); a >= 0; a--) {
|
||||||
|
if (this.Elements[a].mouseInside(mousePos)) return this.Elements[a];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkOverlayBounds(x,y,width,height) {
|
||||||
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
if ((x >= this.Elements[a].X) && (x <= (this.Elements[a].X + this.Elements[a].Width)) && (y >= this.Elements[a].Y) && (y <= (this.Elements[a].Y + this.Elements[a].Height))) return this.Elements[a];
|
||||||
|
if (((x + width) >= this.Elements[a].X) && ((x + width) <= (this.Elements[a].X + this.Elements[a].Width)) && (y >= this.Elements[a].Y) && (y <= (this.Elements[a].Y + this.Elements[a].Height))) return this.Elements[a];
|
||||||
|
if ((x >= this.Elements[a].X) && (x <= (this.Elements[a].X + this.Elements[a].Width)) && ((y + height) >= this.Elements[a].Y) && ((y + height) <= (this.Elements[a].Y + this.Elements[a].Height))) return this.Elements[a];
|
||||||
|
if (((x + width) >= this.Elements[a].X) && ((x + width) <= (this.Elements[a].X + this.Elements[a].Width)) && ((y + height) >= this.Elements[a].Y) && ((y + height) <= (this.Elements[a].Y + this.Elements[a].Height))) return this.Elements[a];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementCatalog_Category {
|
||||||
|
constructor(name,icon) {
|
||||||
|
this.Name = name;
|
||||||
|
this.Icon = icon;
|
||||||
|
this.Elements = new Array();
|
||||||
|
}
|
||||||
|
addElement(element) {
|
||||||
|
if (element instanceof ElementCatalog_Element) {
|
||||||
|
this.Elements.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementCatalog_Element {
|
||||||
|
constructor(name,description,icon,classref,args) {
|
||||||
|
this.Name = name;
|
||||||
|
this.Description = description;
|
||||||
|
this.Icon = icon;
|
||||||
|
this.Class = classref;
|
||||||
|
this.Args = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementCatalog {
|
||||||
|
constructor(categories = new Array()) {
|
||||||
|
this.Categories = categories;
|
||||||
|
for (let a = 0; a < this.Categories.length; a++) {
|
||||||
|
if (!this.Categories[a] instanceof ElementCatalog_Category) {
|
||||||
|
this.Categories.splice(a,1);
|
||||||
|
a--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addCategory(category) {
|
||||||
|
if (category instanceof ElementCatalog_Category) {
|
||||||
|
this.Categories.push(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1291
js/elements.js
Normal file
1291
js/elements.js
Normal file
File diff suppressed because it is too large
Load Diff
163
js/globalfunctions.js
Normal file
163
js/globalfunctions.js
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
function addElement(RestoreData = null,refClass,props) {
|
||||||
|
let newElement = new refClass(RestoreData,logicEngine,...props);
|
||||||
|
|
||||||
|
if (!RestoreData) {
|
||||||
|
let x = Math.round(logicEngine.Canvas.width / 2);
|
||||||
|
let y = Math.round(logicEngine.Canvas.height / 2);
|
||||||
|
let width = newElement.Width;
|
||||||
|
let height = newElement.Height;
|
||||||
|
|
||||||
|
let noclearspot = true;
|
||||||
|
while (noclearspot) {
|
||||||
|
if (!logicEngine.ActiveContainer.checkOverlayBounds(x, y, width, height)) {
|
||||||
|
noclearspot = false;
|
||||||
|
} else {
|
||||||
|
x += Math.floor(Math.random() * (width - (width - (width * 2)))) + (width - (width * 2));
|
||||||
|
y += Math.floor(Math.random() * (height - (height - (height * 2)))) + (height - (height * 2));
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
if (x + width > logicEngine.Canvas.width) x = logicEngine.Canvas.width - width;
|
||||||
|
if (y + height > logicEngine.Canvas.height) y = logicEngine.Canvas.height - height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newElement.X = x;
|
||||||
|
newElement.Y = y;
|
||||||
|
}
|
||||||
|
logicEngine.ActiveContainer.AddElement(newElement);
|
||||||
|
logicEngine.ActiveContainer.Select(newElement);
|
||||||
|
return newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCookie(cname, cvalue, exdays) {
|
||||||
|
let d = new Date();
|
||||||
|
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||||
|
let expires = "expires="+ d.toUTCString();
|
||||||
|
document.cookie = cname + '="' + cvalue + '";' + expires;
|
||||||
|
localStorage.setItem(cname,cvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(cname) {
|
||||||
|
let name = cname + "=";
|
||||||
|
let decodedCookie = decodeURIComponent(document.cookie);
|
||||||
|
let ca = decodedCookie.split(';');
|
||||||
|
for(var i = 0; i <ca.length; i++) {
|
||||||
|
var c = ca[i];
|
||||||
|
while (c.charAt(0) == ' ') {
|
||||||
|
c = c.substring(1);
|
||||||
|
}
|
||||||
|
if (c.indexOf(name) == 0) {
|
||||||
|
return c.substring(name.length, c.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return localStorage.getItem(cname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function CheckForWelcomeCookie() {
|
||||||
|
if (getCookie("hidewelcomescreen")) {
|
||||||
|
let WelcomeScreen = document.getElementById("WelcomeWindow");
|
||||||
|
let DarkOverlay = document.getElementById("darkout-overlay");
|
||||||
|
WelcomeScreen.style.display = "none";
|
||||||
|
DarkOverlay.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMousePos(canvas, evt) {
|
||||||
|
let rect = canvas.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: evt.clientX - rect.left,
|
||||||
|
y: evt.clientY - rect.top
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementInfo(element) {
|
||||||
|
for (let a = 0; a < ElementReferenceTable.length; a++) {
|
||||||
|
if (ElementReferenceTable[a].Name == element) return ElementReferenceTable[a];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVersionNewer(version1,version2,orEqual = true) {
|
||||||
|
let v1 = version1.split(".");
|
||||||
|
let v2 = version1.split(".");
|
||||||
|
if (v1.length != 3) return false;
|
||||||
|
if (v2.length != 3) return false;
|
||||||
|
for (let a = 0; a < 3; a++) {
|
||||||
|
v1[a] = parseInt(v1[a]);
|
||||||
|
v2[a] = parseInt(v2[a]);
|
||||||
|
}
|
||||||
|
if (v1[0] > v2[0]) return true;
|
||||||
|
if (v1[0] == v2[0] && v1[1] > v2[1]) return true;
|
||||||
|
if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] > v2[2]) return true;
|
||||||
|
if ((v1[0] == v2[0] && v1[1] == v2[1]) && (orEqual && v1[2] == v2[2])) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSaveState(container = false) {
|
||||||
|
let saveState = {
|
||||||
|
Name: "LogicDesign",
|
||||||
|
Version: Version,
|
||||||
|
Timestamp: Date.now(),
|
||||||
|
Elements: new Array()
|
||||||
|
};
|
||||||
|
if (container.Elements.length > 0) saveState.Elements = container.Elements;
|
||||||
|
return saveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(filename, savestate) {
|
||||||
|
let text = JSON.stringify(savestate);
|
||||||
|
let element = document.createElement('a');
|
||||||
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
|
||||||
|
element.setAttribute('download', filename);
|
||||||
|
|
||||||
|
element.style.display = 'none';
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadsave(savedata) {
|
||||||
|
if (!savedata) return false;
|
||||||
|
if (!savedata.Version) return false; // TODO: Let the person know invalid save file
|
||||||
|
if (!isVersionNewer(savedata.Version,"0.3.0")) return false; // TODO: Let the person know the version is too old
|
||||||
|
let newContainer = new elementContainer();
|
||||||
|
let elementConnections = new Array();
|
||||||
|
for (let a = 0; a < savedata.Elements.length; a++) {
|
||||||
|
let classRef = getElementInfo(savedata.Elements[a].Name).Class;
|
||||||
|
let newElement = new classRef(savedata.Elements[a],logicEngine,savedata.Elements[a].Args);
|
||||||
|
newContainer.AddElement(newElement);
|
||||||
|
newElement.Designator = savedata.Elements[a].Designator;
|
||||||
|
if (savedata.Elements[a].Outputs) {
|
||||||
|
if (savedata.Elements[a].Outputs.length > 0) {
|
||||||
|
for (let b=0; b < savedata.Elements[a].Outputs.length; b++) {
|
||||||
|
elementConnections.push({
|
||||||
|
FromElement: newElement,
|
||||||
|
Input: savedata.Elements[a].Outputs[b].Input,
|
||||||
|
ToElement: savedata.Elements[a].Outputs[b].Element
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now we need to make all of the connections
|
||||||
|
for (let a = 0; a < elementConnections.length; a++) {
|
||||||
|
let toElement = newContainer.HasElement(elementConnections[a].ToElement);
|
||||||
|
if (toElement) {
|
||||||
|
let newConnection = new ElementConnection(newContainer,toElement,elementConnections[a].Input);
|
||||||
|
elementConnections[a].FromElement.OutputConnections.push(newConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logicEngine.ActiveContainer = newContainer;
|
||||||
|
return true;
|
||||||
|
}
|
1325
js/logicengine.js
1325
js/logicengine.js
File diff suppressed because it is too large
Load Diff
67
js/main.js
67
js/main.js
@ -2,7 +2,7 @@
|
|||||||
MatCat BrowserLogic Simulator
|
MatCat BrowserLogic Simulator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let Version = "0.2.12";
|
let Version = "0.3.0";
|
||||||
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
|
||||||
@ -13,7 +13,6 @@ let logicEngine = new LogicEngine(lCanvasElement);
|
|||||||
// by the HTML5 spec!
|
// by the HTML5 spec!
|
||||||
setInterval(logicEngine.Scheduler.Tick.bind(logicEngine.Scheduler), 4);
|
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) {
|
window.addEventListener('resize', function(evt) {
|
||||||
logicEngine.Resize(evt);
|
logicEngine.Resize(evt);
|
||||||
}, false);
|
}, false);
|
||||||
@ -57,73 +56,95 @@ btn_Delete.addEventListener('click', function(evt) {
|
|||||||
|
|
||||||
let btn_AddAND = document.getElementById("btn_AddAND");
|
let btn_AddAND = document.getElementById("btn_AddAND");
|
||||||
btn_AddAND.addEventListener('click', function(evt) {
|
btn_AddAND.addEventListener('click', function(evt) {
|
||||||
addElement(LogicAND, [2]);
|
addElement(null,LogicAND, [2]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddNAND = document.getElementById("btn_AddNAND");
|
let btn_AddNAND = document.getElementById("btn_AddNAND");
|
||||||
btn_AddNAND.addEventListener('click', function(evt) {
|
btn_AddNAND.addEventListener('click', function(evt) {
|
||||||
addElement(LogicNAND, [2]);
|
addElement(null,LogicNAND, [2]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddOR = document.getElementById("btn_AddOR");
|
let btn_AddOR = document.getElementById("btn_AddOR");
|
||||||
btn_AddOR.addEventListener('click', function(evt) {
|
btn_AddOR.addEventListener('click', function(evt) {
|
||||||
addElement(LogicOR, [2]);
|
addElement(null,LogicOR, [2]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddNOR = document.getElementById("btn_AddNOR");
|
let btn_AddNOR = document.getElementById("btn_AddNOR");
|
||||||
btn_AddNOR.addEventListener('click', function(evt) {
|
btn_AddNOR.addEventListener('click', function(evt) {
|
||||||
addElement(LogicNOR, [2]);
|
addElement(null,LogicNOR, [2]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddXOR = document.getElementById("btn_AddXOR");
|
let btn_AddXOR = document.getElementById("btn_AddXOR");
|
||||||
btn_AddXOR.addEventListener('click', function(evt) {
|
btn_AddXOR.addEventListener('click', function(evt) {
|
||||||
addElement(LogicXOR,[]);
|
addElement(null,LogicXOR,[]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddXNOR = document.getElementById("btn_AddXNOR");
|
let btn_AddXNOR = document.getElementById("btn_AddXNOR");
|
||||||
btn_AddXNOR.addEventListener('click', function(evt) {
|
btn_AddXNOR.addEventListener('click', function(evt) {
|
||||||
addElement(LogicXNOR,[]);
|
addElement(null,LogicXNOR,[]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
let btn_AddNOT = document.getElementById("btn_AddNOT");
|
||||||
btn_AddNOT.addEventListener('click', function(evt) {
|
btn_AddNOT.addEventListener('click', function(evt) {
|
||||||
addElement(LogicNOT,[]);
|
addElement(null,LogicNOT,[]);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
let btn_AddBUFFER = document.getElementById("btn_AddBUFFER");
|
||||||
|
btn_AddBUFFER.addEventListener('click', function(evt) {
|
||||||
|
let logicBuffer = addElement(null,LogicBuffer,[]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddSWITCH = document.getElementById("btn_AddSWITCH");
|
let btn_AddSWITCH = document.getElementById("btn_AddSWITCH");
|
||||||
btn_AddSWITCH.addEventListener('click', function(evt) {
|
btn_AddSWITCH.addEventListener('click', function(evt) {
|
||||||
addElement(InputSwitch,[]);
|
addElement(null,InputSwitch,[]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddBTN = document.getElementById("btn_AddBTN");
|
let btn_AddBTN = document.getElementById("btn_AddBTN");
|
||||||
btn_AddBTN.addEventListener('click', function(evt) {
|
btn_AddBTN.addEventListener('click', function(evt) {
|
||||||
addElement(InputButton,[]);
|
addElement(null,InputButton,[]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddCLK = document.getElementById("btn_AddCLK");
|
let btn_AddCLK = document.getElementById("btn_AddCLK");
|
||||||
btn_AddCLK.addEventListener('click', function(evt) {
|
btn_AddCLK.addEventListener('click', function(evt) {
|
||||||
let clk = addElement(ClockElement,[]);
|
let clk = addElement(null,ClockElement,[]);
|
||||||
logicEngine.Scheduler.addTask(clk.Task);
|
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddPulse = document.getElementById("btn_AddPULSE");
|
let btn_AddPulse = document.getElementById("btn_AddPULSE");
|
||||||
btn_AddPulse.addEventListener('click', function(evt) {
|
btn_AddPulse.addEventListener('click', function(evt) {
|
||||||
let pulse = addElement(PulseElement,[]);
|
let pulse = addElement(null,PulseElement,[]);
|
||||||
logicEngine.Scheduler.addTask(pulse.Task);
|
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
let btn_AddDelay = document.getElementById("btn_AddDELAY");
|
let btn_AddDelay = document.getElementById("btn_AddDELAY");
|
||||||
btn_AddDelay.addEventListener('click', function(evt) {
|
btn_AddDelay.addEventListener('click', function(evt) {
|
||||||
let delay = addElement(DelayElement,[]);
|
let delay = addElement(null,DelayElement,[]);
|
||||||
logicEngine.Scheduler.addTask(delay.Task);
|
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
function CheckForWelcomeCookie() {
|
let btn_Save = document.getElementById("btn_Save");
|
||||||
if (getCookie("hidewelcomescreen")) {
|
btn_Save.addEventListener('click', function(evt) {
|
||||||
let WelcomeScreen = document.getElementById("WelcomeWindow");
|
download("mydeign.LogicParts",createSaveState(logicEngine.ActiveContainer));
|
||||||
let DarkOverlay = document.getElementById("darkout-overlay");
|
});
|
||||||
WelcomeScreen.style.display = "none";
|
|
||||||
DarkOverlay.style.display = "none";
|
let file_Load = document.getElementById("file_Load");
|
||||||
|
let btn_Load = document.getElementById("btn_Load");
|
||||||
|
btn_Load.addEventListener('click', function(evt) {
|
||||||
|
file_Load.click();
|
||||||
|
});
|
||||||
|
file_Load.addEventListener('change', function(evt) {
|
||||||
|
let fread = new FileReader();
|
||||||
|
fread.onload = (function (theFile) {
|
||||||
|
return function (e) {
|
||||||
|
try {
|
||||||
|
let restoredata = JSON.parse(e.target.result);
|
||||||
|
if (!loadsave(restoredata)) {
|
||||||
|
alert("Bad file!");
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
alert("Bad file!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})(evt.target.files[0]);
|
||||||
|
fread.readAsText(evt.target.files[0]);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
|
||||||
CheckForWelcomeCookie();
|
CheckForWelcomeCookie();
|
||||||
|
60
js/scheduler.js
Normal file
60
js/scheduler.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user