0.3.2: IC Chips
This commit is contained in:
parent
6dc7eb5e03
commit
fce90becfc
@ -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.2
|
||||||
|
|
||||||
|
* Added IC Element, allows for converting a logic design to an IC for use in designs.
|
||||||
|
* Added IC Input and IC Output which allow for external connections when a design is used as an IC
|
||||||
|
* Added a New button for creating a new design
|
||||||
|
|
||||||
### 0.3.1
|
### 0.3.1
|
||||||
* Toolbox is now dynamically created and categorized
|
* Toolbox is now dynamically created and categorized
|
||||||
* The delete button is gone for now (use delete key on keyboard), it will come back when toolbar is added.
|
* The delete button is gone for now (use delete key on keyboard), it will come back when toolbar is added.
|
||||||
|
|||||||
16
css/main.css
16
css/main.css
@ -366,7 +366,7 @@ textarea {
|
|||||||
#WelcomeWindow label {
|
#WelcomeWindow label {
|
||||||
font-size: 0.5em;
|
font-size: 0.5em;
|
||||||
}
|
}
|
||||||
#PropertiesBox {
|
#PropertiesBox, #CreateICBox {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
@ -375,15 +375,25 @@ textarea {
|
|||||||
height: 200px;
|
height: 200px;
|
||||||
background-color: #444455;
|
background-color: #444455;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
#CreateICBox {
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
z-index: 9999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
#PropertiesBoxTitle {
|
#CreateICBox input[pattern]:invalid {
|
||||||
|
border: 3px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#PropertiesBoxTitle, #CreateICBoxTitle {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #222222;
|
background-color: #222222;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#PropertiesBoxContent {
|
#PropertiesBoxContent, #CreateICBoxContent {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
index.html
20
index.html
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html class="no-js" lang="">
|
<html class="no-js" lang="" style="height: 100%;">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<meta name="theme-color" content="#fafafa">
|
<meta name="theme-color" content="#fafafa">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body style="height: 100%;">
|
||||||
|
|
||||||
<div id="WelcomeWindow">
|
<div id="WelcomeWindow">
|
||||||
<h2>MatCat BrowserLogic Engine</h2>
|
<h2>MatCat BrowserLogic Engine</h2>
|
||||||
@ -32,9 +32,10 @@
|
|||||||
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
<div id="LeftOf-SiteTitle">
|
<div id="LeftOf-SiteTitle">
|
||||||
|
<input type="button" id="btn_New" value="New"/>
|
||||||
<input type="button" id="btn_Save" value="Save"/>
|
<input type="button" id="btn_Save" value="Save"/>
|
||||||
<input type="button" id="btn_Load" value="Load"/>
|
<input type="button" id="btn_Load" value="Load"/>
|
||||||
<input type="file" id="file_Load" style="display: none;" />
|
<input type="file" id="file_Load" accept=".LogicParts" style="display: none;" />
|
||||||
</div>
|
</div>
|
||||||
<div id ="SiteTitle">
|
<div id ="SiteTitle">
|
||||||
MatCat BrowserLogic <span id="version"> </span>
|
MatCat BrowserLogic <span id="version"> </span>
|
||||||
@ -44,6 +45,7 @@
|
|||||||
<div id="inner-left-menu">
|
<div id="inner-left-menu">
|
||||||
LOADING
|
LOADING
|
||||||
</div>
|
</div>
|
||||||
|
<input type="button" id="btn_CreateIC" value="Create IC" style="position: absolute; bottom: 30px; left: 50px;">
|
||||||
</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>
|
||||||
<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>
|
||||||
@ -55,6 +57,18 @@
|
|||||||
Content
|
Content
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="CreateICBox">
|
||||||
|
<div id="CreateICBoxTitle">
|
||||||
|
Create new IC
|
||||||
|
</div>
|
||||||
|
<div id="CreateICBoxContent">
|
||||||
|
<p>To create an IC you must give it a few parameters below:</p>
|
||||||
|
<div><span style="display: inline-block; text-align: right; vertical-align: middle; width: 100px; height: 100%; padding-right: 10px;">Name</span><input type="text" id="ICName" style="width: 250px" pattern="[a-zA-Z0-9_]+" title="Only letters, numbers, and underscore, no special characters or spaces! Spaces will be converted to _"></div>
|
||||||
|
<div><span style="display: inline-block; text-align: right; vertical-align: middle; width: 100px; height: 100%; padding-right: 10px;">Description</span><textarea id="ICDescription" style="width: 250px" rows="5"></textarea></div>
|
||||||
|
<center><input type="button" id="btn_CreateIC_Create" value="Create IC" disabled> <input type="button" id="btn_CreateIC_Cancel" value="Cancel"></center>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="darkout-overlay"></div>
|
<div id="darkout-overlay"></div>
|
||||||
<script src="js/globalfunctions.js"></script>
|
<script src="js/globalfunctions.js"></script>
|
||||||
<script src="js/baseclasses.js"></script>
|
<script src="js/baseclasses.js"></script>
|
||||||
|
|||||||
@ -57,12 +57,31 @@ class CanvasTools {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContainerConnection {
|
||||||
|
constructor(fromElementContainer,toElementContainer,fromElement,toElement,input) {
|
||||||
|
this.fromElementContainer = fromElementContainer;
|
||||||
|
this.toElementContainer = toElementContainer;
|
||||||
|
this.fromElement = fromElement;
|
||||||
|
this.toElement = toElement;
|
||||||
|
this.Input = input;
|
||||||
|
}
|
||||||
|
toJSON(key) {
|
||||||
|
return {
|
||||||
|
fromElement: (this.fromElement) ? this.fromElement.Designator : null,
|
||||||
|
toElement: (this.toElement) ? this.toElement.Designator : null,
|
||||||
|
Input: parseInt(this.Input)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class elementContainer {
|
class elementContainer {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.Elements = new Array();
|
this.Elements = new Array();
|
||||||
this.Selected = false;
|
this.Selected = false;
|
||||||
|
this.Inputs = new Array();
|
||||||
|
this.Outputs = new Array();
|
||||||
|
this.ICOutputs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(key) {
|
toJSON(key) {
|
||||||
@ -117,7 +136,9 @@ class elementContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DrawAll(ctx,settings) {
|
DrawAll(ctx,settings) {
|
||||||
|
let ICOuts = 0;
|
||||||
for (let a = 0; a < this.Elements.length; a++) {
|
for (let a = 0; a < this.Elements.length; a++) {
|
||||||
|
if (this.Elements[a] instanceof ICOutput) ICOuts++;
|
||||||
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)");
|
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);
|
this.Elements[a].drawElement(this.Elements[a].X, this.Elements[a].Y, ctx);
|
||||||
let old_font = ctx.font;
|
let old_font = ctx.font;
|
||||||
@ -132,6 +153,7 @@ class elementContainer {
|
|||||||
ctx.fillStyle = old_fillStyle;
|
ctx.fillStyle = old_fillStyle;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
this.ICOutputs = ICOuts;
|
||||||
if (!this.Selected) {
|
if (!this.Selected) {
|
||||||
let PropertiesBox = document.getElementById("PropertiesBox");
|
let PropertiesBox = document.getElementById("PropertiesBox");
|
||||||
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
|
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
|
||||||
@ -157,6 +179,9 @@ class elementContainer {
|
|||||||
case "int":
|
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) +");'>";
|
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;
|
break;
|
||||||
|
case "string":
|
||||||
|
contentString += '<input type="text" id="prop_' + this.Selected.Properties[a].Name + '" minlength="' + this.Selected.Properties[a].Minimium + '" maxlength="' + this.Selected.Properties[a].Maximium + '" value="' + this.Selected.Properties[a].CurrentValue + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected.Properties[a].Name + String.fromCharCode(39) + ');">';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
contentString += "</td></tr>";
|
contentString += "</td></tr>";
|
||||||
}
|
}
|
||||||
|
|||||||
388
js/elements.js
388
js/elements.js
@ -3,9 +3,11 @@ let ElementReferenceTable = new Array();
|
|||||||
let ElementCategory_Inputs = new ElementCatalog_Category("Inputs","");
|
let ElementCategory_Inputs = new ElementCatalog_Category("Inputs","");
|
||||||
let ElementCategory_LOGIC = new ElementCatalog_Category("Logic" ,"");
|
let ElementCategory_LOGIC = new ElementCatalog_Category("Logic" ,"");
|
||||||
let ElementCategory_Timing = new ElementCatalog_Category("Timing" ,"");
|
let ElementCategory_Timing = new ElementCatalog_Category("Timing" ,"");
|
||||||
|
let ElementCategory_ICs = new ElementCatalog_Category("ICs" ,"");
|
||||||
let elementCatalog = new ElementCatalog([ElementCategory_Inputs,
|
let elementCatalog = new ElementCatalog([ElementCategory_Inputs,
|
||||||
ElementCategory_LOGIC,
|
ElementCategory_LOGIC,
|
||||||
ElementCategory_Timing]);
|
ElementCategory_Timing,
|
||||||
|
ElementCategory_ICs]);
|
||||||
class ElementProperty {
|
class ElementProperty {
|
||||||
constructor(name,type,callback,defaultValue,currentValue = false,values=false,min=0,max=12) {
|
constructor(name,type,callback,defaultValue,currentValue = false,values=false,min=0,max=12) {
|
||||||
/*
|
/*
|
||||||
@ -51,15 +53,17 @@ class ElementProperty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ElementConnection {
|
class ElementConnection {
|
||||||
constructor(elementContainer,element,input) {
|
constructor(elementContainer,element,input,output = 0) {
|
||||||
this.Container = elementContainer;
|
this.Container = elementContainer;
|
||||||
this.Element = element;
|
this.Element = element;
|
||||||
this.Input = input;
|
this.Input = input;
|
||||||
|
this.Output = output;
|
||||||
}
|
}
|
||||||
toJSON(key) {
|
toJSON(key) {
|
||||||
return {
|
return {
|
||||||
Element: this.Element.Designator,
|
Element: this.Element.Designator,
|
||||||
Input: parseInt(this.Input)
|
Input: parseInt(this.Input),
|
||||||
|
Output: this.Output
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,6 +86,9 @@ class Element extends CanvasTools {
|
|||||||
this.MousePosition = {x: 0, y: 0};
|
this.MousePosition = {x: 0, y: 0};
|
||||||
this.Properties = new Array();
|
this.Properties = new Array();
|
||||||
this.LogicEngine = logicengine;
|
this.LogicEngine = logicengine;
|
||||||
|
this.Outputs = new Array(1);
|
||||||
|
this.NoOutput = false;
|
||||||
|
this.OutputLink = 0;
|
||||||
|
|
||||||
let inputProperty = new ElementProperty("Inputs","int",{CBObject: this,CBFunction: "ChangeInputs"},2,Inputs,false,2);
|
let inputProperty = new ElementProperty("Inputs","int",{CBObject: this,CBFunction: "ChangeInputs"},2,Inputs,false,2);
|
||||||
this.Properties.push(inputProperty);
|
this.Properties.push(inputProperty);
|
||||||
@ -92,7 +99,7 @@ class Element extends CanvasTools {
|
|||||||
this.X = RestoreData.X;
|
this.X = RestoreData.X;
|
||||||
this.Y = RestoreData.Y;
|
this.Y = RestoreData.Y;
|
||||||
if (RestoreData.Properties.length > 0) {
|
if (RestoreData.Properties.length > 0) {
|
||||||
if (this.Properties[0].Name == "Inputs") {
|
if (RestoreData.Properties[0].Name == "Inputs") {
|
||||||
this.ChangeInputs(RestoreData.Properties[0].CurrentValue);
|
this.ChangeInputs(RestoreData.Properties[0].CurrentValue);
|
||||||
this.Properties[0].DefaultValue = RestoreData.Properties[0].DefaultValue;
|
this.Properties[0].DefaultValue = RestoreData.Properties[0].DefaultValue;
|
||||||
this.Properties[0].CurrentValue = RestoreData.Properties[0].CurrentValue;
|
this.Properties[0].CurrentValue = RestoreData.Properties[0].CurrentValue;
|
||||||
@ -167,6 +174,10 @@ class Element extends CanvasTools {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkOutLocation() {
|
||||||
|
return this.OutputLink;
|
||||||
|
}
|
||||||
|
|
||||||
MouseClick(mousePos) {
|
MouseClick(mousePos) {
|
||||||
|
|
||||||
let mouseDistOutput = length2D(this.X+(this.Width-10),
|
let mouseDistOutput = length2D(this.X+(this.Width-10),
|
||||||
@ -193,9 +204,23 @@ class Element extends CanvasTools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (mouseDistOutput <= (this.outputCircleRadius)) {
|
let foundOutput = false;
|
||||||
// Clicked on output, let us start a link
|
for (let a = 0; a < this.Outputs.length;a++) {
|
||||||
this.LogicEngine.Link();
|
let centerY = this.Y + Math.round(this.Height / 2);
|
||||||
|
let totalHeight = this.Outputs.length * ((this.outputCircleRadius*2)+4);
|
||||||
|
let firstY = (centerY - (totalHeight/2)) + 12;
|
||||||
|
|
||||||
|
let mouseDist = length2D(this.X+(this.Width-10),
|
||||||
|
firstY+ (a*24),
|
||||||
|
this.MousePosition.x,
|
||||||
|
this.MousePosition.y);
|
||||||
|
console.log("Distance from " + a + ": " + mouseDist);
|
||||||
|
if (mouseDist <= (this.outputCircleRadius)) {
|
||||||
|
this.OutputLink = {Output: a,x: this.X+(this.Width-10), y: firstY+ (a*24)};
|
||||||
|
this.LogicEngine.Link();
|
||||||
|
foundOutput = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,20 +232,22 @@ class Element extends CanvasTools {
|
|||||||
return this.MouseOver;
|
return this.MouseOver;
|
||||||
}
|
}
|
||||||
|
|
||||||
addConnection(container, element, input) {
|
addConnection(container, element, input,output=0) {
|
||||||
for (let a = 0; a < this.OutputConnections.length; a++) {
|
for (let a = 0; a < this.OutputConnections.length; a++) {
|
||||||
if (this.OutputConnections[a].Element == element && this.OutputConnections[a].Input == input) {
|
if (this.OutputConnections[a].Element == element && this.OutputConnections[a].Input == input) {
|
||||||
// Already existing link, we will remove it instead
|
// Already existing link, we will remove it instead
|
||||||
|
console.log("Removing link");
|
||||||
this.LogicEngine.RecursionCount = 0;
|
this.LogicEngine.RecursionCount = 0;
|
||||||
element.setInput(input,false);
|
element.setInput(input,false);
|
||||||
this.OutputConnections.splice(a,1);
|
this.OutputConnections.splice(a,1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let newConnection = new ElementConnection(container,element,input);
|
let newConnection = new ElementConnection(container,element,input,output);
|
||||||
this.OutputConnections.push(newConnection);
|
this.OutputConnections.push(newConnection);
|
||||||
this.LogicEngine.RecursionCount = 0;
|
this.LogicEngine.RecursionCount = 0;
|
||||||
element.setInput(input,this.getOutput());
|
element.setInput(input,this.getOutput());
|
||||||
|
return newConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover = "#00ffff") {
|
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover = "#00ffff") {
|
||||||
@ -262,6 +289,10 @@ class Element extends CanvasTools {
|
|||||||
|
|
||||||
drawConnections(ctx,settings) {
|
drawConnections(ctx,settings) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
|
let centerY = this.Y + Math.round(this.Height / 2);
|
||||||
|
let totalHeight = this.Outputs.length * ((this.outputCircleRadius*2)+4);
|
||||||
|
let firstY = (centerY - (totalHeight/2)) + 12;
|
||||||
|
|
||||||
for (let a = 0; a < this.OutputConnections.length;a++) {
|
for (let a = 0; a < this.OutputConnections.length;a++) {
|
||||||
if (!this.OutputConnections[a].Container.HasElement(this.OutputConnections[a].Element)) {
|
if (!this.OutputConnections[a].Container.HasElement(this.OutputConnections[a].Element)) {
|
||||||
// This is a ghosted connection, lets get rid of it
|
// This is a ghosted connection, lets get rid of it
|
||||||
@ -273,7 +304,7 @@ class Element extends CanvasTools {
|
|||||||
let endFirstY = (endCenterY - (endTotalHeight/2)) + 12;
|
let endFirstY = (endCenterY - (endTotalHeight/2)) + 12;
|
||||||
|
|
||||||
let startX = this.X + this.Width;
|
let startX = this.X + this.Width;
|
||||||
let startY = this.Y+(this.Height/2);
|
let startY = firstY+ (this.OutputConnections[a].Output*24);
|
||||||
let endX = this.OutputConnections[a].Element.X;
|
let endX = this.OutputConnections[a].Element.X;
|
||||||
//let endY = this.OutputConnections[a].Element.Y+(this.OutputConnections[a].Element.inputCircleRadius + 2)+(((this.OutputConnections[a].Input*(4+(this.OutputConnections[a].Element.inputCircleRadius*2))))-2)+(this.OutputConnections[a].Element.inputCircleRadius/2);
|
//let endY = this.OutputConnections[a].Element.Y+(this.OutputConnections[a].Element.inputCircleRadius + 2)+(((this.OutputConnections[a].Input*(4+(this.OutputConnections[a].Element.inputCircleRadius*2))))-2)+(this.OutputConnections[a].Element.inputCircleRadius/2);
|
||||||
let endY = endFirstY + (this.OutputConnections[a].Input*24);
|
let endY = endFirstY + (this.OutputConnections[a].Input*24);
|
||||||
@ -292,7 +323,7 @@ class Element extends CanvasTools {
|
|||||||
ctx.quadraticCurveTo(startMidX,startMidY,midX,midY);
|
ctx.quadraticCurveTo(startMidX,startMidY,midX,midY);
|
||||||
ctx.quadraticCurveTo(endMidX,endMidY,endX,endY);
|
ctx.quadraticCurveTo(endMidX,endMidY,endX,endY);
|
||||||
ctx.strokeStyle = settings.ActiveConnectionColor;
|
ctx.strokeStyle = settings.ActiveConnectionColor;
|
||||||
if (!this.getOutput()) ctx.strokeStyle = settings.InactiveConnectionColor;
|
if (!this.getOutput(this.OutputConnections[a].Output)) ctx.strokeStyle = settings.InactiveConnectionColor;
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +361,7 @@ class Element extends CanvasTools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
/*
|
/*
|
||||||
Should return true or false
|
Should return true or false
|
||||||
*/
|
*/
|
||||||
@ -341,7 +372,7 @@ class Element extends CanvasTools {
|
|||||||
/*
|
/*
|
||||||
Draw routine for the element
|
Draw routine for the element
|
||||||
*/
|
*/
|
||||||
this.drawBorderBox(ctx,x+10,y,drawWidth-20,drawHeight);
|
this.drawBorderBox(ctx,x+10,y,this.Width-20,this.Height);
|
||||||
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"LOGIC");
|
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"LOGIC");
|
||||||
this.drawInputs(ctx,x,y);
|
this.drawInputs(ctx,x,y);
|
||||||
this.drawOutputs(ctx,x,y);
|
this.drawOutputs(ctx,x,y);
|
||||||
@ -349,6 +380,313 @@ class Element extends CanvasTools {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ICInput extends Element {
|
||||||
|
setPinName(pinname) {
|
||||||
|
// Dont actually need it to do anything
|
||||||
|
this.Properties[0].CurrentValue = pinname;
|
||||||
|
this.Output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(RestoreData = null,logicengine) {
|
||||||
|
super(RestoreData ,logicengine,0);
|
||||||
|
this.removeProperty("Inputs");
|
||||||
|
this.Task = new Task("ICInputTask","CLOCK",0,1,this.ClockTick.bind(this));
|
||||||
|
this.Name = "ICInput";
|
||||||
|
this.Input = false;
|
||||||
|
|
||||||
|
let pinNameProperty = new ElementProperty("Pin Name","string",{CBObject: this,CBFunction: "setPinName"},"Pin","Pin",false,1,32);
|
||||||
|
this.Properties.push(pinNameProperty);
|
||||||
|
this.LogicEngine.Scheduler.addTask(this.Task);
|
||||||
|
|
||||||
|
if (RestoreData) {
|
||||||
|
pinNameProperty.CurrentValue = RestoreData.Properties[0].CurrentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(key) {
|
||||||
|
let superjson = super.toJSON(key);
|
||||||
|
superjson.Task = {
|
||||||
|
Enabled: this.Task.Enabled,
|
||||||
|
Time: this.Task.Time,
|
||||||
|
LastCall: Date.now() - this.Task.LastCall,
|
||||||
|
CallCount: this.Task.CallCount
|
||||||
|
};
|
||||||
|
return superjson;
|
||||||
|
}
|
||||||
|
|
||||||
|
setInput(notused = 0,value) {
|
||||||
|
if (notused > 0) return;
|
||||||
|
if (!value) this.Input = false;
|
||||||
|
if (value) this.Input = true;
|
||||||
|
|
||||||
|
if (!this.Task.Enabled) {
|
||||||
|
this.Task.LastCall = 0;
|
||||||
|
this.Task.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClockTick() {
|
||||||
|
this.Output = this.Input;
|
||||||
|
this.Task.Enabled = false;
|
||||||
|
this.Task.LastCall = 0;
|
||||||
|
|
||||||
|
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(Output=0) {
|
||||||
|
return this.Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawElement(x,y,ctx) {
|
||||||
|
/*
|
||||||
|
Draw routine for the element
|
||||||
|
*/
|
||||||
|
this.drawBorderBox(ctx,x+10,y,this.Width-30,this.Height);
|
||||||
|
this.drawTextCentered(ctx,x,y+2,this.Width-10,14,this.Designator,"12px Console");
|
||||||
|
this.drawTextCentered(ctx,x,y,this.Width-10,this.Height,this.Properties[0].CurrentValue,"12px Console");
|
||||||
|
this.drawOutputs(ctx,x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
let ElementCatalog_ICInput = new ElementCatalog_Element("ICInput","Allows for external signal to be applied to the design when used as an IC.","-<|",ICInput,[]);
|
||||||
|
ElementReferenceTable.push(ElementCatalog_ICInput);
|
||||||
|
ElementCategory_ICs.addElement(ElementCatalog_ICInput);
|
||||||
|
|
||||||
|
class ICOutput extends Element {
|
||||||
|
setPinName(pinname) {
|
||||||
|
// Dont actually need it to do anything
|
||||||
|
this.Properties[0].CurrentValue = pinname;
|
||||||
|
this.Output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(RestoreData = null,logicengine) {
|
||||||
|
super(RestoreData ,logicengine,1);
|
||||||
|
this.removeProperty("Inputs");
|
||||||
|
this.Task = new Task("ICOutputTask","CLOCK",0,1,this.ClockTick.bind(this));
|
||||||
|
this.Name = "ICOutput";
|
||||||
|
this.Input = false;
|
||||||
|
this.NoOutput = true;
|
||||||
|
|
||||||
|
let pinNameProperty = new ElementProperty("Pin Name","string",{CBObject: this,CBFunction: "setPinName"},"Pin","Pin",false,1,32);
|
||||||
|
this.Properties.push(pinNameProperty);
|
||||||
|
this.LogicEngine.Scheduler.addTask(this.Task);
|
||||||
|
if (RestoreData) {
|
||||||
|
pinNameProperty.CurrentValue = RestoreData.Properties[0].CurrentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(key) {
|
||||||
|
let superjson = super.toJSON(key);
|
||||||
|
superjson.Task = {
|
||||||
|
Enabled: this.Task.Enabled,
|
||||||
|
Time: this.Task.Time,
|
||||||
|
LastCall: Date.now() - this.Task.LastCall,
|
||||||
|
CallCount: this.Task.CallCount
|
||||||
|
};
|
||||||
|
return superjson;
|
||||||
|
}
|
||||||
|
|
||||||
|
setInput(notused = 0,value) {
|
||||||
|
if (notused > 0) return;
|
||||||
|
if (!value) this.Input = false;
|
||||||
|
if (value) this.Input = true;
|
||||||
|
this.Inputs[0] = this.Input;
|
||||||
|
|
||||||
|
if (!this.Task.Enabled) {
|
||||||
|
console.log("Starting timer");
|
||||||
|
this.Task.LastCall = 0;
|
||||||
|
this.Task.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClockTick() {
|
||||||
|
this.Output = this.Input;
|
||||||
|
this.Task.Enabled = false;
|
||||||
|
this.Task.LastCall = 0;
|
||||||
|
//console.log(this);
|
||||||
|
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(Output=0) {
|
||||||
|
return this.Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawConnections(ctx, settings) {
|
||||||
|
// Don't draw connections from IC Outputs
|
||||||
|
}
|
||||||
|
|
||||||
|
drawElement(x,y,ctx) {
|
||||||
|
/*
|
||||||
|
Draw routine for the element
|
||||||
|
*/
|
||||||
|
this.drawBorderBox(ctx,x+20,y,this.Width-10,this.Height);
|
||||||
|
this.drawTextCentered(ctx,x+20,y+2,this.Width-10,14,this.Designator,"12px Console");
|
||||||
|
this.drawTextCentered(ctx,x+20,y,this.Width-10,this.Height,this.Properties[0].CurrentValue,"12px Console");
|
||||||
|
this.drawInputs(ctx,x,y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let ElementCatalog_ICOutput = new ElementCatalog_Element("ICOutput","Allows for routing a signal externally when the design is used as an IC.","|>-",ICOutput,[]);
|
||||||
|
ElementReferenceTable.push(ElementCatalog_ICOutput);
|
||||||
|
ElementCategory_ICs.addElement(ElementCatalog_ICOutput);
|
||||||
|
|
||||||
|
class ICElement extends Element {
|
||||||
|
constructor(RestoreData = null, logicengine,ICSettings = null) {
|
||||||
|
|
||||||
|
|
||||||
|
let newContainer = false;
|
||||||
|
let icContainer = false;
|
||||||
|
try {
|
||||||
|
newContainer = loadContainer(JSON.parse(JSON.parse(ICSettings.Container)));
|
||||||
|
icContainer = loadContainer(JSON.parse(JSON.parse(ICSettings.Container)));
|
||||||
|
} catch (ex) {
|
||||||
|
newContainer = loadContainer(JSON.parse(ICSettings.Container));
|
||||||
|
icContainer = loadContainer(JSON.parse(ICSettings.Container));
|
||||||
|
}
|
||||||
|
ICSettings.Inputs = new Array();
|
||||||
|
ICSettings.Outputs = new Array();
|
||||||
|
|
||||||
|
for (let a = 0; a < newContainer.Elements.length; a++) {
|
||||||
|
if (newContainer.Elements[a] instanceof ICInput) {
|
||||||
|
let cConn = new ContainerConnection(null,newContainer,null,newContainer.Elements[a],0);
|
||||||
|
ICSettings.Inputs.push(cConn);
|
||||||
|
}
|
||||||
|
if (newContainer.Elements[a] instanceof ICOutput) {
|
||||||
|
let cConn = new ContainerConnection(newContainer,null,newContainer.Elements[a],null,0);
|
||||||
|
ICSettings.Outputs.push(cConn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalInputs = ICSettings.Inputs.length;
|
||||||
|
let totalOutputs = ICSettings.Outputs.length;
|
||||||
|
|
||||||
|
super(RestoreData, logicengine, totalInputs);
|
||||||
|
this.removeProperty("Inputs");
|
||||||
|
this.ICBlueprint = icContainer;
|
||||||
|
this.Outputs = ICSettings.Outputs;
|
||||||
|
this.InputConnections = ICSettings.Inputs;
|
||||||
|
this.Container = newContainer;
|
||||||
|
this.Name = ICSettings.Name;
|
||||||
|
this.Icon = "≡[°]≡";
|
||||||
|
this.Width = 140;
|
||||||
|
this.Height = (totalInputs >= totalOutputs) ? totalInputs*25 : totalOutputs*25;
|
||||||
|
if (this.Height < 60) this.Height = 60;
|
||||||
|
|
||||||
|
if (RestoreData) {
|
||||||
|
//console.log(RestoreData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(key) {
|
||||||
|
let superjson = super.toJSON(key);
|
||||||
|
superjson.IsIC = true;
|
||||||
|
let eCat = getElementInfo(this.Name);
|
||||||
|
superjson.Description = eCat.Description;
|
||||||
|
superjson.ICOutputs = this.Outputs;
|
||||||
|
superjson.InputConnections = this.InputConnections;
|
||||||
|
superjson.ICBlueprint = this.ICBlueprint;
|
||||||
|
superjson.ICContainer = this.Container;
|
||||||
|
return superjson;
|
||||||
|
}
|
||||||
|
|
||||||
|
addConnection(container, element, input, output = 0) {
|
||||||
|
console.log("IC Add Connection " + element.Designator + " I:" + input + " O:"+output);
|
||||||
|
super.addConnection(container, element, input, output);
|
||||||
|
console.log(this.OutputConnections);
|
||||||
|
this.Outputs[output].toElementContainer = container;
|
||||||
|
this.Outputs[output].toElement = element;
|
||||||
|
this.Outputs[output].Input = input;
|
||||||
|
this.Outputs[output].fromElement.addConnection(container,element,input,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
setInput(Input, Value) {
|
||||||
|
if (this.InputConnections.length >= Input) {
|
||||||
|
// No need to worry about recursion as this goes to an input element which is buffered
|
||||||
|
this.Inputs[Input] = Value;
|
||||||
|
//console.log("Calling " + this.InputConnections[Input].toElement.Designator);
|
||||||
|
this.InputConnections[Input].toElement.setInput(this.InputConnections[Input].Input,Value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getOutput(Output = 0) {
|
||||||
|
if (this.Outputs.length >= Output) {
|
||||||
|
return this.Outputs[Output].fromElement.getOutput(this.Outputs[Output].Input);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawElement(x,y,ctx) {
|
||||||
|
/*
|
||||||
|
Draw routine for the element
|
||||||
|
*/
|
||||||
|
this.drawBorderBox(ctx,x+20,y,this.Width-40,this.Height);
|
||||||
|
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Icon,"12px Console");
|
||||||
|
this.drawTextCentered(ctx,x,(y+this.Height)-14,this.Width,14,this.Designator,"10px Console","#000");
|
||||||
|
this.drawInputs(ctx,x,y);
|
||||||
|
this.drawOutputs(ctx,x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover = "#00ffff") {
|
||||||
|
ctx.save();
|
||||||
|
let centerY = y + Math.round(this.Height / 2);
|
||||||
|
let totalHeight = this.totalInputs() * ((this.inputCircleRadius*2)+4);
|
||||||
|
let firstY = (centerY - (totalHeight/2)) + 12;
|
||||||
|
|
||||||
|
for (let a = 0; a < this.totalInputs();a++) {
|
||||||
|
let mouseDist = length2D(x+10, firstY + (a*24),this.MousePosition.x,this.MousePosition.y);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(x+10,firstY + (a*24),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();
|
||||||
|
this.drawText(ctx,x+(this.inputCircleRadius*2)+ 5,(firstY + (a*24)) + 5,this.InputConnections[a].toElement.Properties[0].CurrentValue,"10px Console","#000");
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
drawOutputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00",circleColorHover = "#00ffff") {
|
||||||
|
ctx.save();
|
||||||
|
let centerY = y + Math.round(this.Height / 2);
|
||||||
|
let totalHeight = this.Outputs.length * ((this.outputCircleRadius*2)+4);
|
||||||
|
let firstY = (centerY - (totalHeight/2)) + 12;
|
||||||
|
|
||||||
|
for (let a = 0; a < this.Outputs.length;a++) {
|
||||||
|
let mouseDist = length2D(x+(this.Width - 10), firstY + (a*24),this.MousePosition.x,this.MousePosition.y);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(x+(this.Width-10),firstY + (a*24),this.outputCircleRadius,0,2*Math.PI);
|
||||||
|
ctx.strokeStyle = borderColor;
|
||||||
|
ctx.fillStyle = circleColorFalse;
|
||||||
|
if (this.Outputs[a].fromElement.getOutput(0)) ctx.fillStyle = circleColorTrue;
|
||||||
|
if ((mouseDist <= (this.outputCircleRadius)) && !this.LogicEngine.ActiveLink) ctx.fillStyle = circleColorHover;
|
||||||
|
ctx.fill();
|
||||||
|
ctx.stroke();
|
||||||
|
let textSize = this.textSize(ctx,this.InputConnections[a].toElement.Properties[0].CurrentValue,"10px Console");
|
||||||
|
this.drawText(ctx,(x+(this.Width-10)) - (textSize.width + 5 + (this.outputCircleRadius*2)),(firstY + (a*24)) + 5,this.Outputs[a].fromElement.Properties[0].CurrentValue,"10px Console","#000");
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class ClockElement extends Element {
|
class ClockElement extends Element {
|
||||||
ClockTick() {
|
ClockTick() {
|
||||||
if (this.Inputs[0]) {
|
if (this.Inputs[0]) {
|
||||||
@ -370,7 +708,7 @@ class ClockElement extends Element {
|
|||||||
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
return this.Output;
|
return this.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +820,7 @@ class PulseElement extends Element {
|
|||||||
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
return this.Output;
|
return this.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +941,7 @@ class DelayElement extends Element {
|
|||||||
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
return this.Output;
|
return this.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,7 +1061,7 @@ class inputElement extends Element {
|
|||||||
this.removeProperty("Inputs");
|
this.removeProperty("Inputs");
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
return this.Output;
|
return this.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +1159,7 @@ class LogicAND extends Element {
|
|||||||
this.Name = "AND";
|
this.Name = "AND";
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
let ANDResult = true;
|
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;
|
if (!this.Inputs[a]) ANDResult = false;
|
||||||
@ -864,7 +1202,7 @@ class LogicNAND extends LogicAND {
|
|||||||
this.Name = "NAND";
|
this.Name = "NAND";
|
||||||
this.Width = this.Width + 10;
|
this.Width = this.Width + 10;
|
||||||
}
|
}
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
if (super.getOutput()) {
|
if (super.getOutput()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -916,7 +1254,7 @@ class LogicOR extends Element {
|
|||||||
this.Name = "OR";
|
this.Name = "OR";
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
let ORResult = false;
|
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;
|
if (this.Inputs[a]) ORResult = true;
|
||||||
@ -963,7 +1301,7 @@ class LogicNOR extends LogicOR {
|
|||||||
this.Name = "NOR";
|
this.Name = "NOR";
|
||||||
this.Width = this.Width + 10;
|
this.Width = this.Width + 10;
|
||||||
}
|
}
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
if (super.getOutput()) {
|
if (super.getOutput()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -1018,7 +1356,7 @@ class LogicXOR extends Element {
|
|||||||
this.removeProperty("Inputs");
|
this.removeProperty("Inputs");
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
let ORResult = false;
|
let ORResult = false;
|
||||||
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
|
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
|
||||||
return ORResult;
|
return ORResult;
|
||||||
@ -1081,7 +1419,7 @@ class LogicXNOR extends Element {
|
|||||||
this.Width += 10;
|
this.Width += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
let ORResult = false;
|
let ORResult = false;
|
||||||
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
|
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
|
||||||
return !ORResult;
|
return !ORResult;
|
||||||
@ -1155,7 +1493,7 @@ class LogicNOT extends Element {
|
|||||||
this.Width += 10;
|
this.Width += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
if (this.Inputs[0]) return false;
|
if (this.Inputs[0]) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1217,7 +1555,7 @@ class LogicBuffer extends Element {
|
|||||||
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutput() {
|
getOutput(Output=0) {
|
||||||
return this.Output;
|
return this.Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,32 @@ function addElement(RestoreData = null,refClass,props) {
|
|||||||
return newElement;
|
return newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createIC(container,name,description) {
|
||||||
|
let newContainer = false;
|
||||||
|
if (container instanceof elementContainer) newContainer = loadContainer(JSON.parse(JSON.stringify(container)));
|
||||||
|
if (typeof container == 'string' || container instanceof String) newContainer = loadContainer(JSON.parse(container));
|
||||||
|
if (!newContainer) return false;
|
||||||
|
|
||||||
|
let ICSettings = {
|
||||||
|
Name: name.replace('^[a-zA-Z0-9_]+$',''),
|
||||||
|
Description: description,
|
||||||
|
Container: JSON.stringify(container),
|
||||||
|
};
|
||||||
|
|
||||||
|
let outputCount = 0;
|
||||||
|
for (let a = 0; a < newContainer.Elements.length; a++) {
|
||||||
|
if (newContainer.Elements[a] instanceof ICOutput) {
|
||||||
|
outputCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outputCount == 0) return false;
|
||||||
|
let ElementCatalog_IC = new ElementCatalog_Element(ICSettings.Name,ICSettings.Description,"≡█≡",ICElement,[ICSettings]);
|
||||||
|
ElementReferenceTable.push(ElementCatalog_IC);
|
||||||
|
ElementCategory_ICs.addElement(ElementCatalog_IC);
|
||||||
|
BuildToolbox();
|
||||||
|
return ElementCatalog_IC;
|
||||||
|
}
|
||||||
|
|
||||||
function setCookie(cname, cvalue, exdays) {
|
function setCookie(cname, cvalue, exdays) {
|
||||||
let d = new Date();
|
let d = new Date();
|
||||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
||||||
@ -162,24 +188,47 @@ function download(filename, savestate) {
|
|||||||
document.body.removeChild(element);
|
document.body.removeChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadsave(savedata) {
|
function loadContainer(Elements) {
|
||||||
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 newContainer = new elementContainer();
|
||||||
let elementConnections = new Array();
|
let elementConnections = new Array();
|
||||||
for (let a = 0; a < savedata.Elements.length; a++) {
|
let icelementConnections = new Array();
|
||||||
let classRef = getElementInfo(savedata.Elements[a].Name).Class;
|
for (let a = 0; a < Elements.length; a++) {
|
||||||
let newElement = new classRef(savedata.Elements[a],logicEngine,savedata.Elements[a].Args);
|
if (Elements[a].IsIC) {
|
||||||
|
let classRef = getElementInfo(Elements[a].Name).Class;
|
||||||
|
if (!classRef) {
|
||||||
|
// We need to add this IC to the toolbox
|
||||||
|
let newIC = createIC(JSON.stringify(Elements[a].ICBlueprint),Elements[a].Name,Elements[a].Description);
|
||||||
|
console.log("NewIC:" + newIC);
|
||||||
|
if (!newIC) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let classRef = getElementInfo(Elements[a].Name).Class;
|
||||||
|
|
||||||
|
let newElement = new classRef(Elements[a],logicEngine,getElementInfo(Elements[a].Name).Args[0]);
|
||||||
|
|
||||||
newContainer.AddElement(newElement);
|
newContainer.AddElement(newElement);
|
||||||
newElement.Designator = savedata.Elements[a].Designator;
|
newElement.Designator = Elements[a].Designator;
|
||||||
if (savedata.Elements[a].Outputs) {
|
if (Elements[a].Outputs) {
|
||||||
if (savedata.Elements[a].Outputs.length > 0) {
|
if (Elements[a].Outputs.length > 0) {
|
||||||
for (let b=0; b < savedata.Elements[a].Outputs.length; b++) {
|
for (let b=0; b < Elements[a].Outputs.length; b++) {
|
||||||
elementConnections.push({
|
elementConnections.push({
|
||||||
FromElement: newElement,
|
FromElement: newElement,
|
||||||
Input: savedata.Elements[a].Outputs[b].Input,
|
Input: Elements[a].Outputs[b].Input,
|
||||||
ToElement: savedata.Elements[a].Outputs[b].Element
|
Output: Elements[a].Outputs[b].Output,
|
||||||
|
ToElement: Elements[a].Outputs[b].Element
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Elements[a].ICOutputs) {
|
||||||
|
if (Elements[a].ICOutputs.length > 0) {
|
||||||
|
for (let b=0; b < Elements[a].ICOutputs.length; b++) {
|
||||||
|
icelementConnections.push({
|
||||||
|
Element: newElement,
|
||||||
|
FromContainer: newElement.Container,
|
||||||
|
FromElement: Elements[a].ICOutputs[b].fromElement,
|
||||||
|
Input: Elements[a].ICOutputs[b].Input,
|
||||||
|
ToElement: Elements[a].ICOutputs[b].toElement
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,12 +236,56 @@ function loadsave(savedata) {
|
|||||||
}
|
}
|
||||||
// Now we need to make all of the connections
|
// Now we need to make all of the connections
|
||||||
for (let a = 0; a < elementConnections.length; a++) {
|
for (let a = 0; a < elementConnections.length; a++) {
|
||||||
|
if (elementConnections[a].FromElement.Name == "1B_ADD") {
|
||||||
|
console.log("Making connection " + a);
|
||||||
|
console.log(elementConnections[a]);
|
||||||
|
}
|
||||||
let toElement = newContainer.HasElement(elementConnections[a].ToElement);
|
let toElement = newContainer.HasElement(elementConnections[a].ToElement);
|
||||||
if (toElement) {
|
if (toElement) {
|
||||||
let newConnection = new ElementConnection(newContainer,toElement,elementConnections[a].Input);
|
if (elementConnections[a].FromContainer) {
|
||||||
elementConnections[a].FromElement.OutputConnections.push(newConnection);
|
let fromElement = elementConnections[a].FromContainer.HasElement(elementConnections[a].fromElement);
|
||||||
|
let newConnection = new ContainerConnection(elementConnections[a].FromContainer,newContainer,fromElement,toElement,elementConnections[a].Input);
|
||||||
|
elementConnections[a].Element.Outputs.push(newConnection);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
let newConnection = new ElementConnection(newContainer, toElement, elementConnections[a].Input, elementConnections[a].Output);
|
||||||
|
//elementConnections[a].FromElement.addConnection(newContainer,toElement,elementConnections[a].Input,elementConnections[a].Output)
|
||||||
|
if (newConnection) {
|
||||||
|
//elementConnections[a].FromElement.OutputConnections.push(newConnection);
|
||||||
|
elementConnections[a].FromElement.addConnection(newContainer,toElement,elementConnections[a].Input, elementConnections[a].Output)
|
||||||
|
if (elementConnections[a].FromElement.Name == "1B_ADD") {
|
||||||
|
console.log("Making Connection");
|
||||||
|
console.log(newConnection);
|
||||||
|
console.log(elementConnections[a].FromElement);
|
||||||
|
console.log(elementConnections[a].FromElement.OutputConnections);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("We dont have a new connection!!!");
|
||||||
|
console.log(toElement);
|
||||||
|
console.log(elementConnections[a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
for (let a = 0; a < icelementConnections.length; a++) {
|
||||||
|
let fromElement = icelementConnections[a].FromContainer.HasElement(icelementConnections[a].FromElement);
|
||||||
|
let toElement = newContainer.HasElement(icelementConnections[a].ToElement);
|
||||||
|
if (toElement) {
|
||||||
|
icelementConnections[a].Element.addConnection(newContainer, toElement, icelementConnections[a].Input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return newContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadsave(savedata) {
|
||||||
|
if (!savedata) return 0;
|
||||||
|
if (!savedata.Version) return -1; // TODO: Let the person know invalid save file
|
||||||
|
if (!isVersionNewer(savedata.Version,"0.3.0")) return -2; // TODO: Let the person know the version is too old
|
||||||
|
let newContainer = loadContainer(savedata.Elements);
|
||||||
|
if (!newContainer) return -3;
|
||||||
logicEngine.ActiveContainer = newContainer;
|
logicEngine.ActiveContainer = newContainer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -151,7 +151,7 @@ class LogicEngine {
|
|||||||
Link(input = 0) {
|
Link(input = 0) {
|
||||||
if (this.ActiveLink) {
|
if (this.ActiveLink) {
|
||||||
if (this.ActiveContainer.Selected && (this.ActiveContainer.Selected != this.ActiveLink)) {
|
if (this.ActiveContainer.Selected && (this.ActiveContainer.Selected != this.ActiveLink)) {
|
||||||
this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected,input);
|
this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected,input,this.ActiveLink.OutputLink.Output);
|
||||||
this.ActiveLink = false;
|
this.ActiveLink = false;
|
||||||
} else {
|
} else {
|
||||||
this.ActiveLink = false;
|
this.ActiveLink = false;
|
||||||
@ -173,9 +173,12 @@ class LogicEngine {
|
|||||||
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
|
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
|
||||||
|
|
||||||
this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
|
this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
|
||||||
|
let btn_CreateIC = document.getElementById("btn_CreateIC");
|
||||||
|
btn_CreateIC.disabled = true;
|
||||||
|
if (this.ActiveContainer.ICOutputs > 0) btn_CreateIC.disabled = false;
|
||||||
if (this.ActiveLink) {
|
if (this.ActiveLink) {
|
||||||
let startX = this.ActiveLink.X + this.ActiveLink.Width;
|
let startX = this.ActiveLink.LinkOutLocation().x;
|
||||||
let startY = this.ActiveLink.Y+(this.ActiveLink.Height/2);
|
let startY = this.ActiveLink.LinkOutLocation().y;
|
||||||
let endX = this.Mouse.x;
|
let endX = this.Mouse.x;
|
||||||
let endY = this.Mouse.y;
|
let endY = this.Mouse.y;
|
||||||
let startMidX = startX + ((endX - startX)/2);
|
let startMidX = startX + ((endX - startX)/2);
|
||||||
|
|||||||
58
js/main.js
58
js/main.js
@ -2,7 +2,7 @@
|
|||||||
MatCat BrowserLogic Simulator
|
MatCat BrowserLogic Simulator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let Version = "0.3.1";
|
let Version = "0.3.2";
|
||||||
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
|
||||||
@ -50,6 +50,45 @@ btn_CloseWelcome.addEventListener('click', function(evt) {
|
|||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
let btn_CreateIC = document.getElementById("btn_CreateIC");
|
||||||
|
btn_CreateIC.addEventListener('click', function(evt) {
|
||||||
|
let CreateICBox = document.getElementById("CreateICBox");
|
||||||
|
CreateICBox.style.display = "block";
|
||||||
|
});
|
||||||
|
|
||||||
|
let btn_CreateIC_Cancel = document.getElementById("btn_CreateIC_Cancel");
|
||||||
|
btn_CreateIC_Cancel.addEventListener('click', function(evt) {
|
||||||
|
let CreateICBox = document.getElementById("CreateICBox");
|
||||||
|
CreateICBox.style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
let btn_CreateIC_Create = document.getElementById("btn_CreateIC_Create");
|
||||||
|
btn_CreateIC_Create.addEventListener('click', function(evt) {
|
||||||
|
let CreateICBox = document.getElementById("CreateICBox");
|
||||||
|
let ICName = document.getElementById("ICName");
|
||||||
|
let ICDescription = document.getElementById("ICDescription");
|
||||||
|
createIC(logicEngine.ActiveContainer,ICName.value,ICDescription.value);
|
||||||
|
CreateICBox.style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
let ICName = document.getElementById("ICName");
|
||||||
|
let ICDescription = document.getElementById("ICDescription");
|
||||||
|
|
||||||
|
ICName.addEventListener('input', function(evt){
|
||||||
|
btn_CreateIC_Create.disabled = true;
|
||||||
|
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
ICDescription.addEventListener('input', function(evt){
|
||||||
|
btn_CreateIC_Create.disabled = true;
|
||||||
|
if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
let btn_New = document.getElementById("btn_New");
|
||||||
|
btn_New.addEventListener('click', function(evt) {
|
||||||
|
logicEngine.ActiveContainer = new elementContainer();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
let btn_Save = document.getElementById("btn_Save");
|
let btn_Save = document.getElementById("btn_Save");
|
||||||
btn_Save.addEventListener('click', function(evt) {
|
btn_Save.addEventListener('click', function(evt) {
|
||||||
@ -67,11 +106,24 @@ file_Load.addEventListener('change', function(evt) {
|
|||||||
return function (e) {
|
return function (e) {
|
||||||
try {
|
try {
|
||||||
let restoredata = JSON.parse(e.target.result);
|
let restoredata = JSON.parse(e.target.result);
|
||||||
if (!loadsave(restoredata)) {
|
console.log(restoredata);
|
||||||
alert("Bad file!");
|
loadresult = loadsave(restoredata);
|
||||||
|
if (!loadresult) {
|
||||||
|
switch(loadresult) {
|
||||||
|
case -1:
|
||||||
|
alert("Invalid LogicParts file!");
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
alert("The version of MatCat BrowserLogic cannot open this save version!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
alert("Bad save file!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
alert("Bad file!");
|
alert("Bad file!");
|
||||||
|
console.log(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})(evt.target.files[0]);
|
})(evt.target.files[0]);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user