add new zone box visuals,
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,3 @@
|
||||
//bls 4
|
||||
|
||||
// This file should not exist. Fix later...
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -1,4 +1,3 @@
|
||||
//bls 3
|
||||
|
||||
// This file is way too big. Fix later...
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
16
readme.md
16
readme.md
@ -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.
|
||||
|
@ -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.");
|
||||
|
@ -1,4 +1,3 @@
|
||||
//bls 3
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//bls 3
|
||||
|
||||
// Handles interactions with the handheld duplicator item.
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
//bls 3
|
||||
|
||||
//function ndRotateVector(%vector, %steps)
|
||||
function ndFillBus(%pos1, %pos2, %angleId, %color) {
|
||||
talk(%pos1 @ ", " @ %pos2 @ ", " @ %angleId);
|
||||
$ND::FillBrickColorID = %color + 1;
|
||||
|
73
scripts/server/shapeline.cs
Normal file
73
scripts/server/shapeline.cs
Normal 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));
|
||||
}
|
@ -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");
|
||||
|
Reference in New Issue
Block a user