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
### 0.4.3
* There is now multi-selection, including movement, deleting, disconnecting, etc.
### 0.4.2
* Added Hex keypad with 4 bit output, also has 3 function keys

View File

@ -80,6 +80,15 @@ class elementContainer {
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) {
let isHigh = false;
for (let a = 0; a < this.Elements.length; a++) {
@ -121,15 +130,30 @@ class elementContainer {
}
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;
// Can pass object or Designator, or array
if (Array.isArray(element)) {
let returnval = false;
for (let a = 0; a < element.length; a++) {
for (let b = 0; b < this.Elements.length; b++) {
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) {
@ -144,8 +168,17 @@ class elementContainer {
Disconnect(element) {
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].isVisible()) {
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);
ctx.restore();
}
@ -171,8 +204,10 @@ class elementContainer {
this.ICOutputs = ICOuts;
if (!this.Selected) {
let PropertiesBox = document.getElementById("PropertiesBox");
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
if (this.Selected.length == 1) {
let PropertiesBox = document.getElementById("PropertiesBox");
if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none";
}
}
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) {
this.Selected = element;
this.Selected = new Array(element);
let PropertiesBox = document.getElementById("PropertiesBox");
let PropertiesBoxTitle = document.getElementById("PropertiesBoxTitle");
let PropertiesBoxContent = document.getElementById("PropertiesBoxContent");
PropertiesBoxTitle.innerText = this.Selected.Designator + " Properties";
PropertiesBoxTitle.innerText = this.Selected[0].Designator + " Properties";
let contentString = "<table id='propertiesTable'>";
for (let a = 0; a < this.Selected.Properties.length;a++) {
contentString += "<tr><td>" + this.Selected.Properties[a].Name + "</td><td>";
switch (this.Selected.Properties[a].Type) {
for (let a = 0; a < this.Selected[0].Properties.length;a++) {
contentString += "<tr><td>" + this.Selected[0].Properties[a].Name + "</td><td>";
switch (this.Selected[0].Properties[a].Type) {
case "int":
contentString += "<input type='number' id='prop_" + this.Selected.Properties[a].Name + "' min='" + this.Selected.Properties[a].Minimium + "' max='" + this.Selected.Properties[a].Maximium + "' value='" + this.Selected.Properties[a].CurrentValue + "' onchange='logicEngine.PropertyChange(" + String.fromCharCode(34) + this.Selected.Properties[a].Name + String.fromCharCode(34) +");'>";
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;
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;
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;
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) + ');">';
for (let b = 0; b < this.Selected.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 += '<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[0].Properties[a].Values.length; b++) {
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>';
break;

View File

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

View File

@ -2,7 +2,7 @@
MatCat BrowserLogic Simulator
*/
let Version = "0.4.2";
let Version = "0.4.3";
let spanVersion = document.getElementById("version");
spanVersion.innerText = Version;
// 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");
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);
});