First commit

This commit is contained in:
MatCat 2021-02-19 13:47:37 -08:00
commit be4aa54aaf
20 changed files with 2986 additions and 0 deletions

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
# editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

194
.gitattributes vendored Normal file
View File

@ -0,0 +1,194 @@
## GITATTRIBUTES FOR WEB PROJECTS
#
# These settings are for any web project.
#
# Details per file setting:
# text These files should be normalized (i.e. convert CRLF to LF).
# binary These files are binary and should be left untouched.
#
# Note that binary is a macro for -text -diff.
######################################################################
## AUTO-DETECT
## Handle line endings automatically for files detected as
## text and leave all files detected as binary untouched.
## This will handle all files NOT defined below.
* text=auto
## SOURCE CODE
*.bat text eol=crlf
*.coffee text
*.css text
*.htm text
*.html text
*.inc text
*.ini text
*.js text
*.json text
*.jsx text
*.less text
*.od text
*.onlydata text
*.php text
*.pl text
*.py text
*.rb text
*.sass text
*.scm text
*.scss text
*.sh text eol=lf
*.sql text
*.styl text
*.tag text
*.ts text
*.tsx text
*.xml text
*.xhtml text
## DOCKER
*.dockerignore text
Dockerfile text
## DOCUMENTATION
*.markdown text
*.md text
*.mdwn text
*.mdown text
*.mkd text
*.mkdn text
*.mdtxt text
*.mdtext text
*.txt text
AUTHORS text
CHANGELOG text
CHANGES text
CONTRIBUTING text
COPYING text
copyright text
*COPYRIGHT* text
INSTALL text
license text
LICENSE text
NEWS text
readme text
*README* text
TODO text
## TEMPLATES
*.dot text
*.ejs text
*.haml text
*.handlebars text
*.hbs text
*.hbt text
*.jade text
*.latte text
*.mustache text
*.njk text
*.phtml text
*.tmpl text
*.tpl text
*.twig text
## LINTERS
.babelrc text
.csslintrc text
.eslintrc text
.htmlhintrc text
.jscsrc text
.jshintrc text
.jshintignore text
.prettierrc text
.stylelintrc text
## CONFIGS
*.bowerrc text
*.cnf text
*.conf text
*.config text
.browserslistrc text
.editorconfig text
.gitattributes text
.gitconfig text
.gitignore text
.htaccess text
*.npmignore text
*.yaml text
*.yml text
browserslist text
Makefile text
makefile text
## HEROKU
Procfile text
.slugignore text
## GRAPHICS
*.ai binary
*.bmp binary
*.eps binary
*.gif binary
*.ico binary
*.jng binary
*.jp2 binary
*.jpg binary
*.jpeg binary
*.jpx binary
*.jxr binary
*.pdf binary
*.png binary
*.psb binary
*.psd binary
*.svg text
*.svgz binary
*.tif binary
*.tiff binary
*.wbmp binary
*.webp binary
## AUDIO
*.kar binary
*.m4a binary
*.mid binary
*.midi binary
*.mp3 binary
*.ogg binary
*.ra binary
## VIDEO
*.3gpp binary
*.3gp binary
*.as binary
*.asf binary
*.asx binary
*.fla binary
*.flv binary
*.m4v binary
*.mng binary
*.mov binary
*.mp4 binary
*.mpeg binary
*.mpg binary
*.ogv binary
*.swc binary
*.swf binary
*.webm binary
## ARCHIVES
*.7z binary
*.gz binary
*.jar binary
*.rar binary
*.tar binary
*.zip binary
## FONTS
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
*.woff2 binary
## EXECUTABLES
*.exe binary
*.pyc binary

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Include your project-specific ignores in this file
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
# Useful .gitignore templates: https://github.com/github/gitignore
node_modules
dist
.cache
doc/
.idea/

1225
.htaccess Normal file

File diff suppressed because it is too large Load Diff

62
404.html Normal file
View File

