From a991b479e318ff89a0187fa097eb575f76de5579 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sat, 16 Oct 2021 02:27:37 -0400
Subject: [PATCH] Random build tool improvements from oldchemy and firestorm,
 subject to cleanup still

---
 .../newview/app_settings/settings_alchemy.xml |  11 ++
 indra/newview/llfloaterpreference.cpp         |   2 +-
 indra/newview/llfloatertools.cpp              |  81 +++++++-
 indra/newview/llmanip.cpp                     |   6 +-
 indra/newview/llmanipscale.cpp                |  16 +-
 indra/newview/llmanipscale.h                  |   4 +
 .../default/xui/en/floater_build_options.xml  |  26 ++-
 .../skins/default/xui/en/floater_tools.xml    | 186 ++++++++++--------
 8 files changed, 237 insertions(+), 95 deletions(-)

diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 6bf49b87b69..1bfebc8f834 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -277,6 +277,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>AlchemyEditRootAxis</key>
+    <map>
+      <key>Comment</key>
+      <string>Always use root object as edit pivot point</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>AlchemyForceFly</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 38d854d5017..85a1bb1722a 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -351,7 +351,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 
 	mCommitCallbackRegistrar.add("Pref.ClearLog",				boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
 	mCommitCallbackRegistrar.add("Pref.DeleteTranscripts",      boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
-	mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
+	mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false));
 
 	mCommitCallbackRegistrar.add("Pref.AddSkin", boost::bind(&LLFloaterPreference::onAddSkin, this));
 	mCommitCallbackRegistrar.add("Pref.RemoveSkin", boost::bind(&LLFloaterPreference::onRemoveSkin, this));
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index e5e9e0ebcba..e1994befe5d 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -459,6 +459,73 @@ void LLFloaterTools::refresh()
 
 	// Refresh object and prim count labels
 	LLLocale locale(LLLocale::USER_LOCALE);
+	
+	std::string desc_string;
+	std::string num_string;
+	bool enable_link_count = true;
+
+	LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+	S32 prim_count = selected_objects->getObjectCount();
+	if (prim_count == 1 && LLToolMgr::getInstance()->getCurrentTool() == LLToolFace::getInstance())
+	{
+		desc_string = getString("selected_faces");
+		
+		LLViewerObject* objectp = mObjectSelection->getFirstRootObject();
+		LLSelectNode* nodep = mObjectSelection->getFirstRootNode();
+		if(!objectp || !nodep)
+		{
+			objectp = selected_objects->getFirstObject();
+			nodep = selected_objects->getFirstNode();
+		}
+
+		if (objectp && objectp->getNumTEs() == selected_objects->getTECount())
+			num_string = "ALL_SIDES";
+		else if (objectp && nodep)
+		{
+			for (S32 i = 0; i < objectp->getNumTEs(); i++)
+			{
+				if (nodep->isTESelected(i))
+				{
+					if (!num_string.empty())
+						num_string.append(", ");
+					num_string.append(llformat("%d", i));
+				}
+			}
+		}
+	}
+	else if (prim_count == 1 && gSavedSettings.getBOOL("EditLinkedParts"))
+	{
+		desc_string = getString("link_number");
+		LLViewerObject* objectp = selected_objects->getFirstObject();
+		if (objectp && objectp->getRootEdit())
+		{
+			const LLViewerObject::const_child_list_t& children = objectp->getRootEdit()->getChildren();
+			if (children.empty())
+				num_string = "0"; //a childless prim is always link zero, and unhappy
+			else if (objectp->getRootEdit()->isSelected())
+				num_string = "1"; //root prim is always link one
+			else
+			{
+				S32 index = 1;
+				for (LLViewerObject* selected_child : children)
+				{
+					index++;
+					if (selected_child->isSelected())
+					{
+						LLResMgr::getInstance()->getIntegerString(num_string, index);
+						break;
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		enable_link_count = false;
+	}
+	getChild<LLUICtrl>("link_num_obj_count")->setTextArg("[DESC]", desc_string);
+	getChild<LLUICtrl>("link_num_obj_count")->setTextArg("[NUM]", num_string);
+
 #if 0
 	if (!gMeshRepo.meshRezEnabled())
 	{		
@@ -475,23 +542,20 @@ void LLFloaterTools::refresh()
 			std::string prim_cost_string;
 			S32 render_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectRenderCost();
 			LLResMgr::getInstance()->getIntegerString(prim_cost_string, render_cost);
-			getChild<LLUICtrl>("RenderingCost")->setTextArg("[COUNT]", prim_cost_string);
 		}
 		
 		// disable the object and prim counts if nothing selected
 		bool have_selection = ! LLSelectMgr::getInstance()->getSelection()->isEmpty();
-		getChildView("obj_count")->setEnabled(have_selection);
-		getChildView("prim_count")->setEnabled(have_selection);
-		getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost);
+		getChildView("link_num_obj_count")->setEnabled(have_selection);
 	}
 	else
 #endif
 	{
-		F32 link_cost  = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost();
-		S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount();
+		F32 link_cost  = selected_objects->getSelectedLinksetCost();
+		S32 link_count = selected_objects->getRootObjectCount();
 
 		LLCrossParcelFunctor func;
-		if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true))
+		if (selected_objects->applyToRootObjects(&func, true))
 		{
 			// Selection crosses parcel bounds.
 			// We don't display remaining land capacity in this case.
@@ -531,6 +595,9 @@ void LLFloaterTools::refresh()
 		getChild<LLTextBox>("selection_count")->setText(selection_info.str());
 	}
 
+	// disable the object and prim counts if nothing selected
+	bool have_selection = !selected_objects->isEmpty();
+	getChildView("link_num_obj_count")->setEnabled(have_selection && enable_link_count);
 
 	// Refresh child tabs
 	mPanelPermissions->refresh();
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 510f00a5530..d20f158c66b 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -359,9 +359,11 @@ LLVector3 LLManip::getSavedPivotPoint() const
 
 LLVector3 LLManip::getPivotPoint()
 {
-	if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
+	static LLCachedControl<bool> editRootAxis(gSavedSettings, "AlchemyEditRootAxis", false);
+	LLViewerObject* vobjp = mObjectSelection->getFirstRootObject(TRUE);
+	if (vobjp && (mObjectSelection->getObjectCount() == 1 || editRootAxis) && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
 	{
-		return mObjectSelection->getFirstObject()->getPivotPositionAgent();
+		return vobjp->getPivotPositionAgent();
 	}
 	return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent();
 }
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index d003d89fce4..6abf342ef70 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -85,6 +85,8 @@ const LLManip::EManipPart MANIPULATOR_IDS[LLManipScale::NUM_MANIPULATORS] =
 	LLManip::LL_FACE_NEGZ
 };
 
+BOOL LLManipScale::sInvertUniform = FALSE;
+
 F32 get_default_max_prim_scale(bool is_flora)
 {
 	// a bit of a hack, but if it's foilage, we don't want to use the
@@ -121,7 +123,7 @@ void LLManipScale::setStretchTextures(BOOL b)
 // static
 BOOL LLManipScale::getUniform()
 {
-	return gSavedSettings.getBOOL("ScaleUniform");
+	return (gSavedSettings.getBOOL("ScaleUniform") ^ sInvertUniform);
 }
 
 // static
@@ -2102,3 +2104,15 @@ BOOL LLManipScale::canAffectSelection()
 	}
 	return can_scale;
 }
