230 lines
7.7 KiB
JavaScript
Executable File
230 lines
7.7 KiB
JavaScript
Executable File
var canvas, ctx
|
|
var selectedItem
|
|
var mouseisdown
|
|
var chip = new Component("main");
|
|
var pinImages = [];
|
|
var wireVisuals = [];
|
|
var wireBeingDrawn = [];
|
|
images = {};
|
|
var x;
|
|
document.addEventListener("DOMContentLoaded", function(event){
|
|
canvas = document.getElementById('logicsim');
|
|
canvas.addEventListener("mousedown",selectItem);
|
|
canvas.addEventListener("mouseup", function(){mouseisdown=false});
|
|
canvas.addEventListener("mousemove",mousemove);
|
|
document.addEventListener("keydown",checkKey);
|
|
ctx = canvas.getContext('2d');
|
|
preloadAssets();
|
|
requestAnimationFrame(drawCanvas);
|
|
x=setInterval(function(){chip.process()},1);
|
|
});
|
|
function getMousePos(c,e){
|
|
var rect = c.getBoundingClientRect();
|
|
return {
|
|
x: e.clientX - rect.left,
|
|
y: e.clientY - rect.top
|
|
}
|
|
}
|
|
function checkKey(e){
|
|
e=e||window.event;
|
|
if(e.keyCode==27){
|
|
selectedPin={component:-1,pin:-1};
|
|
wireBeingDrawn=[];
|
|
}
|
|
}
|
|
function isInside(c,point){
|
|
return ( point.x > c.position.x && point.x < c.position.x + images[c.type].width) &&
|
|
( point.y > c.position.y && point.y < c.position.y + images[c.type].height);
|
|
}
|
|
function isInsidePin(p,point){
|
|
return Math.sqrt(Math.pow((p.position.x-point.x),2)+Math.pow((p.position.y-point.y),2)) < p.radius;
|
|
}
|
|
var clickpos;
|
|
var nWireAttempts=0;
|
|
var selectedPin = {component:-1,pin:-1};
|
|
var hoveredPin = {component:-1,pin:-1,type:-1};
|
|
function selectItem(e){
|
|
pos = getMousePos(canvas, e)
|
|
if(hoveredPin.component>=0){
|
|
if(hoveredPin.type==1){
|
|
chip.pins[hoveredPin.pin]=1-chip.pins[hoveredPin.pin];
|
|
} else {
|
|
if(wireBeingDrawn.length>0){
|
|
if(chip.connect(selectedPin, hoveredPin, nWireAttempts)){
|
|
wireBeingDrawn[wireBeingDrawn.length-1]={component:hoveredPin.component,pin:hoveredPin.pin};
|
|
wireVisuals.push({wireId:nWireAttempts,path:wireBeingDrawn.slice()});
|
|
wireBeingDrawn=[];
|
|
selectedPin={component:-1,pin:-1};
|
|
nWireAttempts+=1;
|
|
} else {
|
|
console.log("noooo");
|
|
}
|
|
} else {
|
|
wireBeingDrawn.push({component:hoveredPin.component,pin:hoveredPin.pin});
|
|
wireBeingDrawn.push({x:pos.x,y:pos.y});
|
|
selectedPin = {component:hoveredPin.component,pin:hoveredPin.pin};
|
|
}
|
|
}
|
|
} else {
|
|
if(wireBeingDrawn.length>0){
|
|
wireBeingDrawn[wireBeingDrawn.length-1]={x:pos.x,y:pos.y};
|
|
wireBeingDrawn.push({x:pos.x,y:pos.y})//slice());
|
|
}
|
|
}
|
|
chip.zIndex.forEach(function(c,i){
|
|
if (isInside(c, pos) && ctx.getImageData(pos.x,pos.y,1,1).data[3]) {
|
|
mouseisdown = true;
|
|
clickpos = pos;
|
|
chip.sendToFront(chip.getProperIndex(c));
|
|
// DELETE THIS LATER //
|
|
return;
|
|
}
|
|
|
|
});
|
|
}
|
|
var pos;
|
|
function mousemove(e){
|
|
pos = getMousePos(canvas,e);
|
|
if(wireBeingDrawn.length>0){
|
|
wireBeingDrawn[wireBeingDrawn.length-1]={x:pos.x,y:pos.y};
|
|
}
|
|
if(mouseisdown){
|
|
last = chip.zIndex.length-1;
|
|
chip.zIndex[last].position.x -= (clickpos.x - pos.x);
|
|
chip.zIndex[last].position.y -= (clickpos.y - pos.y);
|
|
clickpos = pos;
|
|
}
|
|
if(!pinImages.some(pi=>{
|
|
if(isInsidePin(pi,pos)){
|
|
hoveredPin = {component:pi.component,pin:pi.pin,type:pi.type}
|
|
return true;
|
|
}
|
|
})){
|
|
hoveredPin={component:-1,pin:-1};
|
|
}
|
|
}
|
|
function preloadAssets(){
|
|
Object.entries(chips).forEach(function(c){
|
|
if (!(c[1].image in images)){
|
|
images[c[0]] = new Image();
|
|
images[c[0]].src = c[1].image;
|
|
}
|
|
});
|
|
}
|
|
function makeArr(startValue, stopValue, cardinality) {
|
|
var arr = [];
|
|
var step = (stopValue - startValue) / (cardinality - 1);
|
|
for (var i = 0; i < cardinality; i++) {
|
|
arr.push(startValue + (step * i));
|
|
}
|
|
return arr;
|
|
}
|
|
function drawCircle(x,y,radius,colour){
|
|
ctx.beginPath();
|
|
ctx.arc(Math.floor(x),Math.floor(y),radius,0,2*Math.PI,false);
|
|
ctx.fillStyle=colour;
|
|
ctx.fill();
|
|
}
|
|
function drawLine(origin,destination,width,colour){
|
|
ctx.beginPath();
|
|
ctx.moveTo(origin.x,origin.y);
|
|
ctx.lineTo(destination.x,destination.y);
|
|
ctx.strokeStyle=colour;
|
|
ctx.lineWidth=width;
|
|
ctx.stroke();
|
|
}
|
|
function drawCanvas() {
|
|
pI = [];
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
ctx.canvas.width = 600;
|
|
ctx.canvas.height = 600;
|
|
ctx.fillStyle="lightgray";
|
|
ctx.fillRect(0,0,20,canvas.height);
|
|
//components.slice().reverse().forEach(function(c){
|
|
for(var i=0;i<wireBeingDrawn.length-1;i++){
|
|
if(i==0)
|
|
p1=pinImages.find(p=>p.component==wireBeingDrawn[0].component && p.pin==wireBeingDrawn[0].pin && p.type==0).position;
|
|
else
|
|
p1=wireBeingDrawn[i];
|
|
//if(i==wireBeingDrawn.length-2)
|
|
// p2=pinImages.find(p=>p.component==wireBeingDrawn[i+1].component&&p.pin==wireBeingDrawn[i+1].pin&&p.type==0).position;
|
|
//else
|
|
p2=wireBeingDrawn[i+1]
|
|
drawLine(p1,p2,3,["black","red"][chip.subComponents[wireBeingDrawn[0].component].pins[wireBeingDrawn[0].pin]]);
|
|
}
|
|
wireVisuals=wireVisuals.filter(wv=> {return chip.wires.findIndex(w=>w.wireId==wv.wireId)>=0});
|
|
wireVisuals.forEach(wv=>{
|
|
for(var i=0;i<wv.path.length-1;i++){
|
|
if(i==0)
|
|
p1=pinImages.find(p=>p.component==wv.path[0].component && p.pin==wv.path[0].pin && p.type==0).position;
|
|
else
|
|
p1=wv.path[i];
|
|
if(i==wv.path.length-2)
|
|
p2=pinImages.find(p=>p.component==wv.path[i+1].component&&p.pin==wv.path[i+1].pin&&p.type==0).position;
|
|
else
|
|
p2=wv.path[i+1];
|
|
drawLine(p1,p2,3,["black","red"][chip.subComponents[wv.path[0].component].pins[wv.path[0].pin]]);
|
|
}
|
|
});
|
|
chip.pins.forEach((p,i)=>{
|
|
if(i<chip.inputs){
|
|
centerX=10;
|
|
otherpins = chip.inputs;
|
|
pindex=i;
|
|
} else {
|
|
centerX = canvas.width - 10;
|
|
otherpins = chip.pins.length - chip.inputs;
|
|
pindex = i - chip.inputs;
|
|
}
|
|
ys = makeArr(0-(20/otherpins),0+canvas.height+(20/otherpins),otherpins+2);
|
|
ys.shift();
|
|
ys.pop();
|
|
centerY = ys[pindex];
|
|
pI.push({component:0,pin:i,position:{x:centerX,y:centerY},radius:10,type:1});
|
|
secondaryX=(i<chip.inputs?centerX+20:centerX-20);
|
|
pI.push({component:0,pin:i,position:{x:secondaryX,y:centerY},radius:5,type:0});
|
|
//ctx.beginPath();
|
|
//ctx.arc(Math.floor(centerX), Math.floor(centerY), 10, 0, 2*Math.PI, false);
|
|
(hoveredPin.component==0&&hoveredPin.pin==i&&hoveredPin.type==0) ? offset=2 : offset=0;
|
|
|
|
fillStyle1=["black","red","grey","pink"][chip.pins[i]+offset];
|
|
fillStyle2=(i<chip.inputs?["black","red","grey","pink"]:["black","red","black","red"])[chip.pins[i]+((hoveredPin.component==0&&hoveredPin.pin==i&&hoveredPin.type==1)?2:0)];
|
|
//ctx.fill();
|
|
drawLine({x:centerX,y:centerY},{x:secondaryX,y:centerY},1,["black","red"][chip.pins[i]]);
|
|
drawCircle(centerX,centerY,10,fillStyle2);
|
|
drawCircle(secondaryX,centerY,5,fillStyle1);
|
|
})
|
|
chip.zIndex.forEach(c=>{
|
|
img = images[c.type];
|
|
ctx.drawImage(img,c.position.x,c.position.y);
|
|
c.pins.forEach((p,i)=>{
|
|
//trueCenterY = (c.position.y+(c.position.y + c.height))/2
|
|
centerX = c.position.x+img.width+5;
|
|
otherpins = c.pins.length - c.inputs;
|
|
pindex = i - c.inputs;
|
|
if(i<c.inputs){
|
|
centerX = c.position.x-5;
|
|
if(["xor","nor","or"].includes(c.type)){
|
|
centerX += 9;
|
|
}
|
|
otherpins = c.inputs;
|
|
pindex=i;
|
|
}
|
|
ys = makeArr(c.position.y-(20/otherpins),c.position.y+img.height+(20/otherpins),otherpins+2);
|
|
ys.shift();
|
|
ys.pop();
|
|
centerY = ys[pindex];
|
|
pI.push({component:chip.subComponents.indexOf(c),pin:i,position:{x:centerX,y:centerY},radius:10,type:0});
|
|
ctx.beginPath();
|
|
ctx.arc(Math.floor(centerX), Math.floor(centerY), 5, 0, 2*Math.PI, false);
|
|
(hoveredPin.component==chip.subComponents.indexOf(c)&&hoveredPin.pin==i) ? offset=2 : offset=0;
|
|
ctx.fillStyle=["black","red","grey","pink"][c.pins[i]+offset];
|
|
ctx.fill();
|
|
|
|
|
|
});
|
|
});
|
|
pinImages=pI;
|
|
requestAnimationFrame(drawCanvas);
|
|
}
|