@ -0,0 +1,62 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page Not Found</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
line-height: 1.2;
margin: 0;
}
html {
color: #888;
display: table;
font-family: sans-serif;
height: 100%;
text-align: center;
width: 100%;
}
body {
display: table-cell;
vertical-align: middle;
margin: 2em auto;
}
h1 {
color: #555;
font-size: 2em;
font-weight: 400;
}
p {
margin: 0 auto;
width: 280px;
}
@media only screen and (max-width: 280px) {
body,
p {
width: 95%;
}
h1 {
font-size: 1.5em;
margin: 0 0 0.3em;
}
}
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>Sorry, but the page you were trying to view does not exist.</p>
</body>
</html>
<!-- IE needs 512+ bytes: https://docs.microsoft.com/archive/blogs/ieinternals/friendly-http-error-pages -->

16
README.md Normal file
View File

@ -0,0 +1,16 @@
# MatCat BrowserLogic
MatCat BrowserLogic https://www.logic.parts/ is a logic simulator written purely in HTML5 / Javascript using 2D Canvas.
## Status
This simulator is in extremely early stages, it is not even Alpha at this point but early development. Outside contribution is welcome, please contact me in #LogicParts on Freenode IRC network.
## License
To be decided, but at this moment this code is open source and free to use for non-commercial uses.
## Changelog
### 0.1.0
Initial public release.

263
css/main.css Normal file
View File