+
+BOOL LLManipScale::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+	sInvertUniform = TRUE;
+	return handleMouseDown(x,y,mask);
+}
+
+BOOL LLManipScale::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
+{
+	sInvertUniform = FALSE;
+    return handleMouseUp(x, y, mask);
+}
diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h
index 11ade9b7d0a..d9f6fe0f646 100644
--- a/indra/newview/llmanipscale.h
+++ b/indra/newview/llmanipscale.h
@@ -79,6 +79,8 @@ class LLManipScale : public LLManip
 	virtual BOOL	handleMouseDown( S32 x, S32 y, MASK mask );
 	virtual BOOL	handleMouseUp( S32 x, S32 y, MASK mask );
 	virtual BOOL	handleHover( S32 x, S32 y, MASK mask );
+	virtual BOOL	handleMiddleMouseDown( S32 x, S32 y, MASK mask );
+	virtual BOOL	handleMiddleMouseUp( S32 x, S32 y, MASK mask );
 	virtual void	render();
 	virtual void	handleSelect();
 
@@ -174,6 +176,8 @@ class LLManipScale : public LLManip
 	S32				mFirstClickX;
 	S32				mFirstClickY;
 	bool			mIsFirstClick;
+	
+	static BOOL		sInvertUniform;
 };
 
 #endif  // LL_MANIPSCALE_H
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
index 38428b36fc6..a4acefc1b5c 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
  legacy_header_height="18"
- height="170"
+ height="193"
  layout="topleft"
  name="build options floater"
  help_topic="build_options_floater"
@@ -14,14 +14,14 @@
      height="23"
      initial_value="1"
      label="Units (meters)"
-     label_width="130"
+     label_width="172"
      layout="topleft"
      left="10"
      max_val="5"
      min_val="0.01"
      name="GridResolution"
      top_pad="30"
-     width="200" />
+     width="242" />
     <spinner
      control_name="GridDrawSize"
      decimal_digits="1"
