summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llprimitive/llgltfmaterial.cpp4
-rw-r--r--indra/llprimitive/llgltfmaterial.h2
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llfloaterregioninfo.cpp154
-rw-r--r--indra/newview/llfloaterregioninfo.h577
-rw-r--r--indra/newview/llpbrterrainfeatures.cpp198
-rw-r--r--indra/newview/llpbrterrainfeatures.h48
-rwxr-xr-xindra/newview/llviewerregion.cpp43
-rw-r--r--indra/newview/llvlcomposition.cpp610
-rw-r--r--indra/newview/llvlcomposition.h132
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml263
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_terrain_elevation.xml307
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml365
14 files changed, 2047 insertions, 669 deletions
diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp
index 94bc5ef74c..008c72462c 100644
--- a/indra/llprimitive/llgltfmaterial.cpp
+++ b/indra/llprimitive/llgltfmaterial.cpp
@@ -681,7 +681,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
}
}
-void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data)
+void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) const
{
LL_PROFILE_ZONE_SCOPED;
llassert(data.isUndefined());
@@ -690,7 +690,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
- LLUUID& texture_id = mTextureId[i];
+ const LLUUID& texture_id = mTextureId[i];
const LLUUID& override_texture_id = override_mat.mTextureId[i];
if (override_texture_id.notNull() && override_texture_id != texture_id)
{
diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
index 67b22f56e2..e04b6d5eee 100644
--- a/indra/llprimitive/llgltfmaterial.h
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -202,7 +202,7 @@ public:
// Get the given override on this LLGLTFMaterial as LLSD
// override_mat -- the override source data
// data -- output LLSD object (should be passed in empty)
- void getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data);
+ void getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) const;
// For base materials only (i.e. assets). Clears transforms to
// default since they're not supported in assets yet.
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e56534b84d..7568c08430 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -502,6 +502,7 @@ set(viewer_SOURCE_FILES
llpathfindingobject.cpp
llpathfindingobjectlist.cpp
llpathfindingpathtool.cpp
+ llpbrterrainfeatures.cpp
llpersistentnotificationstorage.cpp
llphysicsmotion.cpp
llphysicsshapebuilderutil.cpp
@@ -1148,6 +1149,7 @@ set(viewer_HEADER_FILES
llpathfindingobject.h
llpathfindingobjectlist.h
llpathfindingpathtool.h
+ llpbrterrainfeatures.h
llpersistentnotificationstorage.h
llphysicsmotion.h
llphysicsshapebuilderutil.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c7999fc2e9..3c1f469f82 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9308,6 +9308,17 @@
<key>Value</key>
<real>8.0</real>
</map>
+ <key>RenderTerrainPBRTransformsEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>EXPERIMENTAL: Enable PBR Terrain texture transforms.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderTerrainPBRNormalsEnabled</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 1f84da4b07..4b0e628a7e 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -68,6 +68,7 @@
#include "llnamelistctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
+#include "llpbrterrainfeatures.h"
#include "llregioninfomodel.h"
#include "llscrolllistitem.h"
#include "llsliderctrl.h"
@@ -263,7 +264,16 @@ bool LLFloaterRegionInfo::postBuild()
panel = new LLPanelRegionTerrainInfo;
mInfoPanels.push_back(panel);
- panel->buildFromFile("panel_region_terrain.xml");
+ static LLCachedControl<bool> feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false);
+ static LLCachedControl<bool> feature_pbr_terrain_transforms_enabled(gSavedSettings, "RenderTerrainPBRTransformsEnabled", false);
+ if (!feature_pbr_terrain_transforms_enabled || !feature_pbr_terrain_enabled)
+ {
+ panel->buildFromFile("panel_region_terrain.xml");
+ }
+ else
+ {
+ panel->buildFromFile("panel_region_terrain_texture_transform.xml");
+ }
mTab->addTabPanel(panel);
mEnvironmentPanel = new LLPanelRegionEnvironment;
@@ -554,6 +564,20 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
}
// static
+void LLFloaterRegionInfo::sRefreshFromRegion(LLViewerRegion* region)
+{
+ if (region != gAgent.getRegion()) { return; }
+
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
+ if (!floater) { return; }
+
+ if (floater->getVisible() && region == gAgent.getRegion())
+ {
+ floater->refreshFromRegion(region);
+ }
+}
+
+// static
LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate()
{
LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
@@ -825,6 +849,13 @@ void LLPanelRegionInfo::initCtrl(const std::string& name)
getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this));
}
+template<typename CTRL>
+void LLPanelRegionInfo::initAndSetCtrl(CTRL*& ctrl, const std::string& name)
+{
+ initCtrl(name);
+ ctrl = findChild<CTRL>(name);
+}
+
void LLPanelRegionInfo::onClickManageTelehub()
{
LLFloaterReg::hideInstance("region_info");
@@ -1494,11 +1525,17 @@ LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo()
const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures();
for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
{
+ mTextureDetailCtrl[i] = nullptr;
+ mMaterialDetailCtrl[i] = nullptr;
+
mLastSetTextures[i] = default_textures[i];
- }
- for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
- {
mLastSetMaterials[i] = BLANK_MATERIAL_ASSET_ID;
+
+ mMaterialScaleUCtrl[i] = nullptr;
+ mMaterialScaleVCtrl[i] = nullptr;
+ mMaterialRotationCtrl[i] = nullptr;
+ mMaterialOffsetUCtrl[i] = nullptr;
+ mMaterialOffsetVCtrl[i] = nullptr;
}
}
@@ -1517,22 +1554,21 @@ bool LLPanelRegionTerrainInfo::postBuild()
std::string buffer;
- for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
- {
- buffer = llformat("texture_detail_%d", i);
- initCtrl(buffer);
- mTextureDetailCtrl[i] = findChild<LLTextureCtrl>(buffer);
- if (mTextureDetailCtrl)
+ for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ initAndSetCtrl(mTextureDetailCtrl[i], llformat("texture_detail_%d", i));
+ if (mTextureDetailCtrl[i])
{
mTextureDetailCtrl[i]->setBakeTextureEnabled(false);
}
- }
- for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
- {
- buffer = llformat("material_detail_%d", i);
- initCtrl(buffer);
- mMaterialDetailCtrl[i] = findChild<LLTextureCtrl>(buffer);
- }
+ initAndSetCtrl(mMaterialDetailCtrl[i], llformat("material_detail_%d", i));
+
+ initAndSetCtrl(mMaterialScaleUCtrl[i], llformat("terrain%dScaleU", i));
+ initAndSetCtrl(mMaterialScaleVCtrl[i], llformat("terrain%dScaleV", i));
+ initAndSetCtrl(mMaterialRotationCtrl[i], llformat("terrain%dRotation", i));
+ initAndSetCtrl(mMaterialOffsetUCtrl[i], llformat("terrain%dOffsetU", i));
+ initAndSetCtrl(mMaterialOffsetVCtrl[i], llformat("terrain%dOffsetV", i));
+ }
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
@@ -1583,6 +1619,17 @@ void LLPanelRegionTerrainInfo::updateForMaterialType()
}
}
+ // Toggle visibility of terrain tabs
+ LLTabContainer* terrain_tabs = findChild<LLTabContainer>("terrain_tabs");
+ if (terrain_tabs)
+ {
+ LLPanel* pbr_terrain_repeats_tab = findChild<LLPanel>("terrain_transform_panel");
+ if (pbr_terrain_repeats_tab)
+ {
+ terrain_tabs->setTabVisibility(pbr_terrain_repeats_tab, show_material_controls);
+ }
+ }
+
// Toggle visibility of labels
LLUICtrl* texture_label = findChild<LLUICtrl>("detail_texture_text");
if (texture_label) { texture_label->setVisible(show_texture_controls); }
@@ -1711,6 +1758,21 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
}
}
+ for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ if (!mMaterialScaleUCtrl[i] || !mMaterialScaleVCtrl[i] || !mMaterialRotationCtrl[i] || !mMaterialOffsetUCtrl[i] || !mMaterialOffsetVCtrl[i]) { continue; }
+ const LLGLTFMaterial* mat_override = compp->getMaterialOverride(i);
+ if (!mat_override) { mat_override = &LLGLTFMaterial::sDefault; }
+
+ // Assume all texture transforms have the same value
+ const LLGLTFMaterial::TextureTransform& transform = mat_override->mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR];
+ mMaterialScaleUCtrl[i]->setValue(transform.mScale.mV[VX]);
+ mMaterialScaleVCtrl[i]->setValue(transform.mScale.mV[VY]);
+ mMaterialRotationCtrl[i]->setValue(transform.mRotation * RAD_TO_DEG);
+ mMaterialOffsetUCtrl[i]->setValue(transform.mOffset.mV[VX]);
+ mMaterialOffsetVCtrl[i]->setValue(transform.mOffset.mV[VY]);
+ }
+
std::string buffer;
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
@@ -1725,7 +1787,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
LL_DEBUGS() << "no region set" << LL_ENDL;
getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
}
-
+
// Update visibility of terrain swatches, etc
refresh();
@@ -1740,7 +1802,14 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
// virtual
bool LLPanelRegionTerrainInfo::sendUpdate()
{
- LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL;
+ LL_INFOS() << __FUNCTION__ << LL_ENDL;
+
+ LLUICtrl* apply_btn = getChild<LLUICtrl>("apply_btn");
+ if (apply_btn && !apply_btn->getEnabled())
+ {
+ LL_WARNS() << "Duplicate update, ignored" << LL_ENDL;
+ return false;
+ }
// Make sure user hasn't chosen wacky textures.
if (!validateTextureSizes())
@@ -1841,7 +1910,52 @@ bool LLPanelRegionTerrainInfo::sendUpdate()
sendEstateOwnerMessage(msg, "texturecommit", invoice, strings);
- return true;
+ // ========================================
+ // POST to ModifyRegion endpoint, if enabled
+
+ static LLCachedControl<bool> feature_pbr_terrain_transforms_enabled(gSavedSettings, "RenderTerrainPBRTransformsEnabled", false);
+ if (material_type == LLTerrainMaterials::Type::PBR && feature_pbr_terrain_transforms_enabled)
+ {
+ LLTerrainMaterials composition;
+ for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ LLPointer<LLGLTFMaterial> mat_override = new LLGLTFMaterial();
+
+ const bool transform_controls_valid = mMaterialScaleUCtrl[i] && mMaterialScaleVCtrl[i] && mMaterialRotationCtrl[i] && mMaterialOffsetUCtrl[i] && mMaterialOffsetVCtrl[i];
+ if (transform_controls_valid)
+ {
+ // Set texture transforms for all texture infos to the same value,
+ // because the PBR terrain shader doesn't currently support
+ // different transforms per texture info. See also
+ // LLDrawPoolTerrain::renderFullShaderPBR .
+ for (U32 tt = 0; tt < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++tt)
+ {
+ LLGLTFMaterial::TextureTransform& transform = mat_override->mTextureTransform[tt];
+ transform.mScale.mV[VX] = mMaterialScaleUCtrl[i]->getValue().asReal();
+ transform.mScale.mV[VY] = mMaterialScaleVCtrl[i]->getValue().asReal();
+ transform.mRotation = mMaterialRotationCtrl[i]->getValue().asReal() * DEG_TO_RAD;
+ transform.mOffset.mV[VX] = mMaterialOffsetUCtrl[i]->getValue().asReal();
+ transform.mOffset.mV[VY] = mMaterialOffsetVCtrl[i]->getValue().asReal();
+ }
+ }
+
+ if (*mat_override == LLGLTFMaterial::sDefault) { mat_override = nullptr; }
+ composition.setMaterialOverride(i, mat_override.get());
+ }
+
+ // queueModify leads to a few messages being sent back and forth:
+ // viewer: POST ModifyRegion
+ // simulator: RegionHandshake
+ // viewer: GET ModifyRegion
+ LLViewerRegion* region = gAgent.getRegion();
+ llassert(region);
+ if (region)
+ {
+ LLPBRTerrainFeatures::queueModify(*region, composition);
+ }
+ }
+
+ return true;
}
bool LLPanelRegionTerrainInfo::callbackTextureHeights(const LLSD& notification, const LLSD& response)
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 4b81a26210..81167efdad 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfloaterregioninfo.h
* @author Aaron Brashears
* @brief Declaration of the region info and controls floater and panels.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -73,58 +73,59 @@ class LLEventTimer;
class LLFloaterRegionInfo : public LLFloater
{
- friend class LLFloaterReg;
+ friend class LLFloaterReg;
public:
- void onOpen(const LLSD& key) override;
- void onClose(bool app_quitting) override;
+ void onOpen(const LLSD& key) override;
+ void onClose(bool app_quitting) override;
bool postBuild() override;
- static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
-
- // get and process region info if necessary.
- static void processRegionInfo(LLMessageSystem* msg);
-
- static const LLUUID& getLastInvoice() { return sRequestInvoice; }
- static void nextInvoice() { sRequestInvoice.generate(); }
- //static S32 getSerial() { return sRequestSerial; }
- //static void incrementSerial() { sRequestSerial++; }
-
- static LLPanelEstateInfo* getPanelEstate();
- static LLPanelEstateAccess* getPanelAccess();
- static LLPanelEstateCovenant* getPanelCovenant();
- static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
- static LLPanelRegionExperiences* getPanelExperiences();
- static LLPanelRegionGeneralInfo* getPanelGeneral();
- static LLPanelRegionEnvironment* getPanelEnvironment();
-
- // from LLPanel
- void refresh() override;
-
- void onRegionChanged();
- void requestRegionInfo();
- void enableTopButtons();
- void disableTopButtons();
+ static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
+
+ // get and process region info if necessary.
+ static void processRegionInfo(LLMessageSystem* msg);
+ static void sRefreshFromRegion(LLViewerRegion* region);
+
+ static const LLUUID& getLastInvoice() { return sRequestInvoice; }
+ static void nextInvoice() { sRequestInvoice.generate(); }
+ //static S32 getSerial() { return sRequestSerial; }
+ //static void incrementSerial() { sRequestSerial++; }
+
+ static LLPanelEstateInfo* getPanelEstate();
+ static LLPanelEstateAccess* getPanelAccess();
+ static LLPanelEstateCovenant* getPanelCovenant();
+ static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
+ static LLPanelRegionExperiences* getPanelExperiences();
+ static LLPanelRegionGeneralInfo* getPanelGeneral();
+ static LLPanelRegionEnvironment* getPanelEnvironment();
+
+ // from LLPanel
+ void refresh() override;
+
+ void onRegionChanged();
+ void requestRegionInfo();
+ void enableTopButtons();
+ void disableTopButtons();
private:
-
- LLFloaterRegionInfo(const LLSD& seed);
- ~LLFloaterRegionInfo();
+
+ LLFloaterRegionInfo(const LLSD& seed);
+ ~LLFloaterRegionInfo();
protected:
- void onTabSelected(const LLSD& param);
- void disableTabCtrls();
- void refreshFromRegion(LLViewerRegion* region);
- void onGodLevelChange(U8 god_level);
-
- // member data
- LLTabContainer* mTab;
- typedef std::vector<LLPanelRegionInfo*> info_panels_t;
- info_panels_t mInfoPanels;
+ void onTabSelected(const LLSD& param);
+ void disableTabCtrls();
+ void refreshFromRegion(LLViewerRegion* region);
+ void onGodLevelChange(U8 god_level);
+
+ // member data
+ LLTabContainer* mTab;
+ typedef std::vector<LLPanelRegionInfo*> info_panels_t;
+ info_panels_t mInfoPanels;
LLPanelRegionEnvironment *mEnvironmentPanel;
- //static S32 sRequestSerial; // serial # of last EstateOwnerRequest
- static LLUUID sRequestInvoice;
+ //static S32 sRequestSerial; // serial # of last EstateOwnerRequest
+ static LLUUID sRequestInvoice;
private:
LLAgent::god_level_change_slot_t mGodLevelChangeSlot;
@@ -136,42 +137,43 @@ private:
class LLPanelRegionInfo : public LLPanel
{
public:
- LLPanelRegionInfo();
-
- void onBtnSet();
- void onChangeChildCtrl(LLUICtrl* ctrl);
- void onChangeAnything();
- static void onChangeText(LLLineEditor* caller, void* user_data);
-
- virtual bool refreshFromRegion(LLViewerRegion* region);
- virtual bool estateUpdate(LLMessageSystem* msg) { return true; }
-
+ LLPanelRegionInfo();
+
+ void onBtnSet();
+ void onChangeChildCtrl(LLUICtrl* ctrl);
+ void onChangeAnything();
+ static void onChangeText(LLLineEditor* caller, void* user_data);
+
+ virtual bool refreshFromRegion(LLViewerRegion* region);
+ virtual bool estateUpdate(LLMessageSystem* msg) { return true; }
+
bool postBuild() override;
- virtual void updateChild(LLUICtrl* child_ctrl);
-
- void enableButton(const std::string& btn_name, bool enable = true);
- void disableButton(const std::string& btn_name);
-
- void onClickManageTelehub();
-
+ virtual void updateChild(LLUICtrl* child_ctrl);
+
+ void enableButton(const std::string& btn_name, bool enable = true);
+ void disableButton(const std::string& btn_name);
+
+ void onClickManageTelehub();
+
protected:
- void initCtrl(const std::string& name);
-
- // Returns true if update sent and apply button should be
- // disabled.
- virtual bool sendUpdate() { return true; }
-
- typedef std::vector<std::string> strings_t;
- //typedef std::vector<U32> integers_t;
- void sendEstateOwnerMessage(
- LLMessageSystem* msg,
- const std::string& request,
- const LLUUID& invoice,
- const strings_t& strings);
-
-
- // member data
- LLHost mHost;
+ void initCtrl(const std::string& name);
+ template<typename CTRL> void initAndSetCtrl(CTRL*& ctrl, const std::string& name);
+
+ // Returns true if update sent and apply button should be
+ // disabled.
+ virtual bool sendUpdate() { return true; }
+
+ typedef std::vector<std::string> strings_t;
+ //typedef std::vector<U32> integers_t;
+ void sendEstateOwnerMessage(
+ LLMessageSystem* msg,
+ const std::string& request,
+ const LLUUID& invoice,
+ const strings_t& strings);
+
+
+ // member data
+ LLHost mHost;
};
/////////////////////////////////////////////////////////////////////////////
@@ -180,30 +182,30 @@ protected:
class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
{
-
+
public:
- LLPanelRegionGeneralInfo()
- : LLPanelRegionInfo() {}
- ~LLPanelRegionGeneralInfo() {}
-
- bool refreshFromRegion(LLViewerRegion* region) override;
-
+ LLPanelRegionGeneralInfo()
+ : LLPanelRegionInfo() {}
+ ~LLPanelRegionGeneralInfo() {}
+
+ bool refreshFromRegion(LLViewerRegion* region) override;
+
bool postBuild() override;
-
- void onBtnSet();
- void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
+
+ void onBtnSet();
+ void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
protected:
- bool sendUpdate() override;
- void onClickKick();
- void onKickCommit(const uuid_vec_t& ids);
- static void onClickKickAll(void* userdata);
- bool onKickAllCommit(const LLSD& notification, const LLSD& response);
- static void onClickMessage(void* userdata);
- bool onMessageCommit(const LLSD& notification, const LLSD& response);
- bool onChangeObjectBonus(const LLSD& notification, const LLSD& response);
+ bool sendUpdate() override;
+ void onClickKick();
+ void onKickCommit(const uuid_vec_t& ids);
+ static void onClickKickAll(void* userdata);
+ bool onKickAllCommit(const LLSD& notification, const LLSD& response);
+ static void onClickMessage(void* userdata);
+ bool onMessageCommit(const LLSD& notification, const LLSD& response);
+ bool onChangeObjectBonus(const LLSD& notification, const LLSD& response);
- F32 mObjBonusFactor;
+ F32 mObjBonusFactor;
};
@@ -212,73 +214,80 @@ protected:
class LLPanelRegionDebugInfo : public LLPanelRegionInfo
{
public:
- LLPanelRegionDebugInfo()
- : LLPanelRegionInfo(), mTargetAvatar() {}
- ~LLPanelRegionDebugInfo() {}
+ LLPanelRegionDebugInfo()
+ : LLPanelRegionInfo(), mTargetAvatar() {}
+ ~LLPanelRegionDebugInfo() {}
bool postBuild() override;
-
- bool refreshFromRegion(LLViewerRegion* region) override;
-
+
+ bool refreshFromRegion(LLViewerRegion* region) override;
+
protected:
bool sendUpdate() override;
- void onClickChooseAvatar();
- void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
- static void onClickReturn(void *);
- bool callbackReturn(const LLSD& notification, const LLSD& response);
- static void onClickTopColliders(void*);
- static void onClickTopScripts(void*);
- static void onClickRestart(void* data);
- bool callbackRestart(const LLSD& notification, const LLSD& response);
- static void onClickCancelRestart(void* data);
- static void onClickDebugConsole(void* data);
-
+ void onClickChooseAvatar();
+ void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
+ static void onClickReturn(void *);
+ bool callbackReturn(const LLSD& notification, const LLSD& response);
+ static void onClickTopColliders(void*);
+ static void onClickTopScripts(void*);
+ static void onClickRestart(void* data);
+ bool callbackRestart(const LLSD& notification, const LLSD& response);
+ static void onClickCancelRestart(void* data);
+ static void onClickDebugConsole(void* data);
+
private:
- LLUUID mTargetAvatar;
+ LLUUID mTargetAvatar;
};
/////////////////////////////////////////////////////////////////////////////
class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
{
- LOG_CLASS(LLPanelRegionTerrainInfo);
+ LOG_CLASS(LLPanelRegionTerrainInfo);
public:
- LLPanelRegionTerrainInfo();
- ~LLPanelRegionTerrainInfo() {}
-
+ LLPanelRegionTerrainInfo();
+ ~LLPanelRegionTerrainInfo() {}
+
bool postBuild() override;
-
+
bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator
- void setEnvControls(bool available); // Whether environment settings are available for this region
+ void setEnvControls(bool available); // Whether environment settings are available for this region
bool validateTextureSizes();
bool validateMaterials();
bool validateTextureHeights();
- //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
-
+ //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
+
void onSelectMaterialType();
void updateForMaterialType();
- static void onClickDownloadRaw(void*);
- static void onClickUploadRaw(void*);
- static void onClickBakeTerrain(void*);
- bool callbackBakeTerrain(const LLSD& notification, const LLSD& response);
- bool callbackTextureHeights(const LLSD& notification, const LLSD& response);
+ static void onClickDownloadRaw(void*);
+ static void onClickUploadRaw(void*);
+ static void onClickBakeTerrain(void*);
+ bool callbackBakeTerrain(const LLSD& notification, const LLSD& response);
+ bool callbackTextureHeights(const LLSD& notification, const LLSD& response);
protected:
bool sendUpdate() override;
private:
- bool mConfirmedTextureHeights;
- bool mAskedTextureHeights;
+ bool mConfirmedTextureHeights;
+ bool mAskedTextureHeights;
LLCheckBoxCtrl* mMaterialTypeCtrl = nullptr;
LLTextureCtrl* mTextureDetailCtrl[LLTerrainMaterials::ASSET_COUNT];
LLTextureCtrl* mMaterialDetailCtrl[LLTerrainMaterials::ASSET_COUNT];
+
LLUUID mLastSetTextures[LLTerrainMaterials::ASSET_COUNT];
LLUUID mLastSetMaterials[LLTerrainMaterials::ASSET_COUNT];
+
+ LLSpinCtrl* mMaterialScaleUCtrl[LLTerrainMaterials::ASSET_COUNT];
+ LLSpinCtrl* mMaterialScaleVCtrl[LLTerrainMaterials::ASSET_COUNT];
+ LLSpinCtrl* mMaterialRotationCtrl[LLTerrainMaterials::ASSET_COUNT];
+ LLSpinCtrl* mMaterialOffsetUCtrl[LLTerrainMaterials::ASSET_COUNT];
+ LLSpinCtrl* mMaterialOffsetVCtrl[LLTerrainMaterials::ASSET_COUNT];
};
/////////////////////////////////////////////////////////////////////////////
@@ -286,59 +295,59 @@ private:
class LLPanelEstateInfo : public LLPanelRegionInfo
{
public:
- static void initDispatch(LLDispatcher& dispatch);
-
- void onChangeFixedSun();
- void onChangeUseGlobalTime();
- void onChangeAccessOverride();
-
- void onClickEditSky();
- void onClickEditSkyHelp();
- void onClickEditDayCycle();
- void onClickEditDayCycleHelp();
-
- void onClickKickUser();
-
-
- bool kickUserConfirm(const LLSD& notification, const LLSD& response);
-
- void onKickUserCommit(const uuid_vec_t& ids);
- static void onClickMessageEstate(void* data);
- bool onMessageCommit(const LLSD& notification, const LLSD& response);
-
- LLPanelEstateInfo();
- ~LLPanelEstateInfo() {}
-
- void updateControls(LLViewerRegion* region);
-
- static void updateEstateName(const std::string& name);
- static void updateEstateOwnerName(const std::string& name);
-
- bool refreshFromRegion(LLViewerRegion* region) override;
- bool estateUpdate(LLMessageSystem* msg) override;
-
+ static void initDispatch(LLDispatcher& dispatch);
+
+ void onChangeFixedSun();
+ void onChangeUseGlobalTime();
+ void onChangeAccessOverride();
+
+ void onClickEditSky();
+ void onClickEditSkyHelp();
+ void onClickEditDayCycle();
+ void onClickEditDayCycleHelp();
+
+ void onClickKickUser();
+
+
+ bool kickUserConfirm(const LLSD& notification, const LLSD& response);
+
+ void onKickUserCommit(const uuid_vec_t& ids);
+ static void onClickMessageEstate(void* data);
+ bool onMessageCommit(const LLSD& notification, const LLSD& response);
+
+ LLPanelEstateInfo();
+ ~LLPanelEstateInfo() {}
+
+ void updateControls(LLViewerRegion* region);
+
+ static void updateEstateName(const std::string& name);
+ static void updateEstateOwnerName(const std::string& name);
+
+ bool refreshFromRegion(LLViewerRegion* region) override;
+ bool estateUpdate(LLMessageSystem* msg) override;
+
bool postBuild() override;
- void updateChild(LLUICtrl* child_ctrl) override;
- void refresh() override;
+ void updateChild(LLUICtrl* child_ctrl) override;
+ void refresh() override;
- void refreshFromEstate();
-
- static bool isLindenEstate();
-
- const std::string getOwnerName() const;
- void setOwnerName(const std::string& name);
+ void refreshFromEstate();
+
+ static bool isLindenEstate();
+
+ const std::string getOwnerName() const;
+ void setOwnerName(const std::string& name);
protected:
bool sendUpdate() override;
- // confirmation dialog callback
- bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response);
-
- void commitEstateAccess();
- void commitEstateManagers();
+ // confirmation dialog callback
+ bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response);
- bool checkSunHourSlider(LLUICtrl* child_ctrl);
+ void commitEstateAccess();
+ void commitEstateManagers();
+
+ bool checkSunHourSlider(LLUICtrl* child_ctrl);
- U32 mEstateID;
+ U32 mEstateID;
};
/////////////////////////////////////////////////////////////////////////////
@@ -346,59 +355,59 @@ protected:
class LLPanelEstateCovenant : public LLPanelRegionInfo
{
public:
- LLPanelEstateCovenant();
- ~LLPanelEstateCovenant() {}
-
+ LLPanelEstateCovenant();
+ ~LLPanelEstateCovenant() {}
+
bool postBuild() override;
- void updateChild(LLUICtrl* child_ctrl) override;
- bool refreshFromRegion(LLViewerRegion* region) override;
- bool estateUpdate(LLMessageSystem* msg) override;
-
- // LLView overrides
- bool handleDragAndDrop(S32 x, S32 y, MASK mask,
- bool drop, EDragAndDropType cargo_type,
- void *cargo_data, EAcceptance *accept,
- std::string& tooltip_msg) override;
- static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response);
- static void resetCovenantID(void* userdata);
- static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response);
- void sendChangeCovenantID(const LLUUID &asset_id);
- void loadInvItem(LLInventoryItem *itemp);
- static void onLoadComplete(const LLUUID& asset_uuid,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status);
-
- // Accessor functions
- static void updateCovenantText(const std::string& string, const LLUUID& asset_id);
- static void updateEstateName(const std::string& name);
- static void updateLastModified(const std::string& text);
- static void updateEstateOwnerName(const std::string& name);
-
- const LLUUID& getCovenantID() const { return mCovenantID; }
- void setCovenantID(const LLUUID& id) { mCovenantID = id; }
- std::string getEstateName() const;
- void setEstateName(const std::string& name);
- std::string getOwnerName() const;
- void setOwnerName(const std::string& name);
- void setCovenantTextEditor(const std::string& text);
-
- typedef enum e_asset_status
- {
- ASSET_ERROR,
- ASSET_UNLOADED,
- ASSET_LOADING,
- ASSET_LOADED
- } EAssetStatus;
+ void updateChild(LLUICtrl* child_ctrl) override;
+ bool refreshFromRegion(LLViewerRegion* region) override;
+ bool estateUpdate(LLMessageSystem* msg) override;
+
+ // LLView overrides
+ bool handleDragAndDrop(S32 x, S32 y, MASK mask,
+ bool drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg) override;
+ static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response);
+ static void resetCovenantID(void* userdata);
+ static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response);
+ void sendChangeCovenantID(const LLUUID &asset_id);
+ void loadInvItem(LLInventoryItem *itemp);
+ static void onLoadComplete(const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status);
+
+ // Accessor functions
+ static void updateCovenantText(const std::string& string, const LLUUID& asset_id);
+ static void updateEstateName(const std::string& name);
+ static void updateLastModified(const std::string& text);
+ static void updateEstateOwnerName(const std::string& name);
+
+ const LLUUID& getCovenantID() const { return mCovenantID; }
+ void setCovenantID(const LLUUID& id) { mCovenantID = id; }
+ std::string getEstateName() const;
+ void setEstateName(const std::string& name);
+ std::string getOwnerName() const;
+ void setOwnerName(const std::string& name);
+ void setCovenantTextEditor(const std::string& text);
+
+ typedef enum e_asset_status
+ {
+ ASSET_ERROR,
+ ASSET_UNLOADED,
+ ASSET_LOADING,
+ ASSET_LOADED
+ } EAssetStatus;
protected:
bool sendUpdate() override;
- LLTextBox* mEstateNameText;
- LLTextBox* mEstateOwnerText;
- LLTextBox* mLastModifiedText;
- // CovenantID from sim
- LLUUID mCovenantID;
- LLViewerTextEditor* mEditor;
- EAssetStatus mAssetStatus;
+ LLTextBox* mEstateNameText;
+ LLTextBox* mEstateOwnerText;
+ LLTextBox* mLastModifiedText;
+ // CovenantID from sim
+ LLUUID mCovenantID;
+ LLViewerTextEditor* mEditor;
+ EAssetStatus mAssetStatus;
};
/////////////////////////////////////////////////////////////////////////////
@@ -409,96 +418,96 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
LOG_CLASS(LLPanelRegionExperiences);
public:
- LLPanelRegionExperiences(){}
+ LLPanelRegionExperiences(){}
bool postBuild() override;
+
+ static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
+ static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
- static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
- static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
-
- static void infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content);
- bool refreshFromRegion(LLViewerRegion* region) override;
- void sendPurchaseRequest()const;
- void processResponse( const LLSD& content );
+ static void infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content);
+ bool refreshFromRegion(LLViewerRegion* region) override;
+ void sendPurchaseRequest()const;
+ void processResponse( const LLSD& content );
protected:
bool sendUpdate() override;
private:
- void refreshRegionExperiences();
+ void refreshRegionExperiences();
static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap);
- LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id);
- static LLSD addIds( LLPanelExperienceListEditor* panel );
+ LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id);
+ static LLSD addIds( LLPanelExperienceListEditor* panel );
- void itemChanged(U32 event_type, const LLUUID& id);
+ void itemChanged(U32 event_type, const LLUUID& id);
- LLPanelExperienceListEditor* mTrusted;
- LLPanelExperienceListEditor* mAllowed;
- LLPanelExperienceListEditor* mBlocked;
- LLUUID mDefaultExperience;
+ LLPanelExperienceListEditor* mTrusted;
+ LLPanelExperienceListEditor* mAllowed;
+ LLPanelExperienceListEditor* mBlocked;
+ LLUUID mDefaultExperience;
};
class LLPanelEstateAccess : public LLPanelRegionInfo
{
- LOG_CLASS(LLPanelEstateAccess);
+ LOG_CLASS(LLPanelEstateAccess);
public:
- LLPanelEstateAccess();
+ LLPanelEstateAccess();
bool postBuild() override;
- void updateChild(LLUICtrl* child_ctrl) override;
+ void updateChild(LLUICtrl* child_ctrl) override;
- void updateControls(LLViewerRegion* region);
- void updateLists();
+ void updateControls(LLViewerRegion* region);
+ void updateLists();
- void setPendingUpdate(bool pending) { mPendingUpdate = pending; }
- bool getPendingUpdate() { return mPendingUpdate; }
+ void setPendingUpdate(bool pending) { mPendingUpdate = pending; }
+ bool getPendingUpdate() { return mPendingUpdate; }
- bool refreshFromRegion(LLViewerRegion* region) override;
+ bool refreshFromRegion(LLViewerRegion* region) override;
private:
- void onClickAddAllowedAgent();
- void onClickRemoveAllowedAgent();
- void onClickCopyAllowedList();
- void onClickAddAllowedGroup();
- void onClickRemoveAllowedGroup();
- void onClickCopyAllowedGroupList();
- void onClickAddBannedAgent();
- void onClickRemoveBannedAgent();
+ void onClickAddAllowedAgent();
+ void onClickRemoveAllowedAgent();
+ void onClickCopyAllowedList();
+ void onClickAddAllowedGroup();
+ void onClickRemoveAllowedGroup();
+ void onClickCopyAllowedGroupList();
+ void onClickAddBannedAgent();
+ void onClickRemoveBannedAgent();
void onClickCopyBannedList();
- void onClickAddEstateManager();
- void onClickRemoveEstateManager();
- void onAllowedSearchEdit(const std::string& search_string);
- void onAllowedGroupsSearchEdit(const std::string& search_string);
- void onBannedSearchEdit(const std::string& search_string);
-
- // Group picker callback is different, can't use core methods below
- bool addAllowedGroup(const LLSD& notification, const LLSD& response);
- void addAllowedGroup2(LLUUID id);
+ void onClickAddEstateManager();
+ void onClickRemoveEstateManager();
+ void onAllowedSearchEdit(const std::string& search_string);
+ void onAllowedGroupsSearchEdit(const std::string& search_string);
+ void onBannedSearchEdit(const std::string& search_string);
+
+ // Group picker callback is different, can't use core methods below
+ bool addAllowedGroup(const LLSD& notification, const LLSD& response);
+ void addAllowedGroup2(LLUUID id);
- // Core methods for all above add/remove button clicks
- static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
- static bool accessAddCore2(const LLSD& notification, const LLSD& response);
- static void accessAddCore3(const uuid_vec_t& ids, std::vector<LLAvatarName> names, void* data);
+ // Core methods for all above add/remove button clicks
+ static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
+ static bool accessAddCore2(const LLSD& notification, const LLSD& response);
+ static void accessAddCore3(const uuid_vec_t& ids, std::vector<LLAvatarName> names, void* data);
- static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name);
- static bool accessRemoveCore2(const LLSD& notification, const LLSD& response);
+ static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name);
+ static bool accessRemoveCore2(const LLSD& notification, const LLSD& response);
- // used for both add and remove operations
- static bool accessCoreConfirm(const LLSD& notification, const LLSD& response);
+ // used for both add and remove operations
+ static bool accessCoreConfirm(const LLSD& notification, const LLSD& response);
- // Send the actual EstateOwnerRequest "estateaccessdelta" message
- static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
+ // Send the actual EstateOwnerRequest "estateaccessdelta" message
+ static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
- static void requestEstateGetAccessCoro(std::string url);
+ static void requestEstateGetAccessCoro(std::string url);
- void searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string);
- void copyListToClipboard(std::string list_name);
+ void searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string);
+ void copyListToClipboard(std::string list_name);
- bool mPendingUpdate;
- bool mCtrlsEnabled;
+ bool mPendingUpdate;
+ bool mCtrlsEnabled;
};
#endif
diff --git a/indra/newview/llpbrterrainfeatures.cpp b/indra/newview/llpbrterrainfeatures.cpp
new file mode 100644
index 0000000000..87720395f4
--- /dev/null
+++ b/indra/newview/llpbrterrainfeatures.cpp
@@ -0,0 +1,198 @@
+/**
+ * @file llpbrterrainfeatures.cpp
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpbrterrainfeatures.h"
+
+#include "llappviewer.h"
+#include "llgltfmaterial.h"
+#include "llviewerregion.h"
+#include "llvlcomposition.h"
+
+LLPBRTerrainFeatures gPBRTerrainFeatures;
+
+// static
+void LLPBRTerrainFeatures::queueQuery(LLViewerRegion& region, void(*done_callback)(LLUUID, bool, const LLModifyRegion&))
+{
+ llassert(on_main_thread());
+ llassert(LLCoros::on_main_coro());
+
+ LLUUID region_id = region.getRegionID();
+
+ LLCoros::instance().launch("queryRegionCoro",
+ std::bind(&LLPBRTerrainFeatures::queryRegionCoro,
+ region.getCapability("ModifyRegion"),
+ region_id,
+ done_callback));
+}
+
+// static
+void LLPBRTerrainFeatures::queueModify(LLViewerRegion& region, const LLModifyRegion& composition)
+{
+ llassert(on_main_thread());
+ llassert(LLCoros::on_main_coro());
+
+ LLSD updates = LLSD::emptyMap();
+
+ LLSD override_updates = LLSD::emptyArray();
+ for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ const LLGLTFMaterial* material_override = composition.getMaterialOverride(i);
+ LLSD override_update;
+ if (material_override)
+ {
+ LLGLTFMaterial::sDefault.getOverrideLLSD(*material_override, override_update);
+ }
+ else
+ {
+ override_update = LLSD::emptyMap();
+ }
+ override_updates.append(override_update);
+ }
+ updates["overrides"] = override_updates;
+
+ LLCoros::instance().launch("modifyRegionCoro",
+ std::bind(&LLPBRTerrainFeatures::modifyRegionCoro,
+ region.getCapability("ModifyRegion"), // TODO: May actually need a cap for this
+ updates,
+ nullptr));
+}
+
+// static
+void LLPBRTerrainFeatures::queryRegionCoro(std::string cap_url, LLUUID region_id, void(*done_callback)(LLUUID, bool, const LLModifyRegion&) )
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("queryRegionCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders;
+
+ httpOpts->setFollowRedirects(true);
+
+ LL_DEBUGS("GLTF") << "Querying features via ModifyRegion endpoint" << LL_ENDL;
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ bool success = true;
+ if (!status || !result["success"].asBoolean())
+ {
+ if (result["message"].isUndefined())
+ {
+ LL_WARNS("PBRTerrain") << "Failed to query PBR terrain features." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("PBRTerrain") << "Failed to query PBR terrain features: " << result["message"] << LL_ENDL;
+ }
+ success = false;
+ }
+
+ LLTerrainMaterials* composition = new LLTerrainMaterials();
+
+ if (success)
+ {
+ const LLSD& overrides = result["overrides"];
+ if (!overrides.isArray() || overrides.size() < LLTerrainMaterials::ASSET_COUNT)
+ {
+ LL_WARNS("PBRTerrain") << "Invalid composition format: Missing/invalid overrides" << LL_ENDL;
+ success = false;
+ }
+ else
+ {
+ for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ const LLSD& override_llsd = overrides[i];
+ LLPointer<LLGLTFMaterial> material_override = new LLGLTFMaterial();
+ material_override->applyOverrideLLSD(override_llsd);
+ if (*material_override == LLGLTFMaterial::sDefault)
+ {
+ material_override = nullptr;
+ }
+ composition->setMaterialOverride(i, material_override.get());
+ }
+ }
+ }
+
+ if (done_callback)
+ {
+ LLAppViewer::instance()->postToMainCoro([=]()
+ {
+ done_callback(region_id, success, *composition);
+ delete composition;
+ });
+ }
+ else
+ {
+ delete composition;
+ }
+}
+
+// static
+void LLPBRTerrainFeatures::modifyRegionCoro(std::string cap_url, LLSD updates, void(*done_callback)(bool) )
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("modifyRegionCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders;
+
+ httpOpts->setFollowRedirects(true);
+
+ LL_DEBUGS("GLTF") << "Applying features via ModifyRegion endpoint: " << updates << LL_ENDL;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, updates, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ bool success = true;
+ if (!status || !result["success"].asBoolean())
+ {
+ if (result["message"].isUndefined())
+ {
+ LL_WARNS("PBRTerrain") << "Failed to modify PBR terrain features." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("PBRTerrain") << "Failed to modify PBR terrain features: " << result["message"] << LL_ENDL;
+ }
+ success = false;
+ }
+
+ if (done_callback)
+ {
+ LLAppViewer::instance()->postToMainCoro([=]()
+ {
+ done_callback(success);
+ });
+ }
+}
+
diff --git a/indra/newview/llpbrterrainfeatures.h b/indra/newview/llpbrterrainfeatures.h
new file mode 100644
index 0000000000..f29d4ebf50
--- /dev/null
+++ b/indra/newview/llpbrterrainfeatures.h
@@ -0,0 +1,48 @@
+/**
+ * @file llpbrterrainfeatures.h
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#pragma once
+
+#include <string>
+
+class LLViewerRegion;
+class LLMessageSystem;
+class LLModifyRegion;
+
+// Queries/modifies PBR terrain repeats, possibly other features in the future
+class LLPBRTerrainFeatures
+{
+public:
+ static void queueQuery(LLViewerRegion& region, void(*done_callback)(LLUUID, bool, const LLModifyRegion&));
+ static void queueModify(LLViewerRegion& region, const LLModifyRegion& composition);
+
+private:
+ static void queryRegionCoro(std::string cap_url, LLUUID region_id, void(*done_callback)(LLUUID, bool, const LLModifyRegion&) );
+ static void modifyRegionCoro(std::string cap_url, LLSD updates, void(*done_callback)(bool) );
+};
+
+extern LLPBRTerrainFeatures gPBRTerrainFeatures;
+
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index bf4bdfd252..699cde8969 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -55,6 +55,7 @@
#include "llfloaterregioninfo.h"
#include "llgltfmateriallist.h"
#include "llhttpnode.h"
+#include "llpbrterrainfeatures.h"
#include "llregioninfomodel.h"
#include "llsdutil.h"
#include "llstartup.h"
@@ -2462,6 +2463,26 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
gSavedSettings.setS32("max_texture_dimension_Y", 1024);
}
+ if (features.has("PBRTerrainEnabled"))
+ {
+ bool enabled = features["PBRTerrainEnabled"];
+ gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled);
+ }
+ else
+ {
+ gSavedSettings.setBOOL("RenderTerrainPBREnabled", false);
+ }
+
+ if (features.has("PBRMaterialSwatchEnabled"))
+ {
+ bool enabled = features["PBRMaterialSwatchEnabled"];
+ gSavedSettings.setBOOL("UIPreviewMaterial", enabled);
+ }
+ else
+ {
+ gSavedSettings.setBOOL("UIPreviewMaterial", false);
+ }
+
if (features.has("GLTFEnabled"))
{
bool enabled = features["GLTFEnabled"];
@@ -2471,6 +2492,16 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
{
gSavedSettings.setBOOL("GLTFEnabled", false);
}
+
+ if (features.has("PBRTerrainTransformsEnabled"))
+ {
+ bool enabled = features["PBRTerrainTransformsEnabled"];
+ gSavedSettings.setBOOL("RenderTerrainTransformsPBREnabled", enabled);
+ }
+ else
+ {
+ gSavedSettings.setBOOL("RenderTerrainTransformsPBREnabled", false);
+ }
};
@@ -3109,6 +3140,17 @@ void LLViewerRegion::unpackRegionHandshake()
{
compp->setParamsReady();
}
+
+ LLPBRTerrainFeatures::queueQuery(*this, [](LLUUID region_id, bool success, const LLModifyRegion& composition_changes)
+ {
+ if (!success) { return; }
+ LLViewerRegion* region = LLWorld::getInstance()->getRegionFromID(region_id);
+ if (!region) { return; }
+ LLVLComposition* compp = region->getComposition();
+ if (!compp) { return; }
+ compp->apply(composition_changes);
+ LLFloaterRegionInfo::sRefreshFromRegion(region);
+ });
}
@@ -3206,6 +3248,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("MapLayerGod");
capabilityNames.append("MeshUploadFlag");
capabilityNames.append("ModifyMaterialParams");
+ capabilityNames.append("ModifyRegion");
capabilityNames.append("NavMeshGenerationStatus");
capabilityNames.append("NewFileAgentInventory");
capabilityNames.append("ObjectAnimation");
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index bc2fab99c0..4c226073d3 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llvlcomposition.cpp
* @brief Viewer-side representation of a composition layer...
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -115,6 +115,16 @@ LLTerrainMaterials::~LLTerrainMaterials()
unboost();
}
+void LLTerrainMaterials::apply(const LLModifyRegion& other)
+{
+ for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
+ {
+ const LLGLTFMaterial* other_override = other.getMaterialOverride(i);
+ LLGLTFMaterial* material_override = other_override ? new LLGLTFMaterial(*other_override) : nullptr;
+ setMaterialOverride(i, material_override);
+ }
+}
+
bool LLTerrainMaterials::generateMaterials()
{
if (texturesReady(true, true))
@@ -161,7 +171,7 @@ LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset)
// Assume both the the material and texture were fetched in the same way
// using the same UUID. However, we may not know at this point which one
// will load.
- return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null;
+ return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null;
}
LLPointer<LLViewerFetchedTexture> fetch_terrain_texture(const LLUUID& id)
@@ -183,16 +193,16 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
unboost_minimap_texture(mDetailTextures[asset]);
unboost_minimap_material(mDetailMaterials[asset]);
- // This is terrain texture, but we are not setting it as BOOST_TERRAIN
- // since we will be manipulating it later as needed.
- mDetailTextures[asset] = fetch_terrain_texture(id);
+ // This is terrain texture, but we are not setting it as BOOST_TERRAIN
+ // since we will be manipulating it later as needed.
+ mDetailTextures[asset] = fetch_terrain_texture(id);
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[asset];
mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id);
mDetailRenderMaterials[asset] = nullptr;
mMaterialTexturesSet[asset] = false;
}
-const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset)
+const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) const
{
return mDetailMaterialOverrides[asset];
}
@@ -208,7 +218,7 @@ void LLTerrainMaterials::setMaterialOverride(S32 asset, LLGLTFMaterial* mat_over
LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType()
{
- LL_PROFILE_ZONE_SCOPED;
+ LL_PROFILE_ZONE_SCOPED;
const BOOL use_textures = texturesReady(false, false) || !materialsReady(false, false);
return use_textures ? Type::TEXTURE : Type::PBR;
@@ -418,24 +428,24 @@ const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
LLTerrainMaterials(),
- LLViewerLayer(width, scale),
- mParamsReady(false)
+ LLViewerLayer(width, scale),
+ mParamsReady(false)
{
- // Load Terrain Textures - Original ones
+ // Load Terrain Textures - Original ones
const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures();
for (S32 i = 0; i < ASSET_COUNT; ++i)
{
setDetailAssetID(i, default_textures[i]);
}
- mSurfacep = surfacep;
+ mSurfacep = surfacep;
- // Initialize the texture matrix to defaults.
- for (S32 i = 0; i < CORNER_COUNT; ++i)
- {
- mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight");
- mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange");
- }
+ // Initialize the texture matrix to defaults.
+ for (S32 i = 0; i < CORNER_COUNT; ++i)
+ {
+ mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight");
+ mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange");
+ }
}
@@ -447,117 +457,117 @@ LLVLComposition::~LLVLComposition()
void LLVLComposition::setSurface(LLSurface *surfacep)
{
- mSurfacep = surfacep;
+ mSurfacep = surfacep;
}
bool LLVLComposition::generateHeights(const F32 x, const F32 y,
- const F32 width, const F32 height)
+ const F32 width, const F32 height)
{
- if (!mParamsReady)
- {
- // All the parameters haven't been set yet (we haven't gotten the message from the sim)
- return false;
- }
-
- llassert(mSurfacep);
-
- if (!mSurfacep || !mSurfacep->getRegion())
- {
- // We don't always have the region yet here....
- return false;
- }
-
- S32 x_begin, y_begin, x_end, y_end;
-
- x_begin = ll_round( x * mScaleInv );
- y_begin = ll_round( y * mScaleInv );
- x_end = ll_round( (x + width) * mScaleInv );
- y_end = ll_round( (y + width) * mScaleInv );
-
- if (x_end > mWidth)
- {
- x_end = mWidth;
- }
- if (y_end > mWidth)
- {
- y_end = mWidth;
- }
-
- LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle());
-
- // For perlin noise generation...
- const F32 slope_squared = 1.5f*1.5f;
- const F32 xyScale = 4.9215f; //0.93284f;
- const F32 zScale = 4; //0.92165f;
- const F32 z_offset = 0.f;
- const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus
- // simple height)
-
- const F32 xyScaleInv = (1.f / xyScale);
- const F32 zScaleInv = (1.f / zScale);
-
- const F32 inv_width = 1.f/mWidth;
-
- // OK, for now, just have the composition value equal the height at the point.
- for (S32 j = y_begin; j < y_end; j++)
- {
- for (S32 i = x_begin; i < x_end; i++)
- {
-
- F32 vec[3];
- F32 vec1[3];
- F32 twiddle;
-
- // Bilinearly interpolate the start height and height range of the textures
- F32 start_height = bilinear(mStartHeight[SOUTHWEST],
- mStartHeight[SOUTHEAST],
- mStartHeight[NORTHWEST],
- mStartHeight[NORTHEAST],
- i*inv_width, j*inv_width); // These will be bilinearly interpolated
- F32 height_range = bilinear(mHeightRange[SOUTHWEST],
- mHeightRange[SOUTHEAST],
- mHeightRange[NORTHWEST],
- mHeightRange[NORTHEAST],
- i*inv_width, j*inv_width); // These will be bilinearly interpolated
-
- LLVector3 location(i*mScale, j*mScale, 0.f);
-
- F32 height = mSurfacep->resolveHeightRegion(location) + z_offset;
-
- // Step 0: Measure the exact height at this texel
- vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice
- vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv;
- vec[2] = height*zScaleInv;
- //
- // Choose material value by adding to the exact height a random value
- //
- vec1[0] = vec[0]*(0.2222222222f);
- vec1[1] = vec[1]*(0.2222222222f);
- vec1[2] = vec[2]*(0.2222222222f);
- twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions
-
- twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component
- twiddle *= noise_magnitude;
-
- F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range;
-
- scaled_noisy_height = llmax(0.f, scaled_noisy_height);
- scaled_noisy_height = llmin(3.f, scaled_noisy_height);
- *(mDatap + i + j*mWidth) = scaled_noisy_height;
- }
- }
- return true;
+ if (!mParamsReady)
+ {
+ // All the parameters haven't been set yet (we haven't gotten the message from the sim)
+ return false;
+ }
+
+ llassert(mSurfacep);
+
+ if (!mSurfacep || !mSurfacep->getRegion())
+ {
+ // We don't always have the region yet here....
+ return false;
+ }
+
+ S32 x_begin, y_begin, x_end, y_end;
+
+ x_begin = ll_round( x * mScaleInv );
+ y_begin = ll_round( y * mScaleInv );
+ x_end = ll_round( (x + width) * mScaleInv );
+ y_end = ll_round( (y + width) * mScaleInv );
+
+ if (x_end > mWidth)
+ {
+ x_end = mWidth;
+ }
+ if (y_end > mWidth)
+ {
+ y_end = mWidth;
+ }
+
+ LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle());
+
+ // For perlin noise generation...
+ const F32 slope_squared = 1.5f*1.5f;
+ const F32 xyScale = 4.9215f; //0.93284f;
+ const F32 zScale = 4; //0.92165f;
+ const F32 z_offset = 0.f;
+ const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus
+ // simple height)
+
+ const F32 xyScaleInv = (1.f / xyScale);
+ const F32 zScaleInv = (1.f / zScale);
+
+ const F32 inv_width = 1.f/mWidth;
+
+ // OK, for now, just have the composition value equal the height at the point.
+ for (S32 j = y_begin; j < y_end; j++)
+ {
+ for (S32 i = x_begin; i < x_end; i++)
+ {
+
+ F32 vec[3];
+ F32 vec1[3];
+ F32 twiddle;
+
+ // Bilinearly interpolate the start height and height range of the textures
+ F32 start_height = bilinear(mStartHeight[SOUTHWEST],
+ mStartHeight[SOUTHEAST],
+ mStartHeight[NORTHWEST],
+ mStartHeight[NORTHEAST],
+ i*inv_width, j*inv_width); // These will be bilinearly interpolated
+ F32 height_range = bilinear(mHeightRange[SOUTHWEST],
+ mHeightRange[SOUTHEAST],
+ mHeightRange[NORTHWEST],
+ mHeightRange[NORTHEAST],
+ i*inv_width, j*inv_width); // These will be bilinearly interpolated
+
+ LLVector3 location(i*mScale, j*mScale, 0.f);
+
+ F32 height = mSurfacep->resolveHeightRegion(location) + z_offset;
+
+ // Step 0: Measure the exact height at this texel
+ vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice
+ vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv;
+ vec[2] = height*zScaleInv;
+ //
+ // Choose material value by adding to the exact height a random value
+ //
+ vec1[0] = vec[0]*(0.2222222222f);
+ vec1[1] = vec[1]*(0.2222222222f);
+ vec1[2] = vec[2]*(0.2222222222f);
+ twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions
+
+ twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component
+ twiddle *= noise_magnitude;
+
+ F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range;
+
+ scaled_noisy_height = llmax(0.f, scaled_noisy_height);
+ scaled_noisy_height = llmin(3.f, scaled_noisy_height);
+ *(mDatap + i + j*mWidth) = scaled_noisy_height;
+ }
+ }
+ return true;
}
LLTerrainMaterials gLocalTerrainMaterials;
bool LLVLComposition::generateComposition()
{
- if (!mParamsReady)
- {
- // All the parameters haven't been set yet (we haven't gotten the message from the sim)
- return false;
- }
+ if (!mParamsReady)
+ {
+ // All the parameters haven't been set yet (we haven't gotten the message from the sim)
+ return false;
+ }
return LLTerrainMaterials::generateMaterials();
}
@@ -665,22 +675,22 @@ namespace
};
bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
- const F32 width, const F32 height)
+ const F32 width, const F32 height)
{
- LL_PROFILE_ZONE_SCOPED
- llassert(mSurfacep);
- llassert(x >= 0.f);
- llassert(y >= 0.f);
+ LL_PROFILE_ZONE_SCOPED
+ llassert(mSurfacep);
+ llassert(x >= 0.f);
+ llassert(y >= 0.f);
- ///////////////////////////
- //
- // Generate raw data arrays for surface textures
- //
- //
+ ///////////////////////////
+ //
+ // Generate raw data arrays for surface textures
+ //
+ //
- // These have already been validated by generateComposition.
- U8* st_data[ASSET_COUNT];
- S32 st_data_size[ASSET_COUNT]; // for debugging
+ // These have already been validated by generateComposition.
+ U8* st_data[ASSET_COUNT];
+ S32 st_data_size[ASSET_COUNT]; // for debugging
const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR;
if (use_textures)
@@ -692,11 +702,11 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
if (!materialsReady(true, true)) { return false; }
}
- for (S32 i = 0; i < ASSET_COUNT; i++)
- {
- if (mRawImages[i].isNull())
- {
- // Read back a raw image for this discard level, if it exists
+ for (S32 i = 0; i < ASSET_COUNT; i++)
+ {
+ if (mRawImages[i].isNull())
+ {
+ // Read back a raw image for this discard level, if it exists
LLViewerFetchedTexture* tex;
LLViewerFetchedTexture* tex_emissive; // Can be null
bool has_base_color_factor;
@@ -769,14 +779,14 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
raw_emissive = newraw_emissive;
}
}
- if (has_base_color_factor ||
+ if (has_base_color_factor ||
raw_emissive ||
has_alpha ||
tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE ||
- tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE ||
- tex->getComponents() != 3)
- {
- LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
+ tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE ||
+ tex->getComponents() != 3)
+ {
+ LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
if (has_alpha)
{
// Approximate the water underneath terrain alpha with solid water color
@@ -786,7 +796,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
MAX_WATER_COLOR.mV[VZ],
255);
}
- newraw->composite(mRawImagesBaseColor[i]);
+ newraw->composite(mRawImagesBaseColor[i]);
if (has_base_color_factor)
{
newraw->tint(base_color_factor);
@@ -797,8 +807,8 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
newraw->addEmissive(raw_emissive);
}
- mRawImages[i] = newraw; // deletes old
- }
+ mRawImages[i] = newraw; // deletes old
+ }
if (delete_raw_post)
{
@@ -812,150 +822,150 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
// Remove intermediary image references
mRawImagesBaseColor[i] = nullptr;
mRawImagesEmissive[i] = nullptr;
- }
- st_data[i] = mRawImages[i]->getData();
- st_data_size[i] = mRawImages[i]->getDataSize();
- }
-
- ///////////////////////////////////////
- //
- // Generate and clamp x/y bounding box.
- //
- //
-
- S32 x_begin, y_begin, x_end, y_end;
- x_begin = (S32)(x * mScaleInv);
- y_begin = (S32)(y * mScaleInv);
- x_end = ll_round( (x + width) * mScaleInv );
- y_end = ll_round( (y + width) * mScaleInv );
-
- if (x_end > mWidth)
- {
+ }
+ st_data[i] = mRawImages[i]->getData();
+ st_data_size[i] = mRawImages[i]->getDataSize();
+ }
+
+ ///////////////////////////////////////
+ //
+ // Generate and clamp x/y bounding box.
+ //
+ //
+
+ S32 x_begin, y_begin, x_end, y_end;
+ x_begin = (S32)(x * mScaleInv);
+ y_begin = (S32)(y * mScaleInv);
+ x_end = ll_round( (x + width) * mScaleInv );
+ y_end = ll_round( (y + width) * mScaleInv );
+
+ if (x_end > mWidth)
+ {
llassert(false);
- x_end = mWidth;
- }
- if (y_end > mWidth)
- {
+ x_end = mWidth;
+ }
+ if (y_end > mWidth)
+ {
llassert(false);
- y_end = mWidth;
- }
-
-
- ///////////////////////////////////////////
- //
- // Generate target texture information, stride ratios.
- //
- //
-
- LLViewerTexture *texturep;
- U32 tex_width, tex_height, tex_comps;
- U32 tex_stride;
- F32 tex_x_scalef, tex_y_scalef;
- S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
- F32 tex_x_ratiof, tex_y_ratiof;
-
- texturep = mSurfacep->getSTexture();
- tex_width = texturep->getWidth();
- tex_height = texturep->getHeight();
- tex_comps = texturep->getComponents();
- tex_stride = tex_width * tex_comps;
-
- U32 st_comps = 3;
- U32 st_width = BASE_SIZE;
- U32 st_height = BASE_SIZE;
-
- if (tex_comps != st_comps)
- {
+ y_end = mWidth;
+ }
+
+
+ ///////////////////////////////////////////
+ //
+ // Generate target texture information, stride ratios.
+ //
+ //
+
+ LLViewerTexture *texturep;
+ U32 tex_width, tex_height, tex_comps;
+ U32 tex_stride;
+ F32 tex_x_scalef, tex_y_scalef;
+ S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
+ F32 tex_x_ratiof, tex_y_ratiof;
+
+ texturep = mSurfacep->getSTexture();
+ tex_width = texturep->getWidth();
+ tex_height = texturep->getHeight();
+ tex_comps = texturep->getComponents();
+ tex_stride = tex_width * tex_comps;
+
+ U32 st_comps = 3;
+ U32 st_width = BASE_SIZE;
+ U32 st_height = BASE_SIZE;
+
+ if (tex_comps != st_comps)
+ {
llassert(false);
- return false;
- }
-
- tex_x_scalef = (F32)tex_width / (F32)mWidth;
- tex_y_scalef = (F32)tex_height / (F32)mWidth;
- tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
- tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
- tex_x_end = (S32)((F32)x_end * tex_x_scalef);
- tex_y_end = (S32)((F32)y_end * tex_y_scalef);
-
- tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
- tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
-
- LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
- U8 *rawp = raw->getData();
-
- F32 st_x_stride, st_y_stride;
- st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
- st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
-
- llassert(st_x_stride > 0.f);
- llassert(st_y_stride > 0.f);
- ////////////////////////////////
- //
- // Iterate through the target texture, striding through the
- // subtextures and interpolating appropriately.
- //
- //
-
- F32 sti, stj;
- S32 st_offset;
- sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
- stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
-
- st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
- for (S32 j = tex_y_begin; j < tex_y_end; j++)
- {
- U32 offset = j * tex_stride + tex_x_begin * tex_comps;
- sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
- for (S32 i = tex_x_begin; i < tex_x_end; i++)
- {
- S32 tex0, tex1;
- F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
-
- tex0 = llfloor( composition );
- tex0 = llclamp(tex0, 0, 3);
- composition -= tex0;
- tex1 = tex0 + 1;
- tex1 = llclamp(tex1, 0, 3);
-
- st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
- for (U32 k = 0; k < tex_comps; k++)
- {
- // Linearly interpolate based on composition.
- if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
- {
- // SJB: This shouldn't be happening, but does... Rounding error?
- //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL;
- //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL;
- }
- else
- {
- F32 a = *(st_data[tex0] + st_offset);
- F32 b = *(st_data[tex1] + st_offset);
- rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
- }
- offset++;
- st_offset++;
- }
-
- sti += st_x_stride;
- if (sti >= st_width)
- {
- sti -= st_width;
- }
- }
-
- stj += st_y_stride;
- if (stj >= st_height)
- {
- stj -= st_height;
- }
- }
-
- if (!texturep->hasGLTexture())
- {
- texturep->createGLTexture(0, raw);
- }
- texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
+ return false;
+ }
+
+ tex_x_scalef = (F32)tex_width / (F32)mWidth;
+ tex_y_scalef = (F32)tex_height / (F32)mWidth;
+ tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
+ tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
+ tex_x_end = (S32)((F32)x_end * tex_x_scalef);
+ tex_y_end = (S32)((F32)y_end * tex_y_scalef);
+
+ tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
+ tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
+
+ LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
+ U8 *rawp = raw->getData();
+
+ F32 st_x_stride, st_y_stride;
+ st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
+ st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
+
+ llassert(st_x_stride > 0.f);
+ llassert(st_y_stride > 0.f);
+ ////////////////////////////////
+ //
+ // Iterate through the target texture, striding through the
+ // subtextures and interpolating appropriately.
+ //
+ //
+
+ F32 sti, stj;
+ S32 st_offset;
+ sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
+ stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
+
+ st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
+ for (S32 j = tex_y_begin; j < tex_y_end; j++)
+ {
+ U32 offset = j * tex_stride + tex_x_begin * tex_comps;
+ sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
+ for (S32 i = tex_x_begin; i < tex_x_end; i++)
+ {
+ S32 tex0, tex1;
+ F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
+
+ tex0 = llfloor( composition );
+ tex0 = llclamp(tex0, 0, 3);
+ composition -= tex0;
+ tex1 = tex0 + 1;
+ tex1 = llclamp(tex1, 0, 3);
+
+ st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
+ for (U32 k = 0; k < tex_comps; k++)
+ {
+ // Linearly interpolate based on composition.
+ if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
+ {
+ // SJB: This shouldn't be happening, but does... Rounding error?
+ //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL;
+ //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL;
+ }
+ else
+ {
+ F32 a = *(st_data[tex0] + st_offset);
+ F32 b = *(st_data[tex1] + st_offset);
+ rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
+ }
+ offset++;
+ st_offset++;
+ }
+
+ sti += st_x_stride;
+ if (sti >= st_width)
+ {
+ sti -= st_width;
+ }
+ }
+
+ stj += st_y_stride;
+ if (stj >= st_height)
+ {
+ stj -= st_height;
+ }
+ }
+
+ if (!texturep->hasGLTexture())
+ {
+ texturep->createGLTexture(0, raw);
+ }
+ texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
// Un-boost detail textures (will get re-boosted if rendering in high detail)
for (S32 i = 0; i < ASSET_COUNT; i++)
@@ -968,38 +978,38 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
{
unboost_minimap_material(mDetailMaterials[i]);
}
-
- return true;
+
+ return true;
}
F32 LLVLComposition::getStartHeight(S32 corner)
{
- return mStartHeight[corner];
+ return mStartHeight[corner];
}
void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id)
{
- if (id.isNull())
- {
+ if (id.isNull())
+ {
return;
}
LLTerrainMaterials::setDetailAssetID(asset, id);
- mRawImages[asset] = NULL;
- mRawImagesBaseColor[asset] = NULL;
- mRawImagesEmissive[asset] = NULL;
+ mRawImages[asset] = NULL;
+ mRawImagesBaseColor[asset] = NULL;
+ mRawImagesEmissive[asset] = NULL;
}
void LLVLComposition::setStartHeight(S32 corner, const F32 start_height)
{
- mStartHeight[corner] = start_height;
+ mStartHeight[corner] = start_height;
}
F32 LLVLComposition::getHeightRange(S32 corner)
{
- return mHeightRange[corner];
+ return mHeightRange[corner];
}
void LLVLComposition::setHeightRange(S32 corner, const F32 range)
{
- mHeightRange[corner] = range;
+ mHeightRange[corner] = range;
}
diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h
index f7590348f0..5e6fe52f5f 100644
--- a/indra/newview/llvlcomposition.h
+++ b/indra/newview/llvlcomposition.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llvlcomposition.h
* @brief Viewer-side representation of a composition layer...
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,16 +38,24 @@ class LLViewerFetchedTexture;
class LLGLTFMaterial;
class LLFetchedGLTFMaterial;
-class LLTerrainMaterials
+class LLModifyRegion
{
public:
- friend class LLDrawPoolTerrain;
+ virtual const LLGLTFMaterial* getMaterialOverride(S32 asset) const = 0;
+};
+
+class LLTerrainMaterials : public LLModifyRegion
+{
+public:
+ friend class LLDrawPoolTerrain;
LLTerrainMaterials();
virtual ~LLTerrainMaterials();
- // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
- // So we need to compress heights into this range.
+ void apply(const LLModifyRegion& other);
+
+ // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
+ // So we need to compress heights into this range.
static const S32 ASSET_COUNT = 4;
enum class Type
@@ -57,14 +65,14 @@ public:
COUNT
};
- bool generateMaterials();
+ bool generateMaterials();
void boost();
- virtual LLUUID getDetailAssetID(S32 asset);
- virtual void setDetailAssetID(S32 asset, const LLUUID& id);
- virtual const LLGLTFMaterial* getMaterialOverride(S32 asset);
- virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override);
+ virtual LLUUID getDetailAssetID(S32 asset);
+ virtual void setDetailAssetID(S32 asset, const LLUUID& id);
+ const LLGLTFMaterial* getMaterialOverride(S32 asset) const override;
+ virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override);
Type getMaterialType();
bool texturesReady(bool boost, bool strict);
// strict = true -> all materials must be sufficiently loaded
@@ -80,8 +88,8 @@ protected:
// *NOTE: Prefer calling materialReady if mat is known to be LLFetchedGLTFMaterial
static bool materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict);
- LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
- LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
+ LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
+ LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
LLPointer<LLGLTFMaterial> mDetailMaterialOverrides[ASSET_COUNT];
LLPointer<LLFetchedGLTFMaterial> mDetailRenderMaterials[ASSET_COUNT];
bool mMaterialTexturesSet[ASSET_COUNT];
@@ -93,61 +101,61 @@ extern LLTerrainMaterials gLocalTerrainMaterials;
class LLVLComposition : public LLTerrainMaterials, public LLViewerLayer
{
public:
- // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
- // So we need to compress heights into this range.
+ // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
+ // So we need to compress heights into this range.
static const S32 ASSET_COUNT = 4;
- static const LLUUID (&getDefaultTextures())[ASSET_COUNT];
-
- LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale);
- /*virtual*/ ~LLVLComposition();
-
- void setSurface(LLSurface *surfacep);
-
- // Viewer side hack to generate composition values
- bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
- bool generateComposition();
- // Generate texture from composition values.
- bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
- bool generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);
-
- // Use these as indeces ito the get/setters below that use 'corner'
- enum ECorner
- {
- SOUTHWEST = 0,
- SOUTHEAST = 1,
- NORTHWEST = 2,
- NORTHEAST = 3,
- CORNER_COUNT = 4
- };
-
- void setDetailAssetID(S32 asset, const LLUUID& id) override;
- F32 getStartHeight(S32 corner);
- F32 getHeightRange(S32 corner);
-
- void setStartHeight(S32 corner, F32 start_height);
- void setHeightRange(S32 corner, F32 range);
-
- friend class LLVOSurfacePatch;
- friend class LLDrawPoolTerrain;
- void setParamsReady() { mParamsReady = true; }
- bool getParamsReady() const { return mParamsReady; }
+ static const LLUUID (&getDefaultTextures())[ASSET_COUNT];
+
+ LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale);
+ /*virtual*/ ~LLVLComposition();
+
+ void setSurface(LLSurface *surfacep);
+
+ // Viewer side hack to generate composition values
+ bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
+ bool generateComposition();
+ // Generate texture from composition values.
+ bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
+ bool generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);
+
+ // Use these as indeces ito the get/setters below that use 'corner'
+ enum ECorner
+ {
+ SOUTHWEST = 0,
+ SOUTHEAST = 1,
+ NORTHWEST = 2,
+ NORTHEAST = 3,
+ CORNER_COUNT = 4
+ };
+
+ void setDetailAssetID(S32 asset, const LLUUID& id) override;
+ F32 getStartHeight(S32 corner);
+ F32 getHeightRange(S32 corner);
+
+ void setStartHeight(S32 corner, F32 start_height);
+ void setHeightRange(S32 corner, F32 range);
+
+ friend class LLVOSurfacePatch;
+ friend class LLDrawPoolTerrain;
+ void setParamsReady() { mParamsReady = true; }
+ bool getParamsReady() const { return mParamsReady; }
protected:
- bool mParamsReady = false;
- LLSurface *mSurfacep;
+ bool mParamsReady = false;
+ LLSurface *mSurfacep;
// Final minimap raw images
- LLPointer<LLImageRaw> mRawImages[LLTerrainMaterials::ASSET_COUNT];
+ LLPointer<LLImageRaw> mRawImages[LLTerrainMaterials::ASSET_COUNT];
// Only non-null during minimap tile generation
- LLPointer<LLImageRaw> mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT];
- LLPointer<LLImageRaw> mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT];
+ LLPointer<LLImageRaw> mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT];
+ LLPointer<LLImageRaw> mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT];
- F32 mStartHeight[CORNER_COUNT];
- F32 mHeightRange[CORNER_COUNT];
+ F32 mStartHeight[CORNER_COUNT];
+ F32 mHeightRange[CORNER_COUNT];
- F32 mTexScaleX = 16.f;
- F32 mTexScaleY = 16.f;
+ F32 mTexScaleX = 16.f;
+ F32 mTexScaleY = 16.f;
};
#endif //LL_LLVLCOMPOSITION_H
diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml
new file mode 100644
index 0000000000..cbcbe418cd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel
+ border="true"
+ follows="top|left"
+ height="460"
+ help_topic="panel_region_terrain_tab"
+ label="Terrain"
+ layout="topleft"
+ left="0"
+ name="Terrain"
+ top="320"
+ width="480">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="400">
+ unknown
+ </text>
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="detail_texture_text"
+ left="10"
+ top="35"
+ width="170">
+ Terrain Textures
+ </text>
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="detail_material_text"
+ left="10"
+ top="35"
+ width="170">
+ Terrain Materials
+ </text>
+ <check_box
+ height="20"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ layout="topleft"
+ top_delta="1"
+ left_delta="180"
+ label="PBR Metallic Roughness"
+ name="terrain_material_type"
+ tool_tip="If checked, use PBR Metallic Roughness materials for terrain. Otherwise, use textures."
+ left_pad="2"
+ width="200" />
+ <texture_picker
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left="10"
+ name="texture_detail_0"
+ default_image_id="0bc58228-74a0-7e83-89bc-5c23464bcec5"
+ top_delta="30"
+ width="100" />
+ <texture_picker
+ follows="top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_1"
+ default_image_id="63338ede-0037-c4fd-855b-015d77112fc8"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_2"
+ default_image_id="303cd381-8560-7579-23f1-f0a880799740"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_3"
+ default_image_id="53a2f406-4895-1d13-d541-d2e3b86bc19c"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ visible="false"
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left="10"
+ name="material_detail_0"
+ pick_type="material"
+ default_image_id="968cbad0-4dad-d64e-71b5-72bf13ad051a"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ visible="false"
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="material_detail_1"
+ pick_type="material"
+ default_image_id="968cbad0-4dad-d64e-71b5-72bf13ad051a"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ visible="false"
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="material_detail_2"
+ pick_type="material"
+ default_image_id="968cbad0-4dad-d64e-71b5-72bf13ad051a"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ visible="false"
+ follows="left|top"
+ height="121"
+ layout="topleft"
+ left_pad="10"
+ name="material_detail_3"
+ pick_type="material"
+ default_image_id="968cbad0-4dad-d64e-71b5-72bf13ad051a"
+ top_delta="0"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl"
+ top_delta="104"
+ width="65">
+ 1 (Low)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="45"
+ name="height_text_lbl2"
+ top_delta="0"
+ width="100">
+ 2
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl3"
+ top_delta="0"
+ width="100">
+ 3
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl4"
+ top_delta="0"
+ width="100">
+ 4 (High)
+ </text>
+ <layout_stack name="terrain_features_stack"
+ width="477"
+ height="230"
+ follows="all"
+ animate="false"
+ left="0"
+ top_delta="22"
+ orientation="vertical">
+ <layout_panel name="frame_settings_terrain"
+ auto_resize="true"
+ user_resize="false"
+ height="230"
+ width="467"
+ min_height="0"
+ visible="true">
+ <tab_container
+ follows="all"
+ halign="left"
+ height="230"
+ visible="true"
+ layout="topleft"
+ left="0"
+ name="terrain_tabs"
+ tab_position="top"
+ tab_width="100"
+ tab_padding_right="3"
+ top_pad="0"
+ width="700">
+ <panel
+ border="true"
+ class="panel_settings_terrain_elevation"
+ filename="panel_settings_terrain_elevation.xml"
+ label="Elevation"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="terrain_elevation_panel" />
+ <panel
+ border="true"
+ class="panel_settings_terrain_transform"
+ filename="panel_settings_terrain_transform.xml"
+ label="Transforms"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="terrain_transform_panel" />
+ </tab_container>
+ </layout_panel>
+ </layout_stack>
+ <button
+ enabled="true"
+ follows="left|top"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="353"
+ name="apply_btn"
+ top_delta="290"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_terrain_elevation.xml b/indra/newview/skins/default/xui/en/panel_settings_terrain_elevation.xml
new file mode 100644
index 0000000000..89443290ce
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_terrain_elevation.xml
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel
+ border="true"
+ follows="all"
+ label="Elevation"
+ layout="topleft"
+ left="0"
+ name="panel_settings_terrain_elevation"
+ top="0">
+ <spinner
+ follows="left|top"
+ height="20"
+ label="Water Height"
+ label_width="120"
+ layout="topleft"
+ left="15"
+ max_val="100"
+ name="water_height_spin"
+ top_delta="18"
+ width="180" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.2"
+ label="Terrain Raise Limit"
+ label_width="120"
+ layout="topleft"
+ left="240"
+ max_val="100"
+ name="terrain_raise_spin"
+ top_delta="0"
+ width="180" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.2"
+ label="Terrain Lower Limit"
+ label_width="120"
+ layout="topleft"
+ left="240"
+ max_val="0"
+ min_val="-100"
+ name="terrain_lower_spin"
+ top_delta="20"
+ width="180" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="60"
+ layout="topleft"
+ left="8"
+ top_delta="-30"
+ width="460" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl5"
+ top_delta="74"
+ width="300">
+ Texture Elevation Ranges
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl5_material"
+ top_delta="0"
+ width="300">
+ Material Elevation Ranges
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl10"
+ top_delta="30"
+ width="200"
+ word_wrap="true">
+ These values represent the blend range for the textures above.
+ </text>
+ <text
+ visible="false"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl10_material"
+ top_delta="0"
+ width="200"
+ word_wrap="true">
+ These values represent the blend range for the materials above.
+ </text>
+ <text
+ follows="left|top"
+ height="60"
+ layout="topleft"
+ left_delta="0"
+ name="height_text_lbl11"
+ top_delta="32"
+ width="200"
+ word_wrap="true">
+ Measured in meters, the LOW value is the MAXIMUM height of Texture #1, and the HIGH value is the MINIMUM height of Texture #4.
+ </text>
+ <text
+ visible="false"
+ follows="left|top"
+ height="60"
+ layout="topleft"
+ left_delta="0"
+ name="height_text_lbl11_material"
+ top_delta="0"
+ width="200"
+ word_wrap="true">
+ Measured in meters, the LOW value is the MAXIMUM height of Material #1, and the HIGH value is the MINIMUM height of Material #4.
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="270"
+ name="height_text_lbl6"
+ top_delta="-62"
+ width="100">
+ Northwest
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl7"
+ top_delta="0"
+ width="100">
+ Northeast
+ </text>
+<!-- northwest low-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left="230"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_1"
+ top_delta="15"
+ width="100" />
+<!-- northeast low-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_3"
+ top_delta="0"
+ width="100" />
+<!-- northwest high-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left="230"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_1"
+ top_delta="20"
+ width="100" />
+<!-- northeast high-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_3"
+ top_delta="0"
+ width="100" />
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="270"
+ name="height_text_lbl8"
+ top_pad="10"
+ width="100">
+ Southwest
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl9"
+ top_delta="0"
+ width="100">
+ Southeast
+ </text>
+<!-- southwest low-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left="230"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_0"
+ top_delta="15"
+ width="100" />
+<!-- southeast low-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_2"
+ top_delta="0"
+ width="100" />
+<!--southwest high-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left="230"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_0"
+ top_delta="20"
+ width="100" />
+<!-- southeast high-->
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_2"
+ top_delta="0"
+ width="100" />
+<!-- Terrain Download/Upload/Bake buttons -->
+ <button
+ follows="left|top"
+ height="20"
+ label="Download RAW terrain..."
+ layout="topleft"
+ left="10"
+ name="download_raw_btn"
+ tool_tip="Available only to estate owners, not managers"
+ top_delta="40"
+ width="160" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Upload RAW terrain..."
+ layout="topleft"
+ left_pad="10"
+ top_delta="0"
+ name="upload_raw_btn"
+ tool_tip="Available only to estate owners, not managers"
+ width="160" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Bake Terrain"
+ layout="topleft"
+ left_pad="10"
+ name="bake_terrain_btn"
+ tool_tip="Set current terrain as mid-point for raise/lower limits"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml b/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml
new file mode 100644
index 0000000000..7052622813
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel
+ border="true"
+ follows="all"
+ label="Samping"
+ layout="topleft"
+ left="0"
+ name="panel_settings_terrain_transform"
+ top="0">
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="terrain0ScaleU_label"
+ left="10"
+ top_pad="3"
+ width="170">
+ Scale u
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="8"
+ top_pad="-2"
+ name="terrain0ScaleU_horizontal"
+ width="430" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left="10"
+ min_val="-100"
+ max_val="100"
+ name="terrain0ScaleU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain1ScaleU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain2ScaleU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain3ScaleU"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="terrain0ScaleV_label"
+ left="10"
+ top_pad="3"
+ width="170">
+ Scale v
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="8"
+ top_pad="-2"
+ name="terrain0ScaleV_horizontal"
+ width="430" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale v"
+ label_width="0"
+ layout="topleft"
+ left="10"
+ min_val="-100"
+ max_val="100"
+ name="terrain0ScaleV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain1ScaleV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain2ScaleV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain3ScaleV"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="terrain0Rotation_label"
+ left="10"
+ top_pad="3"
+ width="170">
+ Rotation
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="8"
+ top_pad="-2"
+ name="terrain0Rotation_horizontal"
+ width="430" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Rotation"
+ label_width="0"
+ layout="topleft"
+ left="10"
+ min_val="-360"
+ max_val="360"
+ name="terrain0Rotation"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain1Rotation"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain2Rotation"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain3Rotation"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="terrain0OffsetU_label"
+ left="10"
+ top_pad="3"
+ width="170">
+ Offset y
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="8"
+ top_pad="-2"
+ name="terrain0OffsetU_horizontal"
+ width="430" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Offset u"
+ label_width="0"
+ layout="topleft"
+ left="10"
+ min_val="-999"
+ max_val="999"
+ name="terrain0OffsetU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain1OffsetU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain2OffsetU"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain3OffsetU"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ halign="left"
+ valign="center"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="terrain0OffsetV_label"
+ left="10"
+ top_pad="3"
+ width="170">
+ Offset v
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="8"
+ top_pad="-2"
+ name="terrain0OffsetV_horizontal"
+ width="430" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Offset v"
+ label_width="0"
+ layout="topleft"
+ left="10"
+ min_val="-999"
+ max_val="999"
+ name="terrain0OffsetV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain1OffsetV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain2OffsetV"
+ width="64" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Scale u"
+ label_width="0"
+ layout="topleft"
+ left_delta="110"
+ min_val="-100"
+ max_val="100"
+ name="terrain3OffsetV"
+ width="64" />
+</panel>