@ -0,0 +1,263 @@
/*! HTML5 Boilerplate v8.0.0 | MIT License | https://html5boilerplate.com/ */
/* main.css 2.1.0 | MIT License | https://github.com/h5bp/main.css#readme */
/*
* What follows is the result of much research on cross-browser styling.
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
* Kroc Camen, and the H5BP dev community and team.
*/
/* ==========================================================================
Base styles: opinionated defaults
========================================================================== */
html {
color: #222;
font-size: 1em;
line-height: 1.4;
}
/*
* Remove text-shadow in selection highlight:
* https://twitter.com/miketaylr/status/12228805301
*
* Vendor-prefixed and regular ::selection selectors cannot be combined:
* https://stackoverflow.com/a/16982510/7133471
*
* Customize the background color to match your design.
*/
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
/*
* A better looking default horizontal rule
*/
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 1em 0;
padding: 0;
}
/*
* Remove the gap between audio, canvas, iframes,
* images, videos and the bottom of their containers:
* https://github.com/h5bp/html5-boilerplate/issues/440
*/
audio,
canvas,
iframe,
img,
svg,
video {
vertical-align: middle;
}
/*
* Remove default fieldset styles.
*/
fieldset {
border: 0;
margin: 0;
padding: 0;
}
/*
* Allow only vertical resizing of textareas.
*/
textarea {
resize: vertical;
}
/* ==========================================================================
Author's custom styles
========================================================================== */
/* ==========================================================================
Helper classes
========================================================================== */
/*
* Hide visually and from screen readers
*/
.hidden,
[hidden] {
display: none !important;
}
/*
* Hide only visually, but have it available for screen readers:
* https://snook.ca/archives/html_and_css/hiding-content-for-accessibility
*
* 1. For long content, line feeds are not interpreted as spaces and small width
* causes content to wrap 1 word per line:
* https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
*/
.sr-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
/* 1 */
}
/*
* Extends the .sr-only class to allow the element
* to be focusable when navigated to via the keyboard:
* https://www.drupal.org/node/897638
*/
.sr-only.focusable:active,
.sr-only.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
white-space: inherit;
width: auto;
}
/*
* Hide visually and from screen readers, but maintain layout
*/
.invisible {
visibility: hidden;
}
/*
* Clearfix: contain floats
*
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* `contenteditable` attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that receive the `clearfix` class.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
.clearfix::before,
.clearfix::after {
content: " ";
display: table;
}
.clearfix::after {
clear: both;
}
/* ==========================================================================
EXAMPLE Media Queries for Responsive Design.
These examples override the primary ('mobile first') styles.
Modify as content requires.
========================================================================== */
@media only screen and (min-width: 35em) {
/* Style adjustments for viewports that meet the condition */
}
@media print,
(-webkit-min-device-pixel-ratio: 1.25),
(min-resolution: 1.25dppx),
(min-resolution: 120dpi) {
/* Style adjustments for high resolution devices */
}
/* ==========================================================================
Print styles.
Inlined to avoid the additional HTTP request:
https://www.phpied.com/delay-loading-your-print-css/
========================================================================== */
@media print {
*,
*::before,
*::after {
background: #fff !important;
color: #000 !important;
/* Black prints faster */
box-shadow: none !important;
text-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]::after {
content: " (" attr(href) ")";
}
abbr[title]::after {
content: " (" attr(title) ")";
}
/*
* Don't show links that are fragment identifiers,
* or use the `javascript:` pseudo protocol
*/
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
pre {
white-space: pre-wrap !important;
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
/*
* Printing Tables:
* https://web.archive.org/web/20180815150934/http://css-discuss.incutio.com/wiki/Printing_Tables
*/
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
}

349
css/normalize.css vendored Normal file
View File

@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

0
humans.txt Normal file
View File

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

0
img/.gitignore vendored Normal file
View File

48
index.html Normal file
View File

@ -0,0 +1,48 @@
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content="">
<meta property="og:type" content="">
<meta property="og:url" content="">
<meta property="og:image" content="">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="icon.png">
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<meta name="theme-color" content="#fafafa">
</head>
<body>
<!-- Add your site or application content here -->
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
<div style="height: 50px; overflow: auto; margin: 0px; padding: 0px;">
MatCat BrowserLogic <span id="version">0.1.0</span>
<input type="button" id="btn_Link" value="<->"/>
<input type="button" id="btn_AddAND" value="&"/>
<input type="button" id="btn_AddNAND" value="!&"/>
<input type="button" id="btn_AddOR" value="|"/>
<input type="button" id="btn_AddNOR" value="!|"/>
<input type="button" id="btn_AddXOR" value="^"/>
<input type="button" id="btn_AddXNOR" value="!^"/>
<input type="button" id="btn_AddBTN" value="[]"/>
<input type="button" id="btn_Delete" value="Delete"/>
</div>
<canvas id="LogicPlane" width="400" height="300" style="margin: 0px; padding: 0px;"></canvas>
<script src="js/logicengine.js"></script>
<script src="js/main.js"></script>
</body>
</html>

635
js/logicengine.js Normal file
View File

@ -0,0 +1,635 @@
/*
First a few needed global functions
*/
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;
}
/*
Now we can get into the classes
*/
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") {
let old_fillStyle = ctx.fillStyle;
ctx.fillStyle = borderColor;
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;
}
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 ElementConnection {
constructor(elementContainer,element,input) {
this.Container = elementContainer;
this.Element = element;
this.Input = input;
}
}
class Element extends CanvasTools {
constructor(Inputs) {
super();
this.Name = "Element";
this.Designator = "";
this.Inputs = new Array(Inputs);
this.totalInputs = Inputs;
this.Width = 150;
this.Height = 100;
this.inputCircleRadius = 10;
this.outputCircleRadius = 10;
this.X = 0;
this.Y = 0;
this.OutputConnections = new Array();
}
Delete() {
// Just to clean up connections
for (let a = 0; a < this.OutputConnections.length;a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,false);
}
}
MouseClick() {
// Function for if mouse is clicked
}
mouseInside(mousePos) {
if (((mousePos.x >= this.X ) && (mousePos.x <= (this.X + this.Width))) & ((mousePos.y >= this.Y ) && (mousePos.y <= (this.Y + this.Height)))) return true;
return false;
}
addConnection(container, element, input) {
let newConnection = new ElementConnection(container,element,input);
this.OutputConnections.push(newConnection);
element.setInput(input,this.getOutput());
}
drawInputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00") {
let old_strokeStyle = ctx.strokeStyle;
let old_fillStyle = ctx.fillStyle;
if ((this.totalInputs * ((this.inputCircleRadius*2)+4)) > (this.Height-2)) {
this.inputCircleRadius = ((this.Height-(2 + this.totalInputs * 4)) / this.totalInputs)/2;
}
for (let a = 0; a < this.totalInputs;a++) {
ctx.beginPath();
ctx.arc(x+20,y+(this.inputCircleRadius + 2)+(((a*(4+(this.inputCircleRadius*2))))-2)+(this.inputCircleRadius/2),this.inputCircleRadius,0,2*Math.PI);
ctx.strokeStyle = borderColor;
ctx.fillStyle = circleColorFalse;
if (this.Inputs[a]) ctx.fillStyle = circleColorTrue;
ctx.fill();
ctx.stroke();
}
ctx.strokeStyle = old_strokeStyle;
ctx.fillStyle = old_fillStyle;
}
drawOutputs(ctx,x,y,borderColor = "#000",circleColorFalse = "#ff0000",circleColorTrue="#00ff00") {
let old_strokeStyle = ctx.strokeStyle;
let old_fillStyle = ctx.fillStyle;
ctx.beginPath();
ctx.arc(x+(this.Width-20),y+(this.Height/2),this.outputCircleRadius,0,2*Math.PI);
ctx.strokeStyle = borderColor;
ctx.fillStyle = circleColorFalse;
if (this.getOutput()) ctx.fillStyle = circleColorTrue;
ctx.fill();
ctx.stroke();
ctx.strokeStyle = old_strokeStyle;
ctx.fillStyle = old_fillStyle;
}
drawConnections(ctx) {
ctx.save();
for (let a = 0; a < this.OutputConnections.length;a++) {
if (!this.OutputConnections[a].Container.HasElement(this.OutputConnections[a].Element)) {
// This is a ghosted connection, lets get rid of it
this.OutputConnections.splice(a,1);
a--;
} else {
ctx.beginPath();
ctx.moveTo((this.X + this.Width) - 20, this.Y + (this.Height / 2));
ctx.lineTo(this.OutputConnections[a].Element.X + 20, this.OutputConnections[a].Element.Y + 20);
ctx.strokeStyle = "#555";
ctx.stroke();
}
}
ctx.restore();
}
setInput(Input,Value) {
let oldOutput = this.getOutput();
if (Value) {
Value = true;
} else {
Value = false;
}
if (Input < this.totalInputs) {
this.Inputs[Input] = Value;
}
if (this.getOutput() != oldOutput) {
// The output changed, we need to notify connected elements
for (let a = 0; a < this.OutputConnections.length;a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
}
}
}
getOutput() {
/*
Should return true or false
*/
return false;
}
drawElement(x,y,ctx) {
/*
Draw routine for the element
*/
this.drawBorderBox(ctx,x,y,drawWidth,drawHeight);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"LOGIC");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class inputElement extends Element {
constructor() {
super(0);
this.Output = false;
this.Width = 100;
this.Name = "InputElement";
}
getOutput() {
return this.Output;
}
drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"IN");
this.drawOutputs(ctx,x,y);
}
}
class inputButton extends inputElement {
constructor() {
super();
this.Name = "Button";
}
MouseClick() {
this.Output = ~this.Output;
for (let a = 0; a < this.OutputConnections.length;a++) {
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input,this.getOutput());
}
}
drawElement(x, y, ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawBorderBox(ctx,x+10,y+25,50,50,1,"#ccc","#777");
this.drawOutputs(ctx,x,y);
}
}
class LogicAND extends Element {
constructor(Inputs) {
super(Inputs);
this.Name = "AND";
}
getOutput() {
let ANDResult = true;
for (let a = 0; a < this.totalInputs;a++) {
if (!this.Inputs[a]) ANDResult = false;
}
return ANDResult;
}
drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"|⊃");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class LogicNAND extends LogicAND {
constructor(Inputs) {
super(Inputs);
this.Name = "NAND";
}
getOutput() {
if (super.getOutput()) {
return false;
} else {
return true;
}
}
drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,"|⊃🞄");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class LogicOR extends Element {
constructor(Inputs) {
super(Inputs);
this.Name = "OR";
}
getOutput() {
let ORResult = false;
for (let a = 0; a < this.totalInputs;a++) {
if (this.Inputs[a]) ORResult = true;
}
return ORResult;
}
drawElement(x,y,ctx) {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x,y,drawWidth,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,")⊃");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class LogicNOR extends LogicOR {
constructor(Inputs) {
super(Inputs);
this.Name = "NOR";
}
getOutput() {
if (super.getOutput()) {
return false;
} else {
return true;
}
}
drawElement(x,y,ctx) {
this.drawBorderBox(ctx, x,y,this.Width,this.Height);
this.drawTextCentered(ctx,x,y,this.Width,this.Height,")⊃🞄");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class LogicXOR extends Element {
constructor() {
super(2); // Only 2 inputs on XOR
this.Name = "XOR";
}
getOutput() {
let ORResult = false;
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
return ORResult;
}
drawElement(x,y,ctx) {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x,y,drawWidth,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class LogicXNOR extends Element {
constructor() {
super(2); // Only 2 inputs on XOR
this.Name = "XNOR";
}
getOutput() {
let ORResult = false;
if ( (this.Inputs[0] && !this.Inputs[1]) || (!this.Inputs[0] && this.Inputs[1]) ) ORResult = true;
return !ORResult;
}
drawElement(x,y,ctx) {
let drawWidth = this.Width;
let drawHeight = this.Height;
this.drawBorderBox(ctx, x,y,drawWidth,drawHeight);
this.drawTextCentered(ctx,x,y,drawWidth,drawHeight,"))⊃🞄");
this.drawInputs(ctx,x,y);
this.drawOutputs(ctx,x,y);
}
}
class elementContainer {
constructor() {
this.Elements = new Array();
this.Selected = false;
}
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 true;
}
}
return false;
}
DrawAll(ctx) {
for (let a = 0;a < this.Elements.length;a++) {
// Not ideal to loop twice but we need the connections drawn first
this.Elements[a].drawConnections(ctx);
}
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,2,"#5555FF","#5555ff");
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;
}
}
Select(element) {
this.Selected = element;
}
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;
}
}
class LogicEngine {
Resize(evt) {
this.Canvas.width = window.innerWidth;
this.Canvas.height = window.innerHeight - 50;
this.Mouse = false;
}
Mouse_Down(evt) {
let mousePos = getMousePos(this.Canvas, evt);
this.MouseDown = true;
this.MouseDownTime = performance.now();
let element = this.ActiveContainer.checkMouseBounds(mousePos);
if (element) {
console.log("Moused down on " + element.Designator);
this.MovingElement = element;
this.MovingElementStartX = element.X;
this.MovingElementStartY = element.Y;
this.MovingElementMouseStartX = mousePos.x;
this.MovingElementMouseStartY = mousePos.y;
}
}
Mouse_Up(evt) {
this.MouseDown = false;
if (this.MovingElement && (this.MovingElement.X == this.MovingElementStartX) && (this.MovingElement.Y == this.MovingElementStartY)) {
if ((performance.now() - this.MouseDownTime) < 3000) {
// Presume this was a click
this.ActiveContainer.Select(this.MovingElement);
if (this.ActiveLink) {
this.Link();
} else {
this.MovingElement.MouseClick();
}
}
//console.log("Mouse Up");
}
if (!this.MovingElement) this.ActiveContainer.Selected = false;
this.ActiveLink = false;
this.MovingElement = false;
}
Mouse_Move(evt) {
let mousePos = getMousePos(this.Canvas, evt);
this.Mouse = mousePos;
if(this.MouseDown) {
//console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y);
if (this.MovingElement) {
if ((performance.now() - this.MouseDownTime) > 100) {
this.ActiveContainer.Select(this.MovingElement);
let xOffset = mousePos.x - this.MovingElementMouseStartX;
let yOffset = mousePos.y - this.MovingElementMouseStartY;
let diffxOffset = this.MovingElementMouseStartX - this.MovingElementStartX;
let diffyOffset = this.MovingElementMouseStartY - this.MovingElementStartY;
this.MovingElement.X = (this.MovingElementMouseStartX + xOffset) - diffxOffset;
this.MovingElement.Y = (this.MovingElementMouseStartY + yOffset) - diffyOffset;
}
}
}
}
Key_Press(evt) {
if (evt.key == "Escape") {
if (this.MovingElement && this.MouseDown) {
this.MovingElement.X = this.MovingElementStartX;
this.MovingElement.Y = this.MovingElementStartY;
this.MovingElement = false;
}
}
if (evt.key == "Delete") {
if (this.ActiveContainer.Selected) {
this.ActiveContainer.DeleteElement(this.ActiveContainer.Selected);
this.ActiveContainer.Selected = false;
}
}
}
constructor(canvas) {
this.Canvas = canvas;
this.Ctx = canvas.getContext("2d");
this.FPSCounter = 0;
this.FPS = 0;
this.PotentialFPS = 0;
this.PotentialFPSAVGs = new Array(20);
this.PotentialFPSAVGLoc = 0;
this.LastFPSCheck = performance.now();
this.MouseDown = false;
this.MouseDownTime = 0;
this.MovingElementContainer = false;
this.MovingElement = false;
this.MovingElementStartX = 0;
this.MovingElementStartY = 0;
this.MovingElementMouseStartX = 0;
this.MovingElementMouseStartY = 0;
this.ActiveContainer = new elementContainer();
this.ActiveLink = false;
this.Canvas.setAttribute('tabindex','0');
}
Link() {
if (this.ActiveLink) {
if (this.ActiveContainer.Selected && (this.ActiveContainer.Selected != this.ActiveLink)) {
let input = parseInt(prompt("Please enter the input number (0 - x)"));
while (input == NaN) {
input = parseInt(prompt("Please enter the input number (0 - x)"));
}
this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected,input);
this.ActiveLink = false;
} else {
this.ActiveLink = false;
}
} else {
if (this.ActiveContainer.Selected) {
this.ActiveLink = this.ActiveContainer.Selected;
}
}
}
DrawLoop() {
let startLoop = performance.now();
this.Canvas.focus();
this.Ctx.clearRect(0,0,this.Canvas.width,this.Canvas.height);
if (this.ActiveLink) {
this.Ctx.save();
this.Ctx.strokeStyle = "#5555AA";
this.Ctx.lineWidth = 5;
this.Ctx.beginPath();
this.Ctx.moveTo(this.ActiveLink.X + (this.ActiveLink.Width/2), this.ActiveLink.Y + (this.ActiveLink.Height/2));
this.Ctx.lineTo(this.Mouse.x, this.Mouse.y);
this.Ctx.stroke();
this.Ctx.restore();
}
this.ActiveContainer.DrawAll(this.Ctx);
let ct = new CanvasTools();
let FPSOffset = this.Canvas.width - 150;
ct.drawText(this.Ctx,FPSOffset,650,"FPS: " + this.FPS,"12px console", "#005500");
ct.drawText(this.Ctx,FPSOffset,670,"Potential FPS: " + this.PotentialFPS,"12px console", "#005500");
let timeCheck = performance.now();
this.FPSCounter++;
if (!(Math.round(timeCheck - this.LastFPSCheck) % 50)) {
let frameTimeUS = (performance.now() - startLoop) * 1000;
let potentialFPS = 1000000 / frameTimeUS;
this.PotentialFPSAVGs[this.PotentialFPSAVGLoc] = Math.round(potentialFPS);
this.PotentialFPSAVGLoc++;
if (this.PotentialFPSAVGLoc == this.PotentialFPSAVGs.length) this.PotentialFPSAVGLoc = 0;
this.PotentialFPS = averageArray(this.PotentialFPSAVGs);
}
if ((timeCheck - this.LastFPSCheck) >= 1000) {
this.FPS = this.FPSCounter;
this.FPSCounter = 0;
this.LastFPSCheck = performance.now();
//console.log("Frame Time: " + frameTimeUS + "uS" + ", Potential FPS: " + potentialFPS);
//console.log("FPS: " + FPS);
}
requestAnimationFrame(this.DrawLoop.bind(this));
}
StartEngine() {
this.Resize("");
this.DrawLoop();
}
}

