diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 868e5e50d6..528b298981 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -23024,6 +23024,28 @@ Change of this parameter will affect the layout of buttons in notification toast
Value
1
+ LastSelectedGrass
+
+ LastSelectedTree
+
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 01d3f4f813..d0ec71717c 100755
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -92,6 +92,8 @@
#include "llmeshrepository.h"
#include "llviewernetwork.h" // Aurora Sim
+#include "llvograss.h"
+#include "llvotree.h"
// Globals
LLFloaterTools *gFloaterTools = NULL;
@@ -304,6 +306,8 @@ BOOL LLFloaterTools::postBuild()
mSliderDozerForce = getChild("slider force");
// the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here
getChild("slider force")->setValue(log10(gSavedSettings.getF32("LandBrushForce")));
+ // FIRE-6934: Grass and tree selection in build tool
+ mTreeGrassCombo = getChild("tree_grass_combo");
mCostTextBorder = getChild("cost_text_border");
@@ -410,6 +414,9 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mBtnDuplicate(NULL),
mBtnDuplicateInPlace(NULL),
+ // FIRE-6934: Grass and tree selection in build tool
+ mTreeGrassCombo(nullptr),
+
mCheckSticky(NULL),
mCheckCopySelection(NULL),
mCheckCopyCenters(NULL),
@@ -470,6 +477,9 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mCommitCallbackRegistrar.add("BuildTool.Flip", boost::bind(&LLPanelFace::onCommitFlip, _1, _2));
//
+ // FIRE-6934: Grass and tree selection in build tool
+ mCommitCallbackRegistrar.add("BuildTool.TreeGrass", boost::bind(&LLFloaterTools::onSelectTreeGrassCombo, this));
+
mLandImpactsObserver = new LLLandImpactsObserver();
LLViewerParcelMgr::getInstance()->addObserver(mLandImpactsObserver);
}
@@ -917,6 +927,10 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
// Create buttons
BOOL create_visible = (tool == LLToolCompCreate::getInstance());
+ // FIRE-6934: Grass and tree selection in build tool
+ if (mTreeGrassCombo) mTreeGrassCombo->setVisible(create_visible);
+ if (create_visible) buildTreeGrassCombo();
+
mBtnCreate ->setToggleState( tool == LLToolCompCreate::getInstance() );
if (mCheckCopySelection
@@ -1278,6 +1292,9 @@ void LLFloaterTools::setObjectType( LLPCode pcode )
{
LLToolPlacer::setObjectType( pcode );
gSavedSettings.setBOOL("CreateToolCopySelection", FALSE);
+ // FIRE-6934: Grass and tree selection in build tool
+ gFloaterTools->buildTreeGrassCombo();
+ //
gFocusMgr.setMouseCapture(NULL);
}
@@ -2252,3 +2269,93 @@ void LLFloaterTools::onClickExpand()
btnExpand->setImageOverlay("Arrow_Down", btnExpand->getImageOverlayHAlign());
}
}
+
+// FIRE-6934: Grass and tree selection in build tool
+template
+void build_plant_combo(const std::map& list, LLComboBox* combo)
+{
+ if (!combo || list.empty()) return;
+ combo->removeall();
+ typename std::map::const_iterator it = list.begin();
+ typename std::map::const_iterator end = list.end();
+ for ( ; it != end; ++it )
+ {
+ P* plant = (*it).second;
+ if (plant) combo->addSimpleElement(plant->mName, ADD_BOTTOM);
+ }
+}
+
+void LLFloaterTools::buildTreeGrassCombo()
+{
+ if (!mTreeGrassCombo) return;
+
+ // Rebuild the combo with the list we need, then select the last-known use
+ // TODO: rebuilding this list continuously is probably not the best way
+ LLPCode pcode = LLToolPlacer::getObjectType();
+ std::string type = LLStringUtil::null;
+
+ // LL_PCODE_TREE_NEW seems to be "new" as in "dodo"
+ switch (pcode)
+ {
+ case LL_PCODE_LEGACY_TREE:
+ case LL_PCODE_TREE_NEW:
+ build_plant_combo(LLVOTree::sSpeciesTable, mTreeGrassCombo);
+ mTreeGrassCombo->addSimpleElement("Random", ADD_TOP);
+ type = "Tree";
+ break;
+ case LL_PCODE_LEGACY_GRASS:
+ build_plant_combo(LLVOGrass::sSpeciesTable, mTreeGrassCombo);
+ mTreeGrassCombo->addSimpleElement("Random", ADD_TOP);
+ type = "Grass";
+ break;
+ default:
+ mTreeGrassCombo->setEnabled(false);
+ break;
+ }
+
+ // select last selected if exists
+ if (!type.empty())
+ {
+ // Enable the options
+ mTreeGrassCombo->setEnabled(true);
+
+ // Set the last selection, or "Random" (old default) if there isn't one
+ std::string last_selected = gSavedSettings.getString("LastSelected"+type);
+ if (last_selected.empty())
+ {
+ mTreeGrassCombo->selectByValue(LLSD(std::string("Random")));
+ }
+ else
+ {
+ mTreeGrassCombo->selectByValue(LLSD(last_selected));
+ }
+ }
+}
+
+void LLFloaterTools::onSelectTreeGrassCombo()
+{
+ // Save the last-used selection
+ std::string last_selected = mTreeGrassCombo->getValue().asString();
+ LLPCode pcode = LLToolPlacer::getObjectType();
+ std::string type = "";
+
+ switch (pcode)
+ {
+ case LL_PCODE_LEGACY_GRASS:
+ type = "Grass";
+ break;
+ case LL_PCODE_LEGACY_TREE:
+ case LL_PCODE_TREE_NEW:
+ type = "Tree";
+ break;
+ default:
+ break;
+ }
+
+ if (!type.empty())
+ {
+ // Should never be an empty string
+ gSavedSettings.setString("LastSelected"+type, last_selected);
+ }
+}
+//
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 03c9cd8d88..9dc3607506 100755
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -130,6 +130,11 @@ private:
static void setObjectType( LLPCode pcode );
void onClickGridOptions();
+ // FIRE-6934: Grass and tree selection in build tool
+ void buildTreeGrassCombo();
+ void onSelectTreeGrassCombo();
+ //
+
public:
LLButton *mBtnFocus;
LLButton *mBtnMove;
@@ -178,6 +183,9 @@ public:
LLButton *mBtnDuplicate;
LLButton *mBtnDuplicateInPlace;
+ // FIRE-6934: Grass and tree selection in build tool
+ LLComboBox* mTreeGrassCombo;
+
// Create buttons
LLCheckBoxCtrl *mCheckSticky;
LLCheckBoxCtrl *mCheckCopySelection;
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index c069c506bb..e4143f71b7 100755
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -79,6 +79,28 @@ const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
//static
LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE;
+// FIRE-6934: Grass and tree selection in build tool
+template
+U32 get_selected_plant(const std::map& list, const std::string& type, S32 max) // MC
+{
+ if (!type.empty() && !list.empty())
+ {
+ std::string last_selected = gSavedSettings.getString("LastSelected"+type);
+ if (!last_selected.empty())
+ {
+ for (U32 i = 0; i < list.size(); ++i)
+ {
+ if (list.at(i) && list.at(i)->mName == last_selected)
+ {
+ return i;
+ }
+ }
+ }
+ }
+ return rand() % max;
+}
+//
+
LLToolPlacer::LLToolPlacer()
: LLTool( "Create" )
{
@@ -242,13 +264,19 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
case LL_PCODE_LEGACY_GRASS:
// Randomize size of grass patch
scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f));
- state = rand() % LLVOGrass::sMaxGrassSpecies;
+ // FIRE-6934: Grass and tree selection in build tool
+ //state = rand() % LLVOGrass::sMaxGrassSpecies;
+ state = get_selected_plant(LLVOGrass::sSpeciesTable, "Grass", LLVOGrass::sMaxGrassSpecies);
+ //
break;
case LL_PCODE_LEGACY_TREE:
case LL_PCODE_TREE_NEW:
- state = rand() % LLVOTree::sMaxTreeSpecies;
+ // FIRE-6934: Grass and tree selection in build tool
+ //state = rand() % LLVOTree::sMaxTreeSpecies;
+ state = get_selected_plant(LLVOTree::sSpeciesTable, "Tree", LLVOTree::sMaxTreeSpecies);
+ //
break;
case LL_PCODE_SPHERE:
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index 57d939170a..a06329bfc9 100755
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -136,6 +136,8 @@ void LLVOGrass::initClass()
}
F32 F32_val;
LLUUID id;
+ // FIRE-6934: Grass and tree selection in build tool
+ std::string name;
BOOL success = TRUE;
@@ -168,6 +170,12 @@ void LLVOGrass::initClass()
success &= grass_def->getFastAttributeF32(blade_sizey_string, F32_val);
newGrass->mBladeSizeY = F32_val;
+ // FIRE-6934: Grass and tree selection in build tool
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ grass_def->getFastAttributeString(name_string, name);
+ newGrass->mName = name;
+ //
+
if (sSpeciesTable.count(species))
{
LL_INFOS() << "Grass species " << species << " already defined! Duplicate discarded." << LL_ENDL;
@@ -183,9 +191,11 @@ void LLVOGrass::initClass()
if (!success)
{
- std::string name;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- grass_def->getFastAttributeString(name_string, name);
+ // FIRE-6934: Grass and tree selection in build tool
+ //std::string name;
+ //static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ //grass_def->getFastAttributeString(name_string, name);
+ //
LL_WARNS() << "Incomplete definition of grass " << name << LL_ENDL;
}
}
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index f0076cf9af..e390607ab6 100755
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -96,6 +96,9 @@ public:
F32 mBladeSizeX;
F32 mBladeSizeY;
+
+ // FIRE-6934: Grass and tree selection in build tool
+ std::string mName;
};
typedef std::map SpeciesMap;
@@ -122,6 +125,9 @@ private:
F32 mLastHeight; // For cheap update hack
S32 mNumBlades;
+// FIRE-6934: Grass and tree selection in build tool
+public:
+//
static SpeciesMap sSpeciesTable;
};
#endif // LL_VO_GRASS_
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 360dcb3237..6f5634eff1 100755
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -129,6 +129,9 @@ void LLVOTree::initClass()
F32 F32_val;
LLUUID id;
S32 S32_val;
+
+ // FIRE-6934: Grass and tree selection in build tool
+ std::string name;
BOOL success = TRUE;
@@ -232,15 +235,23 @@ void LLVOTree::initClass()
success &= tree_def->getFastAttributeF32(repeat_z_string, F32_val);
newTree->mRepeatTrunkZ = F32_val;
+ // FIRE-6934: Grass and tree selection in build tool
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); // MC
+ tree_def->getFastAttributeString(name_string, name);
+ newTree->mName = name;
+ //
+
sSpeciesTable[species] = newTree;
if (species >= sMaxTreeSpecies) sMaxTreeSpecies = species + 1;
if (!success)
{
- std::string name;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- tree_def->getFastAttributeString(name_string, name);
+ // FIRE-6934: Grass and tree selection in build tool
+ //std::string name;
+ //static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ //tree_def->getFastAttributeString(name_string, name);
+ //
LL_WARNS() << "Incomplete definition of tree " << name << LL_ENDL;
}
}
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index f2b93c40d4..f0a0655603 100755
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -143,6 +143,9 @@ public:
F32 mNoiseMag; // amount of perlin noise to deform by (0 = none)
F32 mTaper; // amount of perlin noise to deform by (0 = none)
F32 mRepeatTrunkZ; // Times to repeat the trunk texture vertically along trunk
+
+ // FIRE-6934: Grass and tree selection in build tool
+ std::string mName; // Designated name in XML
};
static F32 sTreeFactor; // Tree level of detail factor
@@ -182,7 +185,8 @@ protected:
U32 mFrameCount;
typedef std::map SpeciesMap;
- static SpeciesMap sSpeciesTable;
+ // FIRE-6934: Grass and tree selection in build tool
+ //static SpeciesMap sSpeciesTable;
static S32 sLODIndexOffset[4];
static S32 sLODIndexCount[4];
@@ -190,6 +194,11 @@ protected:
static S32 sLODVertexCount[4];
static S32 sLODSlices[4];
static F32 sLODAngles[4];
+
+// FIRE-6934: Grass and tree selection in build tool
+public:
+ static SpeciesMap sSpeciesTable;
+//
};
#endif
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 56d683dfc0..510063d4a3 100755
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -653,6 +653,17 @@
name="checkbox copy rotates"
top_delta="16"
width="134" />
+
+
+
+
+
+
+
+
+
+
+
+