add new zone box visuals,

This commit is contained in:
Redo
2025-07-19 21:36:50 -07:00
parent a5ce98b31d
commit 6446a621c6
13 changed files with 165 additions and 41 deletions

View File

@ -1,4 +1,3 @@
//bls 4
// This file should not exist. Fix later...
// -------------------------------------------------------------------
@ -61,6 +60,8 @@ function NDM_BoxSelect::onStartMode(%this, %client, %lastMode)
//Switch away from this mode
function NDM_BoxSelect::onChangeMode(%this, %client, %nextMode)
{
%client.ndBoxCleared();
if(%nextMode == $NDM::StackSelect)
{
//Clear selection
@ -107,6 +108,8 @@ function NDM_BoxSelect::onChangeMode(%this, %client, %nextMode)
//Kill this mode
function NDM_BoxSelect::onKillMode(%this, %client)
{
%client.ndBoxCleared();
//Destroy selection
if(isObject(%client.ndSelection))
%client.ndSelection.delete();
@ -164,6 +167,7 @@ function NDM_BoxSelect::onSelectObject(%this, %client, %obj, %pos, %normal)
else
{
%client.ndSelectionBox.zoneBrick = "";
%client.ndSelectionBox.setNormalColors();
%box = %obj.getWorldBox();
%p1 = getWords(%box, 0, 2);
%p2 = getWords(%box, 3, 5);
@ -186,6 +190,7 @@ function NDM_BoxSelect::onSelectObject(%this, %client, %obj, %pos, %normal)
} else if (isObject(%obj.physicalZone)) {
%box = ndGetBoxFromZone(%obj);
%client.ndSelectionBox.zoneBrick = %obj;
%client.ndSelectionBox.setZoneColors();
} else {
%box = ndGetPlateBoxFromRayCast(%pos, %normal);
}
@ -208,7 +213,7 @@ function ndRound(%v, %step) {
return mFloor(%v/%step + 0.5)*%step;
}
function ndCorrectBox(%box) {
function ndSnapBoxToGrid(%box) {
%xl = ndRound(getWord(%box, 0), 0.5);
%yl = ndRound(getWord(%box, 1), 0.5);
%zl = ndRound(getWord(%box, 2), 0.2);
@ -226,19 +231,16 @@ function ndGetBoxFromRom(%b) {
%bh = getWords(%box, 3, 5);
%bl = vectorAdd(%bl, "0 0 " SPC (%db.brickSizeZ * 0.2));
%bh = vectorAdd(%bh, "0 0 " SPC (%db.logicRomZ * 0.2));
return ndCorrectBox(%bl SPC %bh);
return ndSnapBoxToGrid(%bl SPC %bh);
}
function ndGetBoxFromZone(%b) {
%z = %b.physicalZone;
%pos = %z.position;
%scale = %z.getScale();
%sx = getWord(%scale, 0);
%sy = getWord(%scale, 1);
%sz = getWord(%scale, 2);
%bl = vectorAdd(%pos, 0 SPC -%sy SPC 0);
%bh = vectorAdd(%pos, %sx SPC 0 SPC %sz);
return ndCorrectBox(%bl SPC %bh);
%bl = vectorAdd(%pos, 0 SPC -%getWord(%scale,1) SPC 0);
%bh = vectorAdd(%pos, getWord(%scale,0) SPC 0 SPC getWord(%scale,2));
return ndSnapBoxToGrid(%bl SPC %bh);
}
@ -366,12 +368,18 @@ function ndApplyZoneEvent(%brick, %p1a, %p2a, %client) {
if(%brick.eventOutput[%i] $= "setZoneBox") {
%brick.eventOutputParameter[%i, 1] = %p1;
%brick.eventOutputParameter[%i, 2] = %p2;
// update event
%brick.setZoneBox(%p1,%p2, %brick.eventOutputParameter[%i,3], 0);
if(isFunction("fxDtsBrick", "triggerPropertyOnLoad"))
%brick.triggerPropertyOnLoad();
// inform client
messageClient(%client, 'MsgError', "");
commandToClient(%client, 'centerPrint',
"<font:Verdana:20>\c6Applied selection box to zone event \c3" @ %i
@ "\c6 on brick, and re-created zone.", 5);
%brick.setZoneBox(%p1, %p2,
%brick.eventOutputParameter[%i,3], 0);
@ "\c6 on brick,<br>\c6re-created zone, and triggered propertyOnLoad events.", 5);
return;
}
}

View File

@ -16,24 +16,29 @@ function gameConnection::ndCreateSelectionBox(%client) {
%client.ndSelectionBox = ND_SelectionBox(%shapeName);
}
function gameConnection::ndPushBoxHistory(%client) {
//talk("push");
if(!isObject(%client.ndSelectionBox)) return;
%box = %client.ndSelectionBox.point1 SPC %client.ndSelectionBox.point2;
function gameConnection::ndPushBoxHistory(%client, %optBox) {
if(%optBox $= "") {
if(!isObject(%client.ndSelectionBox)) return;
%box = %client.ndSelectionBox.point1 SPC %client.ndSelectionBox.point2;
%zone = %client.ndSelectionBox.zoneBrick;
} else {
%box = %optBox;
%zone = "";
}
%entry = %box TAB %zone;
if(%client.ndBoxHistoryCount>0 &&
%box $= %client.ndBoxHistory[%client.ndBoxHistoryCount-1])
%entry $= %client.ndBoxHistory[%client.ndBoxHistoryCount-1])
return;
%client.ndBoxHistory[%client.ndBoxHistoryCount+0] = %box;
%client.ndBoxHistory[%client.ndBoxHistoryCount+0] = %entry;
%client.ndBoxHistoryCount++;
%client.ndBoxHistoryPos = 1; // recall prior to this one
}
function gameConnection::ndBoxChanged(%client) {
//talk("changed");
%client.ndBoxHistoryPos = 0; // recall starting with this initial selection
%client.ndSaveBoxOnRecall = true;
}
function gameConnection::ndBoxCleared(%client) {
//talk("cleared");
if(%client.ndSaveBoxOnRecall) {
%client.ndPushBoxHistory();
%client.ndSaveBoxOnRecall = false;
@ -41,18 +46,26 @@ function gameConnection::ndBoxCleared(%client) {
%client.ndBoxHistoryPos = 0;
}
function gameConnection::ndRecallBoxHistory(%client, %offset) {
//talk("recall " @ %offset);
if(%offset<1 || %offset>%client.ndBoxHistoryCount) return;
%idx = %client.ndBoxHistoryCount - %offset;
%box = %client.ndBoxHistory[%idx];
%entry = %client.ndBoxHistory[%idx];
%box = getField(%entry, 0);
%zone = getField(%entry, 1);
%p1 = getWords(%box,0,2);
%p2 = getWords(%box,3,5);
if(!isObject(%client.ndSelectionBox))
%client.ndCreateSelectionBox();
%client.ndSelectionBox.zoneBrick = %zone;
if(isObject(%zone))
%client.ndSelectionBox.setZoneColors();
else
%client.ndSelectionBox.setNormalColors();
%client.ndSelectionBox.setSize(%p1,%p2);
%client.ndUpdateBottomPrint();
ndBoxPlaySound(%client.ndSelectionBox, BrickMoveSound);
}

View File

@ -1,4 +1,3 @@
//bls 4
// This file should not exist. Fix later...
// -------------------------------------------------------------------
@ -273,6 +272,8 @@ function NDM_PlantCopy::conditionalPlant(%this, %client, %force, %ownership)
return;
}
%client.ndPushBoxHistory(%client.ndSelection.getGhostWorldBox());
%client.ndLastPlantTime = $Sim::Time;
%pos = %client.ndSelection.ghostPosition;

View File

@ -1,4 +1,3 @@
//bls 4
// This file should not exist. Fix later...
// -------------------------------------------------------------------

View File

@ -1,4 +1,3 @@
//bls 3
// This file is way too big. Fix later...
// -------------------------------------------------------------------

View File

@ -55,11 +55,27 @@ function ND_SelectionBox::onRemove(%this)
%this.border_y[%i].delete();
%this.border_z[%i].delete();
}
ndShapelineConnectBoxes_delete(%this);
}
//Set normal color values and borders
function ND_SelectionBox::setNormalMode(%this)
{
function ND_SelectionBox::setZoneColors(%this) {
%this.innerColor = "0 0 0 0.60";
%this.outerColor = "0 0 0 0.35";
%this.borderColor = "1 0.7 0.5 0.99";
%this.borderColorSelected = "0.7 0 1 0.99";
%this.cornerColor1 = "0.8 0.74 0.5 0.99";
%this.cornerColor2 = "1 0.94 0.5 0.99";
%this.cornerColorSelected1 = "0.7 0.2 1 0.99";
%this.cornerColorSelected2 = "0.7 0.1 1 0.99";
%this.applyColors();
}
function ND_SelectionBox::setNormalColors(%this) {
%this.innerColor = "0 0 0 0.60";
%this.outerColor = "0 0 0 0.35";
@ -71,7 +87,13 @@ function ND_SelectionBox::setNormalMode(%this)
%this.cornerColorSelected1 = "0 0.2 1 0.99";
%this.cornerColorSelected2 = "0 0.1 0.9 0.99";
%this.applyColors();
}
//Set normal color values and borders
function ND_SelectionBox::setNormalMode(%this)
{
%this.isNormalMode = true;
//Unhide the corners and inner/outer box (hidden in disabled mode)
@ -83,7 +105,7 @@ function ND_SelectionBox::setNormalMode(%this)
%this.outerBox.unHideNode("ALL");
//Apply changes
%this.applyColors();
%this.setNormalColors();
%this.setSize(%this.point1, %this.point2);
%this.shapeName.setShapeName(%this.boxName);
}
@ -307,6 +329,16 @@ function ND_SelectionBox::setSize(%this, %point1, %point2)
%this.border_z[%i].setScale(%width SPC %width SPC %len_z + %width * 0.05);
}
}
// Draw lines from zone brick to zone if present
if(isObject(%this.zoneBrick)) {
ndShapelineConnectBoxes_create(%this, "1 0.7 0.5 0.3");
ndShapelineConnectBoxes_move(%this,
%this.zoneBrick.getWorldBox(),
%this.point1 SPC %this.point2);
} else {
ndShapelineConnectBoxes_delete(%this);
}
}
//Resize the selection box and align it to a player

View File

@ -5,18 +5,18 @@ A fork of the original New Duplicator by Zeblote, presently maintained and with
- Added the `/ownership` or `/o` command, which plants each brick in the current selection with its original ownership. Use in plant mode after copying/cutting.
`/savedup` now saves ownership, and `/ownership` can be used while holding a loaded duplication to load it.
(Loading ownership only works if the duplication was saved with this version, as the original newdup does not save ownership)
Use `/toggleownership` or `/to` to always plant with original ownership, similar to `/toggleforceplant` or `/tfp`
- Added `/prevBox` and `/nextBox` (aliases `/pb` and `/nb`) to recall selection-box history when in box-select mode, similar to pressing up in a chat client or terminal.
- Holding ctrl while making an initial stack selection selects all adjacent bricks of the same color, ignoring diagonals, similar to the fill-can.
Use `/toggleOwnership` or `/to` to always plant with original ownership.
- Added `/prevBox` and `/nextBox` (aliases `/pb` and `/nb`) to recall selection box history when in box-select mode, similar to pressing up in a chat client or terminal.
- Holding ctrl while making an initial stack selection selects all adjacent bricks of the same color, similar to the fill-can, ignoring diagonals.
With limited mode off, all adjacent bricks will be selected regardless of color.
- The `/alldups` list is nicely formatted, sorted by date, and shows who saved each item.
- Support for Brick_LuaLogic
- Support for Brick_LuaLogic:
Supercut can be used on wire bricks.
`/FillBrick LogicWire` or `/fbw` can be used to fill with wire bricks.
`/fillBrick LogicWire` or `/fbw` can be used to fill with wire bricks.
Initial-multi-box-selecting a ROM sets the box to its data volume.
- Support for Event_setZoneBox
- Support for Event_setZoneBox:
Initial multi-box-selecting a brick with a zone sets the box to its zone.
Hitting plant with this box updates the first Event_SetZoneBox event if present.
Hitting plant with this box updates the first setZoneBox output event if present.
## Tweaks
- Made the "Create Sym Table on Start" pref default to true.
@ -26,6 +26,6 @@ Hitting plant with this box updates the first Event_SetZoneBox event if present.
## Fixes
- Fixed "Nonexistent undo state" message when undoing a plant that has been supercut.
- Fixed preventing unequipping any tool for 1.5s after using `/duplicator`
- Removed useless files from the add-on root directory
- Removed useless files from the add-on root directory.
- Removed the annoying messages about mismatched newdup versions when joining a server.
- Removed the worm known as Support_Updater.

View File

@ -46,6 +46,7 @@ function serverCmdDupHelp(%client)
messageClient(%client, '', "<tab:220>\c3/ToggleForcePlant\t\c6 Enable force plant for normal planting, so you dont have to type it all the time.");
messageClient(%client, '', "<tab:220>\c3/PlantAs\c6 [\c3target\c6]\t\c6 Plant bricks in a different brick group. Target can be a name or blid.");
messageClient(%client, '', "<tab:220>\c3/Ownership\t\c6 Plant bricks with the original ownership from when they were copied or saved.");
messageClient(%client, '', "<tab:220>\c3/ToggleOwnership\t\c6 Always plant bricks with original ownership.");
messageClient(%client, '', "<font:Arial:8> ");
messageClient(%client, '', "<tab:220>\c3/FillWrench\t\c6 Open the fill wrench gui to change settings on all selected bricks.");

View File

@ -1,4 +1,3 @@
//bls 3
// -------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
//bls 3
// Handles interactions with the handheld duplicator item.
// -------------------------------------------------------------------

View File

@ -1,6 +1,4 @@
//bls 3
//function ndRotateVector(%vector, %steps)
function ndFillBus(%pos1, %pos2, %angleId, %color) {
talk(%pos1 @ ", " @ %pos2 @ ", " @ %angleId);
$ND::FillBrickColorID = %color + 1;

View File

@ -0,0 +1,73 @@
function ndShapelineCreate(%color) {
if(%color$="") %color="1 1 1 1";
%line = new StaticShape() {
datablock = ND_SelectionBoxBorder;
};
//%line.setScopeAlways(); // newdup does this, idk why yet
%line.setNodeColor("ALL", %color);
return %line;
}
function ndShapelineMove(%line, %p1,%p2) {
// calculate shape position
%center = vectorScale(vectorAdd(%p1,%p2), 0.5);
// calculate shape rotation
%lineDir = "0 0 1"; // direction of static shape
%dir = vectorSub(%p2, %p1);
%axis = vectorNormalize(vectorCross(%dir, %lineDir));
%angle = mAcos(vectorDot(%dir, %lineDir) / vectorLen(%dir) / vectorLen(%lineDir));
%rot = %axis SPC %angle;
// calculate shape scale
%scale = "1 1" SPC %vectorLen(%dir);
%line.setTransform(%center SPC %rot);
%line.setScale(%scale);
}
function ndShapelineDelete(%line) {
%line.delete();
}
////////////////////////////////////////////////////////////////////////////////
// Box drawing
function ndShapelineConnectBoxes_delete(%container) { // public
for(%i=0; %i<8; %i++) {
if(isObject(%line = %container.ndShapeline[%i]))
%line.delete();
}
}
function ndShapelineConnectBoxes_create(%container, %color) { // public
for(%i=0; %i<8; %i++) {
if(!isObject(%container.ndShapeline[%i]))
%container.ndShapeline[%i] = ndShapelineCreate(%color);
}
}
function ndMin(%a,%b) { return %a<%b ? %a : %b; }
function ndMax(%a,%b) { return %a>%b ? %a : %b; }
// draw 8 lines between the boxes' 8 corners
function ndNormalizeBox(%box) {
%pLx = ndMin(getWord(%box,0),getWord(%box,3));
%pLy = ndMin(getWord(%box,1),getWord(%box,4));
%pLz = ndMin(getWord(%box,2),getWord(%box,5));
%pHx = ndMax(getWord(%box,0),getWord(%box,3));
%pHy = ndMax(getWord(%box,1),getWord(%box,4));
%pHz = ndMax(getWord(%box,2),getWord(%box,5));
return %pLx SPC %pLy SPC %pLz SPC %pHx SPC %pHy SPC %pHz;
}
function ndShapelineConnectBoxes_move(%container, %box1, %box2) { // public
%box1 = ndNormalizeBox(%box1);
%box2 = ndNormalizeBox(%box2);
ndShapelineMove(%container.ndShapeline[0], getWord(%box1,0) SPC getWord(%box1,1) SPC getWord(%box1,2), getWord(%box2,0) SPC getWord(%box2,1) SPC getWord(%box2,2));
ndShapelineMove(%container.ndShapeline[1], getWord(%box1,0) SPC getWord(%box1,1) SPC getWord(%box1,5), getWord(%box2,0) SPC getWord(%box2,1) SPC getWord(%box2,5));
ndShapelineMove(%container.ndShapeline[2], getWord(%box1,0) SPC getWord(%box1,4) SPC getWord(%box1,2), getWord(%box2,0) SPC getWord(%box2,4) SPC getWord(%box2,2));
ndShapelineMove(%container.ndShapeline[3], getWord(%box1,0) SPC getWord(%box1,4) SPC getWord(%box1,5), getWord(%box2,0) SPC getWord(%box2,4) SPC getWord(%box2,5));
ndShapelineMove(%container.ndShapeline[4], getWord(%box1,3) SPC getWord(%box1,1) SPC getWord(%box1,2), getWord(%box2,3) SPC getWord(%box2,1) SPC getWord(%box2,2));
ndShapelineMove(%container.ndShapeline[5], getWord(%box1,3) SPC getWord(%box1,1) SPC getWord(%box1,5), getWord(%box2,3) SPC getWord(%box2,1) SPC getWord(%box2,5));
ndShapelineMove(%container.ndShapeline[6], getWord(%box1,3) SPC getWord(%box1,4) SPC getWord(%box1,2), getWord(%box2,3) SPC getWord(%box2,4) SPC getWord(%box2,2));
ndShapelineMove(%container.ndShapeline[7], getWord(%box1,3) SPC getWord(%box1,4) SPC getWord(%box1,5), getWord(%box2,3) SPC getWord(%box2,4) SPC getWord(%box2,5));
}

View File

@ -49,6 +49,7 @@ exec($ND::ScriptPath @ "server/images.cs");
exec($ND::ScriptPath @ "server/modes.cs");
exec($ND::ScriptPath @ "server/namedtargets.cs");
exec($ND::ScriptPath @ "server/prefs.cs");
exec($ND::ScriptPath @ "server/shapeline.cs");
exec($ND::ScriptPath @ "server/symmetrydefinitions.cs");
exec($ND::ScriptPath @ "server/symmetrytable.cs");
exec($ND::ScriptPath @ "server/undo.cs");