@@ -30,14 +30,30 @@
      increment="0.5"
      initial_value="5"
      label="Extents (meters)"
-     label_width="130"
+     label_width="172"
      layout="topleft"
      left_delta="0"
      max_val="50"
      min_val="1"
      name="GridDrawSize"
      top_pad="0"
-     width="200" />
+     width="242" />
+    <spinner
+     control_name="RotationStep"
+     decimal_digits="2"
+     follows="left|top"
+     height="23"
+     increment="0.01"
+     label="Angle (degrees)"
+     label_width="172"
+     layout="topleft"
+     left_delta="0"
+     max_val="359.99"
+     min_val="0.01"
+     name="RotationStep"
+     top_pad="0"
+     width="242"
+	 tool_tip="All rotations via rotation tool are constrained to multiples of this unit [Default: 1.0]"/>
     <check_box
      control_name="GridSubUnit"
      height="16"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 3443e92c80f..e18187a2c97 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
- positioning="cascading"
+ positioning="none"
  legacy_header_height="18"
  height="600"
  layout="topleft"
@@ -74,6 +74,14 @@
      name="status_remaining_capacity">
         Remaining capacity [LAND_CAPACITY].
     </floater.string>
+	<floater.string
+	  name="link_number">
+		Link number:
+	</floater.string>
+	<floater.string
+	  name="selected_faces">
+		Faces:
+	</floater.string>
     <button
      follows="left|top"
      height="25"
@@ -150,7 +158,7 @@
 	     parameter="Land" />
 	</button>
     <text
-     height="20"
+     height="30"
      word_wrap="true"
      use_ellipses="true"
      type="string"
@@ -229,7 +237,7 @@
 	<radio_group
      follows="left|top"
 	 left="5"
-	 top="53"
+	 top="55"
 	 height="70"
      layout="topleft"
 	 name="edit_radio_group">
@@ -263,23 +271,48 @@
     <check_box
      left="5"
      follows="left|top"
-     height="28"
+     height="19"
 	 control_name="EditLinkedParts"
      label="Edit linked"
-     layout="topleft"
+     layout="topleft"     
      name="checkbox edit linked parts"
-     top_pad="-8">
+     top_pad="0">
 		  <check_box.commit_callback
 			function="BuildTool.selectComponent"/>
 	</check_box>
 
+   <button
+     follows="left|top"
+     height="20"
+     image_overlay="BackArrow_Off"
+     top_pad="0"
+     layout="topleft"
+     name="prev_part_btn"
+     tool_tip="Select previous linked part or face"
+     width="12">
+	  <button.commit_callback
+	     function="Tools.SelectNextPart"
+	     parameter="previous" />
+    </button>
+   <button
+     follows="left|top"
+     height="20"
+     image_overlay="ForwardArrow_Off"
+     left_pad="0"
+     layout="topleft"
+     name="next_part_btn"
+     tool_tip="Select next linked part or face"
+     width="12">
+	  <button.commit_callback
+	     function="Tools.SelectNextPart"
+	     parameter="next" />
+    </button>
    <button
      follows="left|top"
      height="20"
      label="Link"
-     top="103"
+     left_pad="2"
      layout="topleft"
-     left="143"
      name="link_btn"
      width="50">
 	  <button.commit_callback
@@ -296,6 +329,30 @@
 	  <button.commit_callback
 	     function="BuildTool.UnlinkObjects"/>
     </button>
+        <combo_box
+     height="20"
+     layout="topleft"
+     left_pad="4"
+     follows="left|top"
+     name="combobox grid mode"
+     tool_tip="Choose the type of grid ruler for positioning the object"
+     top_delta="0"
+     width="108">
+      <combo_box.item
+       label="World grid"
+       name="World"
+       value="World" />
+      <combo_box.item
+       label="Local grid"
+       name="Local"
+       value="Local" />
+      <combo_box.item
+       label="Reference grid"
+       name="Reference"
+       value="Reference" />
+       <combo_box.commit_callback
+      function="BuildTool.gridMode"/>
+    </combo_box>
     <check_box
      control_name="ScaleUniform"
      height="19"
@@ -305,7 +362,7 @@
      name="checkbox uniform"
      top="48"
      label_text.wrap="true"
-     label_text.width="100"
+     label_text.width="120"
      width="134" />
     <check_box
      control_name="ScaleStretchTextures"
@@ -315,7 +372,7 @@
      layout="topleft"
      left="143"
      name="checkbox stretch textures"
-     top_pad="-4"
+     top_pad="-2"
      follows="left|top"
      width="134" />
    <check_box
@@ -324,51 +381,33 @@
      initial_value="true"
      label="Snap"
      layout="topleft"
-     top_pad="0"
+     top_pad="-2"
      name="checkbox snap to grid"
      width="134" />
-    <combo_box
-      height="20"
-      layout="topleft"
-      follows="left|top"
-      name="combobox grid mode"
-      tool_tip="Choose the type of grid ruler for positioning the object"
-      top="83"
-      left="195"
-      top_pad="0"
-      width="60">
-      <combo_box.item
-      label="World"
-      name="World"
-      value="World" />
-      <combo_box.item
-      label="Local"
-      name="Local"
-      value="Local" />
-      <combo_box.item
-      label="Reference"
-      name="Reference"
-      value="Reference" />
-      <combo_box.commit_callback
-      function="BuildTool.gridMode"/>
-    </combo_box>  
-  
-  <button
-     left="259"
-     label=""
+  <check_box
+     control_name="AlchemyEditRootAxis"
+     height="18"
+     initial_value="false"
+     label="Edit axis at root"
+     layout="topleft"
+     top_pad="-2"
+     name="checkbox actual root"
+     width="134" />
+    <button
+     left_pad="0"
      image_selected="ForwardArrow_Press"
-     image_unselected="ForwardArrow_Off"
+     image_unselected="ForwardArrow_Off"   
      layout="topleft"
      follows="top|left"
      name="Options..."
      tool_tip="See more grid options"
-     top="83"
-     width="25"
-     height="20" >
+     top="80"
+     right="-10"
+     width="18"
+     height="23" >
 	 <button.commit_callback
 	     function="BuildTool.gridOptions"/>
 	</button>
-  
    <button
      follows="left|top"
      height="20"
@@ -757,7 +796,19 @@
 	     function="BuildTool.applyToSelection"/>
     </button>
     <text
-	 text_color="LtGray_50"
+     type="string"
+     length="1"
+     height="10"
+     follows="left|top"
+     layout="topleft"
+     top_pad="28"
+     left="10"
+     name="link_num_obj_count"
+	 tool_tip="Link number may not be accurate."
+     width="143">
+        [DESC] [NUM]
+    </text>
+	<text
 	  type="string"
 	  length="1"
 	  height="16"
@@ -766,12 +817,11 @@
 	  layout="topleft"
 	  left="10"
 	  name="selection_empty"
-	  top_pad="11"
+	  top_pad="2"
 	  width="100">
 		Nothing selected.
 	</text>
 	<text
-	 text_color="LtGray_50"
 	  type="string"
 	  length="1"
 	  height="16"
@@ -785,7 +835,6 @@
 	  width="280">
 	</text>
 	<text
-	 text_color="LtGray_50"
 	  type="string"
 	  length="1"
 	  height="16"
@@ -794,37 +843,11 @@
 	  layout="topleft"
 	  left="10"
 	  name="remaining_capacity"
-	  top_pad="-2"
+	  top_pad="-5"
 	  visible="false"
 	  width="280">
 	  [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info]
 	</text>
-    <!-- <text -->
-    <!-- text_color="LtGray_50" -->
-    <!--  type="string" -->
-    <!--  length="1" -->
-    <!--  height="10" -->
-    <!--  follows="left|top" -->
-    <!--  halign="right" -->
-    <!--  layout="topleft" -->
-    <!--  right="-10" -->
-    <!--  name="obj_count" -->
-    <!--  top_pad="5" -->
-    <!--  width="143"> -->
-    <!--     Objects: [COUNT] -->
-    <!-- </text> -->
-    <!-- <text -->
-    <!-- text_color="LtGray_50" -->
-    <!--  type="string" -->
-    <!--  length="1" -->
-    <!--  follows="left|top" -->
-    <!--  halign="right" -->
-    <!--  layout="topleft" -->
-    <!--  right="-10" -->
-    <!--  name="prim_count" -->
-    <!--  width="143"> -->
-    <!--     Prims: [COUNT] -->
-    <!-- </text> -->
     <view_border
     bevel_style="none"
     follows="top|left"
@@ -832,19 +855,20 @@
     layout="topleft"
     left="6"
     name="cost_text_border"
-    top="145"
+    top="165"
     width="282"/>
     <tab_container
      follows="left|top"
-     height="410"
+     height="430"
      halign="center"
      left="0"
      name="Object Info Tabs"
      tab_max_width="100"
      tab_min_width="40"
      tab_position="top"
+     tab_height="20"
      open_tabs_on_drag_and_drop="true"
-     top="180"
+     top="203"
      width="295">
 	
 <panel
@@ -913,6 +937,10 @@
              name="Sale Mixed">
                 Mixed Sale
             </panel.string>
+            <panel.string
+             name="multiple selection">
+                Multiple selection
+            </panel.string>
             <text
              follows="left|top"
              height="10"
-- 
GitLab