144
js/main.js Normal file
View File

@ -0,0 +1,144 @@
/*
MatCat BrowserLogic Simulator
*/
// get the canvas and get the engine object going
let lCanvasElement = document.getElementById("LogicPlane");
let logicEngine = new LogicEngine(lCanvasElement);
// Sadly this doesn't work well inside of the class so we will do it here real fast
window.addEventListener('resize', function(evt) {
logicEngine.Resize(evt);
}, false);
lCanvasElement.addEventListener('keydown', function(evt) {
logicEngine.Key_Press(evt);
}, false);
lCanvasElement.addEventListener('mousedown', function(evt) {
logicEngine.Mouse_Down(evt);
}, false);
lCanvasElement.addEventListener('mouseup', function(evt) {
logicEngine.Mouse_Up(evt);
}, false);
lCanvasElement.addEventListener('mousemove', function(evt) {
logicEngine.Mouse_Move(evt);
}, false);
// Get the engine going
logicEngine.StartEngine();
// Setup interface buttons
let btn_Link = document.getElementById("btn_Link");
btn_Link.addEventListener('click', function(evt) {
logicEngine.Link();
}, false);
let btn_Delete = document.getElementById("btn_Delete");
btn_Delete.addEventListener('click', function(evt) {
logicEngine.Key_Press({key: "Delete"});
}, false);
let btn_AddAND = document.getElementById("btn_AddAND");
btn_AddAND.addEventListener('click', function(evt) {
let newAND = new LogicAND(2);
newAND.X = 20;
newAND.Y = 20;
logicEngine.ActiveContainer.AddElement(newAND);
}, false);
let btn_AddNAND = document.getElementById("btn_AddNAND");
btn_AddNAND.addEventListener('click', function(evt) {
let newNAND = new LogicNAND(2);
newNAND.X = 20;
newNAND.Y = 20;
logicEngine.ActiveContainer.AddElement(newNAND);
}, false);
let btn_AddOR = document.getElementById("btn_AddOR");
btn_AddOR.addEventListener('click', function(evt) {
let newOR = new LogicOR(2);
newOR.X = 20;
newOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newOR);
}, false);
let btn_AddNOR = document.getElementById("btn_AddNOR");
btn_AddNOR.addEventListener('click', function(evt) {
let newNOR = new LogicNOR(2);
newNOR.X = 20;
newNOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newNOR);
}, false);
let btn_AddXOR = document.getElementById("btn_AddXOR");
btn_AddXOR.addEventListener('click', function(evt) {
let newXOR = new LogicXOR();
newXOR.X = 20;
newXOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newXOR);
}, false);
let btn_AddXNOR = document.getElementById("btn_AddXNOR");
btn_AddXNOR.addEventListener('click', function(evt) {
let newXNOR = new LogicXNOR();
newXNOR.X = 20;
newXNOR.Y = 20;
logicEngine.ActiveContainer.AddElement(newXNOR);
}, false);
let btn_AddBTN = document.getElementById("btn_AddBTN");
btn_AddBTN.addEventListener('click', function(evt) {
let newBTN = new inputButton();
newBTN.X = 20;
newBTN.Y = 20;
logicEngine.ActiveContainer.AddElement(newBTN);
}, false);
/*
let AND1 = new LogicAND(2);
AND1.X = 430;
AND1.Y = 70;
logicEngine.ActiveContainer.AddElement(AND1);
let OR1 = new LogicOR(6);
OR1.X = 220;
OR1.Y = 20;
OR1.addConnection(logicEngine.ActiveContainer,AND1,0);
logicEngine.ActiveContainer.AddElement(OR1);
let NAND1 = new LogicNAND(2);
NAND1.X = 220;
NAND1.Y = 140;
NAND1.addConnection(logicEngine.ActiveContainer,AND1,1);
logicEngine.ActiveContainer.AddElement(NAND1);
let AND2 = new LogicAND(2);
AND2.X = 630;
AND2.Y = 120;
AND1.addConnection(logicEngine.ActiveContainer,AND2,0);
logicEngine.ActiveContainer.AddElement(AND2);
let NOR1 = new LogicNOR(2);
NOR1.X = 430;
NOR1.Y = 250;
NOR1.addConnection(logicEngine.ActiveContainer,AND2,1);
logicEngine.ActiveContainer.AddElement(NOR1);
let Button1 = new inputButton();
Button1.X = 20;
Button1.Y = 20;
Button1.addConnection(logicEngine.ActiveContainer,OR1,1);
logicEngine.ActiveContainer.AddElement(Button1);
let Button2 = new inputButton();
Button2.X = 20;
Button2.Y = 130;
Button2.addConnection(logicEngine.ActiveContainer,NAND1,0);
logicEngine.ActiveContainer.AddElement(Button2);
let Button3 = new inputButton();
Button3.X = 20;
Button3.Y = 240;
Button3.addConnection(logicEngine.ActiveContainer,NAND1,1);
logicEngine.ActiveContainer.AddElement(Button3);
*/

24
js/plugins.js Normal file
View File

@ -0,0 +1,24 @@
// Avoid `console` errors in browsers that lack a console.
(function() {
var method;
var noop = function () {};
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
// Only stub undefined methods.
if (!console[method]) {
console[method] = noop;
}
}
}());
// Place any jQuery/helper plugins in here.

3
js/vendor/modernizr-3.11.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

5
robots.txt Normal file
View File

@ -0,0 +1,5 @@
# www.robotstxt.org/
# Allow crawling of all content
User-agent: *
Disallow:

BIN
tile-wide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
tile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB