WIP:0.4.3 Multi-Select

This commit is contained in:
MatCat 2021-03-08 00:38:27 -08:00
parent fd3cea317f
commit 0eb96aead8
4 changed files with 147 additions and 48 deletions

View File

@ -12,6 +12,10 @@ To be decided, but at this moment this code is open source and free to use for n
## Changelog ## Changelog
### 0.4.3
* There is now multi-selection, including movement, deleting, disconnecting, etc.
### 0.4.2 ### 0.4.2
* Added Hex keypad with 4 bit output, also has 3 function keys * Added Hex keypad with 4 bit output, also has 3 function keys

View File

@ -80,6 +80,15 @@ class elementContainer {
this.ICOutputs = 0; this.ICOutputs = 0;
} }
isSelected(element) {
if (this.Selected) {
for (let a = 0; a < this.Selected.length; a++) {
if (this.Selected[a] == element) return true;
}
}
return false;
}
isHigh(element,input) { isHigh(element,input) {
let isHigh = false; let isHigh = false;
for (let a = 0; a < this.Elements.length; a++) { for (let a = 0; a < this.Elements.length; a++) {
@ -121,15 +130,30 @@ class elementContainer {
} }
DeleteElement(element) { DeleteElement(element) {
// Can pass object or Designator // Can pass object or Designator, or array
for (let a = 0; a < this.Elements.length; a++) { if (Array.isArray(element)) {
if ((this.Elements[a] == element) || (this.Elements[a].Designator == element)) { let returnval = false;
this.Elements[a].Delete(); for (let a = 0; a < element.length; a++) {
this.Elements.splice(a,1); for (let b = 0; b < this.Elements.length; b++) {
return true; if ((this.Elements[b] == element[a]) || (this.Elements[b].Designator == element[a])) {
this.Elements[b].Delete();
this.Elements.splice(b, 1);
b--;
returnval = true;
}
}
} }
return returnval;
} else {
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;
} }
return false;
} }
HasElement(element) { HasElement(element) {
@ -144,8 +168,17 @@ class elementContainer {
Disconnect(element) { Disconnect(element) {
if (!element) return false; if (!element) return false;
for (let a = 0; a < this.Elements.length; a++) {
this.Elements[a].Disconnect(element); if (Array.isArray(element)) {
for (let a = 0; a < this.Elements.length; a++) {
for (let b = 0; b < element.length; b++) {
this.Elements[a].Disconnect(element[b]);
}
}
} else {
for (let a = 0; a < this.Elements.length; a++) {
this.Elements[a].Disconnect(element);
}
} }
} }
@ -163,7 +196,7 @@ class elementContainer {
if (this.Elements[a] instanceof ICOutput) ICOuts++; if (this.Elements[a] instanceof ICOutput) ICOuts++;
if (this.Elements[a].isVisible()) { if (this.Elements[a].isVisible()) {
ctx.save(); ctx.save();
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.isSelected(this.Elements[a])) 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);
ctx.restore(); ctx.restore();
} }
@ -171,8 +204,10 @@ class elementContainer {
this.ICOutputs = ICOuts; this.ICOutputs = ICOuts;
if (!this.Selected) { if (!this.Selected) {
let PropertiesBox = document.getElementById("PropertiesBox"); if (this.Selected.length == 1) {
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none"; let PropertiesBox = document.getElementById("PropertiesBox");
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
}
} }
if (logicEngine.Settings.TopConnections && !logicEngine.Settings.HideConnections) { if (logicEngine.Settings.TopConnections && !logicEngine.Settings.HideConnections) {
@ -184,29 +219,37 @@ class elementContainer {
} }
SelectWithin(x1,y1,x2,y2) {
let selectedArray = new Array();
for (let a = 0; a < this.Elements.length; a++) {
if ((this.Elements[a].X >= x1) && ((this.Elements[a].X + this.Elements[a].Width) <= x2) && (this.Elements[a].Y >= y1) && ((this.Elements[a].Y + this.Elements[a].Height) <= y2)) selectedArray.push(this.Elements[a]);
}
this.Selected = selectedArray;
}
Select(element) { Select(element) {
this.Selected = element; this.Selected = new Array(element);
let PropertiesBox = document.getElementById("PropertiesBox"); let PropertiesBox = document.getElementById("PropertiesBox");
let PropertiesBoxTitle = document.getElementById("PropertiesBoxTitle"); let PropertiesBoxTitle = document.getElementById("PropertiesBoxTitle");
let PropertiesBoxContent = document.getElementById("PropertiesBoxContent"); let PropertiesBoxContent = document.getElementById("PropertiesBoxContent");
PropertiesBoxTitle.innerText = this.Selected.Designator + " Properties"; PropertiesBoxTitle.innerText = this.Selected[0].Designator + " Properties";
let contentString = "<table id='propertiesTable'>"; let contentString = "<table id='propertiesTable'>";
for (let a = 0; a < this.Selected.Properties.length;a++) { for (let a = 0; a < this.Selected[0].Properties.length;a++) {
contentString += "<tr><td>" + this.Selected.Properties[a].Name + "</td><td>"; contentString += "<tr><td>" + this.Selected[0].Properties[a].Name + "</td><td>";
switch (this.Selected.Properties[a].Type) { switch (this.Selected[0].Properties[a].Type) {
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[0].Properties[a].Name + "' min='" + this.Selected[0].Properties[a].Minimium + "' max='" + this.Selected[0].Properties[a].Maximium + "' value='" + this.Selected[0].Properties[a].CurrentValue + "' onchange='logicEngine.PropertyChange(" + String.fromCharCode(34) + this.Selected[0].Properties[a].Name + String.fromCharCode(34) +");'>";
break; break;
case "string": 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) + ');">'; contentString += '<input type="text" id="prop_' + this.Selected[0].Properties[a].Name + '" minlength="' + this.Selected[0].Properties[a].Minimium + '" maxlength="' + this.Selected[0].Properties[a].Maximium + '" value="' + this.Selected[0].Properties[a].CurrentValue + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected[0].Properties[a].Name + String.fromCharCode(39) + ');">';
break; break;
case "color": case "color":
contentString += '<input type="color" id="prop_' + this.Selected.Properties[a].Name + '" value="' + this.Selected.Properties[a].CurrentValue + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected.Properties[a].Name + String.fromCharCode(39) + ');">'; contentString += '<input type="color" id="prop_' + this.Selected[0].Properties[a].Name + '" value="' + this.Selected[0].Properties[a].CurrentValue + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected[0].Properties[a].Name + String.fromCharCode(39) + ');">';
break; break;
case "list": case "list":
contentString += '<select id="prop_' + this.Selected.Properties[a].Name + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected.Properties[a].Name + String.fromCharCode(39) + ');">'; contentString += '<select id="prop_' + this.Selected[0].Properties[a].Name + '" onchange="logicEngine.PropertyChange(' + String.fromCharCode(39) + this.Selected[0].Properties[a].Name + String.fromCharCode(39) + ');">';
for (let b = 0; b < this.Selected.Properties[a].Values.length; b++) { for (let b = 0; b < this.Selected[0].Properties[a].Values.length; b++) {
contentString += '<option value="' + this.Selected.Properties[a].Values[b].Value + '" '+ ((this.Selected.Properties[a].Values[b].Value == this.Selected.Properties[a].CurrentValue) ? ' selected' : '') + '>' + this.Selected.Properties[a].Values[b].String + '</option>'; contentString += '<option value="' + this.Selected[0].Properties[a].Values[b].Value + '" '+ ((this.Selected[0].Properties[a].Values[b].Value == this.Selected[0].Properties[a].CurrentValue) ? ' selected' : '') + '>' + this.Selected[0].Properties[a].Values[b].String + '</option>';
} }
contentString += '</select>'; contentString += '</select>';
break; break;

View File

@ -75,12 +75,17 @@ class LogicEngine {
let element = this.ActiveContainer.checkMouseBounds(mousePos); let element = this.ActiveContainer.checkMouseBounds(mousePos);
if (element) { if (element) {
this.MouseDown = true; this.MouseDown = true;
this.ActiveContainer.Select(element); if (this.ActiveContainer.Selected.length <= 1) this.ActiveContainer.Select(element);
this.MovingElement = element; this.MovingElement = new Array(this.ActiveContainer.Selected.length);
this.MovingElementStartX = element.X;
this.MovingElementStartY = element.Y; for (let a = 0; a < this.ActiveContainer.Selected.length; a++) {
this.MovingElementMouseStartX = mousePos.x; this.MovingElement[a] = {
this.MovingElementMouseStartY = mousePos.y; StartX: this.ActiveContainer.Selected[a].X,
StartY: this.ActiveContainer.Selected[a].Y
};
this.MovingElementMouseStartX = mousePos.x;
this.MovingElementMouseStartY = mousePos.y;
}
element.MouseDown(mousePos); element.MouseDown(mousePos);
} else { } else {
this.MouseDown = true; this.MouseDown = true;
@ -90,6 +95,15 @@ class LogicEngine {
this.Panning.StartOffsetY = this.Panning.OffsetY; this.Panning.StartOffsetY = this.Panning.OffsetY;
this.Panning.StartX = mousePos.x; this.Panning.StartX = mousePos.x;
this.Panning.StartY = mousePos.y; this.Panning.StartY = mousePos.y;
} else {
let cmPos = this.getCanvasMousePos(mousePos);
this.MultiSelectStart.InProgress = true;
this.MultiSelectStart.x = cmPos.x;
this.MultiSelectStart.y = cmPos.y;
this.ActiveContainer.Selected = false;
let PropertiesBox = document.getElementById("PropertiesBox");
PropertiesBox.style.display = "none";
} }
} }
if (this.ActiveContainer.Selected) { if (this.ActiveContainer.Selected) {
@ -102,18 +116,35 @@ class LogicEngine {
Mouse_Up(evt) { Mouse_Up(evt) {
let mousePos = getMousePos(this.Canvas, evt); let mousePos = getMousePos(this.Canvas, evt);
if (this.MovingElement) this.MovingElement.MouseUp(mousePos); if (this.MovingElement) {
let element = this.ActiveContainer.checkMouseBounds(mousePos);
if (element) element.MouseUp(mousePos);
}
if (this.MovingElement && (this.MovingElement.X == this.MovingElementStartX) && (this.MovingElement.Y == this.MovingElementStartY)) { if (this.MovingElement && (this.MovingElement.X == this.MovingElementStartX) && (this.MovingElement.Y == this.MovingElementStartY)) {
if ((performance.now() - this.MouseDownTime) < 3000) { if ((performance.now() - this.MouseDownTime) < 3000) {
// Presume this was a click // Presume this was a click
this.MovingElement.MouseClick(mousePos); let element = this.ActiveContainer.checkMouseBounds(mousePos);
if (element) element.MouseClick(mousePos);
} }
//console.log("Mouse Up"); //console.log("Mouse Up");
} }
if (!this.MovingElement && evt.which === 1) this.ActiveContainer.Selected = false; if (!this.MovingElement && evt.which === 1) {
this.ActiveContainer.Selected = false;
let PropertiesBox = document.getElementById("PropertiesBox");
PropertiesBox.style.display = "none";
}
this.MovingElement = false; this.MovingElement = false;
this.MouseDown = false; this.MouseDown = false;
if (this.MultiSelectStart.InProgress) {
this.MultiSelectStart.InProgress = false;
let cmStartPos = {x: this.MultiSelectStart.x, y: this.MultiSelectStart.y};
let cmEndPos = this.getCanvasMousePos(mousePos);
this.ActiveContainer.SelectWithin(cmStartPos.x,cmStartPos.y,cmEndPos.x,cmEndPos.y);
}
if (this.ActiveContainer.Selected) { if (this.ActiveContainer.Selected) {
disableSelectedRCMs(false); disableSelectedRCMs(false);
} else { } else {
@ -128,18 +159,26 @@ class LogicEngine {
if(this.MouseDown) { if(this.MouseDown) {
//console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y); //console.log('Mouse at position: ' + mousePos.x + ',' + mousePos.y);
if (this.MovingElement) { if (this.MovingElement) {
if ((performance.now() - this.MouseDownTime) > 100) { if ((performance.now() - this.MouseDownTime) > 100) {
let xOffset = mousePos.x - this.MovingElementMouseStartX; let xOffset = mousePos.x - this.MovingElementMouseStartX;
let yOffset = mousePos.y - this.MovingElementMouseStartY; let yOffset = mousePos.y - this.MovingElementMouseStartY;
let diffxOffset = this.MovingElementMouseStartX - this.MovingElementStartX;
let diffyOffset = this.MovingElementMouseStartY - this.MovingElementStartY; for (let a = 0; a < this.ActiveContainer.Selected.length; a++) {
let actualPosX = (this.MovingElementMouseStartX + xOffset) - diffxOffset; let diffxOffset = this.MovingElementMouseStartX - this.MovingElement[a].StartX;
let actualPosY = (this.MovingElementMouseStartY + yOffset) - diffyOffset; let diffyOffset = this.MovingElementMouseStartY - this.MovingElement[a].StartY;
if (!this.ControlPressed && this.Settings.SnapGrid) actualPosX = Math.round(actualPosX/this.Settings.GridSize)*this.Settings.GridSize; let actualPosX = (this.MovingElementMouseStartX + xOffset) - diffxOffset;
if (!this.ControlPressed && this.Settings.SnapGrid) actualPosY = Math.round(actualPosY/this.Settings.GridSize)*this.Settings.GridSize; let actualPosY = (this.MovingElementMouseStartY + yOffset) - diffyOffset;
this.MovingElement.X = actualPosX;
this.MovingElement.Y = actualPosY; if (!this.ControlPressed && this.Settings.SnapGrid) actualPosX = Math.round(actualPosX / this.Settings.GridSize) * this.Settings.GridSize;
if (!this.ControlPressed && this.Settings.SnapGrid) actualPosY = Math.round(actualPosY / this.Settings.GridSize) * this.Settings.GridSize;
this.ActiveContainer.Selected[a].X = actualPosX;
this.ActiveContainer.Selected[a].Y = actualPosY;
}
} }
} else { } else {
if (this.ControlPressed) { if (this.ControlPressed) {
let distX = mousePos.x - this.Panning.StartX; let distX = mousePos.x - this.Panning.StartX;
@ -181,6 +220,8 @@ class LogicEngine {
if (this.ActiveContainer.Selected) { if (this.ActiveContainer.Selected) {
this.ActiveContainer.DeleteElement(this.ActiveContainer.Selected); this.ActiveContainer.DeleteElement(this.ActiveContainer.Selected);
this.ActiveContainer.Selected = false; this.ActiveContainer.Selected = false;
let PropertiesBox = document.getElementById("PropertiesBox");
PropertiesBox.style.display = "none";
} }
} }
} }
@ -200,8 +241,6 @@ class LogicEngine {
this.MouseDownTime = 0; this.MouseDownTime = 0;
this.MovingElementContainer = false; this.MovingElementContainer = false;
this.MovingElement = false; this.MovingElement = false;
this.MovingElementStartX = 0;
this.MovingElementStartY = 0;
this.MovingElementMouseStartX = 0; this.MovingElementMouseStartX = 0;
this.MovingElementMouseStartY = 0; this.MovingElementMouseStartY = 0;
this.ActiveContainer = new elementContainer(); this.ActiveContainer = new elementContainer();
@ -212,20 +251,26 @@ class LogicEngine {
this.Canvas.setAttribute('tabindex','0'); this.Canvas.setAttribute('tabindex','0');
this.ControlPressed = false; this.ControlPressed = false;
this.Panning = {OffsetX: 0, OffsetY: 0,StartOffsetX: 0, StartOffsetY: 0, StartX: 0, StartY: 0}; this.Panning = {OffsetX: 0, OffsetY: 0,StartOffsetX: 0, StartOffsetY: 0, StartX: 0, StartY: 0};
this.MultiSelectStart = {
x: 0,
y: 0,
InProgress: false
};
} }
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.OutputLink.Output); this.ActiveLink.addConnection(this.ActiveContainer,this.ActiveContainer.Selected[0],input,this.ActiveLink.OutputLink.Output);
this.ActiveLink = false; this.ActiveLink = false;
} else { } else {
this.ActiveLink = false; this.ActiveLink = false;
} }
} else { } else {
if (this.ActiveContainer.Selected) { if (this.ActiveContainer.Selected.length == 1) {
this.ActiveLink = this.ActiveContainer.Selected; this.ActiveLink = this.ActiveContainer.Selected[0];
} }
} }
@ -242,6 +287,12 @@ class LogicEngine {
} }
let startLoop = performance.now(); let startLoop = performance.now();
this.Ctx.clearRect(0- this.Panning.OffsetX,0- this.Panning.OffsetY,this.Canvas.width,this.Canvas.height); this.Ctx.clearRect(0- this.Panning.OffsetX,0- this.Panning.OffsetY,this.Canvas.width,this.Canvas.height);
let ct = new CanvasTools();
if (this.MultiSelectStart.InProgress) {
let cmPos = this.getCanvasMousePos(this.Mouse);
ct.drawBorderBox(this.Ctx,this.MultiSelectStart.x,this.MultiSelectStart.y,cmPos.x - this.MultiSelectStart.x,cmPos.y - this.MultiSelectStart.y,0,"rgba(100,200,255,0.25)","rgba(100,200,255,0.25)");
}
this.ActiveContainer.DrawAll(this.Ctx,this.Settings); this.ActiveContainer.DrawAll(this.Ctx,this.Settings);
let tfm_CreateIC = document.getElementById("tfm_CreateIC"); let tfm_CreateIC = document.getElementById("tfm_CreateIC");
@ -275,7 +326,6 @@ class LogicEngine {
this.Ctx.stroke(); this.Ctx.stroke();
this.Ctx.restore(); this.Ctx.restore();
} }
let ct = new CanvasTools();
let FPSOffset = 5 - this.Panning.OffsetX; let FPSOffset = 5 - this.Panning.OffsetX;
if (this.Settings.ShowFPS) { if (this.Settings.ShowFPS) {
ct.drawText(this.Ctx, FPSOffset, 15 - this.Panning.OffsetY, "FPS: " + this.FPS, "12px console", "#00ff00"); ct.drawText(this.Ctx, FPSOffset, 15 - this.Panning.OffsetY, "FPS: " + this.FPS, "12px console", "#00ff00");

View File

@ -2,7 +2,7 @@
MatCat BrowserLogic Simulator MatCat BrowserLogic Simulator
*/ */
let Version = "0.4.2"; let Version = "0.4.3";
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
@ -145,7 +145,9 @@ tfm_Delete.addEventListener('click', function(evt) {
let rcm_Disconect = document.getElementById("rcm_Disconnect"); let rcm_Disconect = document.getElementById("rcm_Disconnect");
rcm_Disconect.addEventListener('click', function(evt) { rcm_Disconect.addEventListener('click', function(evt) {
logicEngine.ActiveContainer.Selected.Disconnect(); for (let a = 0; a < logicEngine.ActiveContainer.Selected.length;a++) {
logicEngine.ActiveContainer.Selected[a].Disconnect();
}
logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected); logicEngine.ActiveContainer.Disconnect(logicEngine.ActiveContainer.Selected);
}); });