summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BuildParams11
-rw-r--r--indra/edit-me-to-trigger-new-build.txt1
-rw-r--r--indra/llprimitive/CMakeLists.txt2
-rw-r--r--indra/llprimitive/llmaterialid.cpp117
-rw-r--r--indra/llprimitive/llmaterialid.h63
-rwxr-xr-xindra/llprimitive/llprimitive.cpp34
-rw-r--r--indra/llprimitive/llprimitive.h2
-rw-r--r--indra/llprimitive/llprimtexturelist.cpp10
-rw-r--r--indra/llprimitive/llprimtexturelist.h2
-rw-r--r--indra/llprimitive/lltextureentry.cpp17
-rw-r--r--indra/llprimitive/lltextureentry.h4
-rw-r--r--indra/llrender/llglslshader.cpp66
-rw-r--r--indra/llrender/llglslshader.h13
-rw-r--r--indra/llrender/llshadermgr.cpp10
-rw-r--r--indra/llrender/llshadermgr.h2
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl2
-rw-r--r--indra/newview/llfloaterdebugmaterials.cpp1626
-rw-r--r--indra/newview/llfloaterdebugmaterials.h208
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerobject.cpp21
-rw-r--r--indra/newview/llviewerobject.h14
-rw-r--r--indra/newview/llviewerregion.cpp1
-rw-r--r--indra/newview/llviewershadermgr.cpp10
-rw-r--r--indra/newview/llvovolume.cpp12
-rw-r--r--indra/newview/llvovolume.h2
-rw-r--r--indra/newview/pipeline.cpp52
-rw-r--r--indra/newview/skins/default/colors.xml9
-rw-r--r--indra/newview/skins/default/xui/en/floater_debug_materials.xml1075
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml11
-rw-r--r--indra/newview/tests/llmediadataclient_test.cpp1
-rw-r--r--indra/newview/viewer_manifest.py2
35 files changed, 3357 insertions, 55 deletions
diff --git a/BuildParams b/BuildParams
index e63336cb19..5516d8395b 100644
--- a/BuildParams
+++ b/BuildParams
@@ -143,6 +143,17 @@ viewer-pathfinding.build_debug_release_separately = true
viewer-pathfinding.build_CYGWIN_Debug = false
viewer-pathfinding.build_viewer_update_version_manager = false
+# ========================================
+# viewer-materials
+# ========================================
+
+viewer-materials.viewer_channel = "Project Viewer - Materials"
+viewer-materials.login_channel = "Project Viewer - Materials"
+viewer-materials.viewer_grid = aditi
+viewer-materials.build_debug_release_separately = true
+viewer-materials.build_CYGWIN_Debug = false
+viewer-materials.build_viewer_update_version_manager = false
+
# =================================================================
# asset delivery 2010 projects
# =================================================================
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index e69de29bb2..48afa33218 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -0,0 +1 @@
+Wed Nov 7 01:05:20 UTC 2012
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index e4d9de7eb6..82d0f892f2 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -20,6 +20,7 @@ include_directories(
)
set(llprimitive_SOURCE_FILES
+ llmaterialid.cpp
llmaterialtable.cpp
llmediaentry.cpp
llmodel.cpp
@@ -37,6 +38,7 @@ set(llprimitive_HEADER_FILES
CMakeLists.txt
legacy_object_types.h
+ llmaterialid.h
llmaterialtable.h
llmediaentry.h
llmodel.h
diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp
new file mode 100644
index 0000000000..8122b70c2d
--- /dev/null
+++ b/indra/llprimitive/llmaterialid.cpp
@@ -0,0 +1,117 @@
+/**
+* @file llmaterialid.cpp
+* @brief Implementation of llmaterialid
+* @author Stinson@lindenlab.com
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, 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 "linden_common.h"
+
+#include "llmaterialid.h"
+
+const LLMaterialID LLMaterialID::null;
+
+LLMaterialID::LLMaterialID()
+{
+ clear();
+}
+
+LLMaterialID::LLMaterialID(const LLSD& pMaterialID)
+{
+ llassert(pMaterialID.isBinary());
+ parseFromBinary(pMaterialID.asBinary());
+}
+
+LLMaterialID::LLMaterialID(const LLSD::Binary& pMaterialID)
+{
+ parseFromBinary(pMaterialID);
+}
+
+LLMaterialID::LLMaterialID(const void* pMemory)
+{
+ set(pMemory);
+}
+
+LLMaterialID::LLMaterialID(const LLMaterialID& pOtherMaterialID)
+{
+ copyFromOtherMaterialID(pOtherMaterialID);
+}
+
+LLMaterialID::~LLMaterialID()
+{
+}
+
+bool LLMaterialID::operator == (const LLMaterialID& pOtherMaterialID) const
+{
+ return (compareToOtherMaterialID(pOtherMaterialID) == 0);
+}
+
+bool LLMaterialID::operator != (const LLMaterialID& pOtherMaterialID) const
+{
+ return (compareToOtherMaterialID(pOtherMaterialID) != 0);
+}
+
+LLMaterialID& LLMaterialID::operator = (const LLMaterialID& pOtherMaterialID)
+{
+ copyFromOtherMaterialID(pOtherMaterialID);
+ return (*this);
+}
+
+bool LLMaterialID::isNull() const
+{
+ return (compareToOtherMaterialID(LLMaterialID::null) == 0);
+}
+
+const U8* LLMaterialID::get() const
+{
+ return mID;
+}
+
+void LLMaterialID::set(const void* pMemory)
+{
+ llassert(pMemory != NULL);
+
+ // assumes that the required size of memory is available
+ memcpy(mID, pMemory, MATERIAL_ID_SIZE * sizeof(U8));
+}
+
+void LLMaterialID::clear()
+{
+ memset(mID, 0, MATERIAL_ID_SIZE * sizeof(U8));
+}
+
+void LLMaterialID::parseFromBinary (const LLSD::Binary& pMaterialID)
+{
+ llassert(pMaterialID.size() == (MATERIAL_ID_SIZE * sizeof(U8)));
+ memcpy(mID, &pMaterialID[0], MATERIAL_ID_SIZE * sizeof(U8));
+}
+
+void LLMaterialID::copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID)
+{
+ memcpy(mID, pOtherMaterialID.mID, MATERIAL_ID_SIZE * sizeof(U8));
+}
+
+int LLMaterialID::compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const
+{
+ return memcmp(mID, pOtherMaterialID.mID, MATERIAL_ID_SIZE * sizeof(U8));
+}
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
new file mode 100644
index 0000000000..71c6e72478
--- /dev/null
+++ b/indra/llprimitive/llmaterialid.h
@@ -0,0 +1,63 @@
+/**
+* @file llmaterialid.h
+* @brief Header file for llmaterialid
+* @author Stinson@lindenlab.com
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, 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$
+*/
+#ifndef LL_LLMATERIALID_H
+#define LL_LLMATERIALID_H
+
+#define MATERIAL_ID_SIZE 16
+
+class LLMaterialID
+{
+public:
+ LLMaterialID();
+ LLMaterialID(const LLSD& pMaterialID);
+ LLMaterialID(const LLSD::Binary& pMaterialID);
+ LLMaterialID(const void* pMemory);
+ LLMaterialID(const LLMaterialID& pOtherMaterialID);
+ ~LLMaterialID();
+
+ bool operator == (const LLMaterialID& pOtherMaterialID) const;
+ bool operator != (const LLMaterialID& pOtherMaterialID) const;
+ LLMaterialID& operator = (const LLMaterialID& pOtherMaterialID);
+
+ bool isNull() const;
+
+ const U8* get() const;
+ void set(const void* pMemory);
+ void clear();
+
+ static const LLMaterialID null;
+
+private:
+ void parseFromBinary(const LLSD::Binary& pMaterialID);
+ void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
+ int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const;
+
+ U8 mID[MATERIAL_ID_SIZE];
+} ;
+
+#endif // LL_LLMATERIALID_H
+
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 6dee192783..86aa371368 100755
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -39,6 +39,7 @@
#include "lldatapacker.h"
#include "llsdutil_math.h"
#include "llprimtexturelist.h"
+#include "llmaterialid.h"
/**
* exported constants
@@ -366,6 +367,11 @@ S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow)
return mTextureList.setGlow(index, glow);
}
+S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID)
+{
+ return mTextureList.setMaterialID(index, pMaterialID);
+}
+
LLPCode LLPrimitive::legacyToPCode(const U8 legacy)
{
@@ -1091,6 +1097,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
+ U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1128,6 +1135,9 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
bump[face_index] = te->getBumpShinyFullbright();
media_flags[face_index] = te->getMediaTexGen();
glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
+
+ // Directly sending material_ids is not safe!
+ memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */
}
cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
@@ -1149,6 +1159,8 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
+ *cur_ptr++ = 0;
+ cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID);
}
mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer));
@@ -1170,6 +1182,7 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
+ U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1207,6 +1220,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
bump[face_index] = te->getBumpShinyFullbright();
media_flags[face_index] = te->getMediaTexGen();
glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
+
+ // Directly sending material_ids is not safe!
+ memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */
}
cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
@@ -1228,6 +1244,8 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
*cur_ptr++ = 0;
cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
+ *cur_ptr++ = 0;
+ cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID);
}
dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry");
@@ -1246,6 +1264,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam
const U32 MAX_TES = 32;
// Avoid construction of 32 UUIDs per call. JC
+ static LLMaterialID material_ids[MAX_TES];
U8 image_data[MAX_TES*16];
U8 colors[MAX_TES*4];
@@ -1257,6 +1276,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
+ U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1309,6 +1329,13 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
+ cur_ptr++;
+ cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID);
+
+ for (U32 i = 0; i < face_count; i++)
+ {
+ material_ids[i].set(&material_data[i * 16]);
+ }
LLColor4 color;
LLColor4U coloru;
@@ -1321,6 +1348,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_nam
retval |= setTEBumpShinyFullbright(i, bump[i]);
retval |= setTEMediaTexGen(i, media_flags[i]);
retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
+ retval |= setTEMaterialID(i, material_ids[i]);
coloru = LLColor4U(colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
@@ -1346,6 +1374,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
// Avoid construction of 32 UUIDs per call
static LLUUID image_ids[MAX_TES];
+ static LLMaterialID material_ids[MAX_TES];
U8 image_data[MAX_TES*16];
U8 colors[MAX_TES*4];
@@ -1357,6 +1386,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
+ U8 material_data[MAX_TES*16];
const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -1399,10 +1429,13 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
cur_ptr++;
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
+ cur_ptr++;
+ cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID);
for (i = 0; i < face_count; i++)
{
memcpy(image_ids[i].mData,&image_data[i*16],16); /* Flawfinder: ignore */
+ material_ids[i].set(&material_data[i * 16]);
}
LLColor4 color;
@@ -1416,6 +1449,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
retval |= setTEBumpShinyFullbright(i, bump[i]);
retval |= setTEMediaTexGen(i, media_flags[i]);
retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
+ retval |= setTEMaterialID(i, material_ids[i]);
coloru = LLColor4U(colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 8dcaa8c740..e1635740ef 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -42,6 +42,7 @@ class LLMessageSystem;
class LLVolumeParams;
class LLColor4;
class LLColor3;
+class LLMaterialID;
class LLTextureEntry;
class LLDataPacker;
class LLVolumeMgr;
@@ -353,6 +354,7 @@ public:
virtual S32 setTEFullbright(const U8 te, const U8 fullbright);
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
+ virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
void copyTEs(const LLPrimitive *primitive);
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index 36e04df7b7..20438578b3 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -27,6 +27,7 @@
#include "linden_common.h"
#include "llprimtexturelist.h"
+#include "llmaterialid.h"
#include "lltextureentry.h"
#include "llmemtype.h"
@@ -359,6 +360,15 @@ S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow)
return TEM_CHANGE_NONE;
}
+S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMaterialID)
+{
+ if (index < mEntryList.size())
+ {
+ return mEntryList[index]->setMaterialID(pMaterialID);
+ }
+ return TEM_CHANGE_NONE;
+}
+
S32 LLPrimTextureList::size() const
{
return mEntryList.size();
diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h
index 3cfa52f1d5..691df44c18 100644
--- a/indra/llprimitive/llprimtexturelist.h
+++ b/indra/llprimitive/llprimtexturelist.h
@@ -34,6 +34,7 @@
class LLTextureEntry;
+class LLMaterialID;
// this is a list of LLTextureEntry*'s because in practice the list's elements
// are of some derived class: LLFooTextureEntry
@@ -102,6 +103,7 @@ public:
S32 setFullbright(const U8 index, const U8 t);
S32 setMediaFlags(const U8 index, const U8 media_flags);
S32 setGlow(const U8 index, const F32 glow);
+ S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID);
S32 size() const;
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index 34eff17519..b04fa809d2 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -29,6 +29,7 @@
#include "lluuid.h"
#include "llmediaentry.h"
#include "lltextureentry.h"
+#include "llmaterialid.h"
#include "llsdutil_math.h"
#include "v4color.h"
@@ -83,6 +84,8 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
+ mMaterialID = rhs.mMaterialID;
+
if (rhs.mMediaEntry != NULL) {
// Make a copy
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
@@ -103,6 +106,7 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
+ mMaterialID = rhs.mMaterialID;
if (mMediaEntry != NULL) {
delete mMediaEntry;
}
@@ -130,6 +134,7 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of
mBump = bump;
mMediaFlags = 0x0;
mGlow = 0;
+ mMaterialID.clear();
setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
if (mMediaEntry != NULL) {
@@ -159,6 +164,7 @@ bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
if (mBump != rhs.mBump) return (true);
if (mMediaFlags != rhs.mMediaFlags) return (true);
if (mGlow != rhs.mGlow) return (true);
+ if (mMaterialID != rhs.mMaterialID) return (true);
return(false);
}
@@ -174,6 +180,7 @@ bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const
if (mBump != rhs.mBump) return (false);
if (mMediaFlags != rhs.mMediaFlags) return false;
if (mGlow != rhs.mGlow) return false;
+ if (mMaterialID != rhs.mMaterialID) return (false);
return(true);
}
@@ -523,6 +530,16 @@ S32 LLTextureEntry::setGlow(F32 glow)
return TEM_CHANGE_NONE;
}
+S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID)
+{
+ if (mMaterialID != pMaterialID)
+ {
+ mMaterialID = pMaterialID;
+ return TEM_CHANGE_TEXTURE;
+ }
+ return TEM_CHANGE_NONE;
+}
+
void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
{
mMediaFlags |= MF_HAS_MEDIA;
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 437b85e03f..b681ce8ca7 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -30,6 +30,7 @@
#include "lluuid.h"
#include "v4color.h"
#include "llsd.h"
+#include "llmaterialid.h"
// These bits are used while unpacking TEM messages to tell which aspects of
// the texture entry changed.
@@ -121,6 +122,7 @@ public:
S32 setTexGen(U8 texGen);
S32 setMediaTexGen(U8 media);
S32 setGlow(F32 glow);
+ S32 setMaterialID(const LLMaterialID& pMaterialID);
virtual const LLUUID &getID() const { return mID; }
const LLColor4 &getColor() const { return mColor; }
@@ -139,6 +141,7 @@ public:
U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; }
U8 getMediaTexGen() const { return mMediaFlags; }
F32 getGlow() const { return mGlow; }
+ const LLMaterialID& getMaterialID() const { return mMaterialID; };
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
@@ -193,6 +196,7 @@ protected:
U8 mBump; // Bump map, shiny, and fullbright
U8 mMediaFlags; // replace with web page, movie, etc.
F32 mGlow;
+ LLMaterialID mMaterialID;
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 7cbf39096e..39e81c4bfc 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -150,7 +150,7 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
+ GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mDefines, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle > 0)
{
@@ -372,7 +372,17 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
}
}
}
- }
+}
+
+void LLGLSLShader::addPermutation(std::string name, std::string value)
+{
+ mDefines[name] = value;
+}
+
+void LLGLSLShader::removePermutation(std::string name)
+{
+ mDefines[name].erase();
+}
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
@@ -471,6 +481,58 @@ void LLGLSLShader::bindNoShader(void)
}
}
+S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return bindTexture(channel, texture, mode);
+}
+
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->bind(texture, mode);
+ }
+
+ return uniform;
+}
+
+S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode)
+{
+ S32 channel = 0;
+ channel = getUniformLocation(uniform);
+
+ return unbindTexture(channel);
+}
+
+S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->unbind(mode);
+ }
+
+ return uniform;
+}
+
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (uniform < 0 || uniform >= (S32)mTexture.size())
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 5c68cb46eb..2af74c20ff 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -123,12 +123,22 @@ public:
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
+ void addPermutation(std::string name, std::string value);
+ void removePermutation(std::string name);
+
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
//returns channel texture is enabled in from [0-MAX)
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
- S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+
+ // bindTexture returns the texture unit we've bound the texture to.
+ // You can reuse the return value to unbind a texture when required.
+ S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
BOOL link(BOOL suppress_errors = FALSE);
void bind();
@@ -153,6 +163,7 @@ public:
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
+ boost::unordered_map<std::string, std::string> mDefines;
};
//UI shader (declared here so llui_libtest will link properly)
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index b6a9a6b653..3b1ec281c9 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -521,7 +521,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string> defines, S32 texture_index_channels)
{
GLenum error = GL_NO_ERROR;
if (gDebugGL)
@@ -657,6 +657,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
std::string define = "#define " + iter->first + " " + iter->second + "\n";
text[count++] = (GLcharARB *) strdup(define.c_str());
}
+
+ for (boost::unordered_map<std::string,std::string>::iterator iter = defines.begin(); iter != defines.end(); ++iter)
+ {
+ std::string define = "#define " + iter->first + " " + iter->second + "\n";
+ text[count++] = (GLcharARB *) strdup(define.c_str());
+ }
if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
{
@@ -854,7 +860,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
- return loadShaderFile(filename,shader_level,type,texture_index_channels);
+ return loadShaderFile(filename,shader_level,type, defines, texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 7a16b7c20f..4b93aae735 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -176,7 +176,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string> defines, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7eea9ece5a..4742f6166a 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -194,6 +194,7 @@ set(viewer_SOURCE_FILES
llfloaterbuyland.cpp
llfloatercamera.cpp
llfloatercolorpicker.cpp
+ llfloaterdebugmaterials.cpp
llfloaterdeleteenvpreset.cpp
llfloaterdestinations.cpp
llfloaterdisplayname.cpp
@@ -771,6 +772,7 @@ set(viewer_HEADER_FILES
llfloaterbuyland.h
llfloatercamera.h
llfloatercolorpicker.h
+ llfloaterdebugmaterials.h
llfloaterdeleteenvpreset.h
llfloaterdestinations.h
llfloaterdisplayname.h
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 7e79317543..9e194cdcd1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -128,8 +128,7 @@ void main()
if (sa > 0.0)
{
- sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
- sa *= noise;
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
col += da*sa*light_col[i].rgb*spec.rgb;
}
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 75757b26c8..6e5ac8317b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -110,8 +110,7 @@ void main()
float sa = dot(normalize(lv-normalize(pos)),norm);
if (sa > 0.0)
{
- sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
- sa *= noise;
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
col += da*sa*color.rgb*spec.rgb;
}
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 89448e2167..14eaafeb68 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -301,7 +301,7 @@ void main()
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = vary_SunlitColor*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
+ vec3 dumbshiny = vary_SunlitColor*(texture2D(lightFunc, vec2(sa, spec.a)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 9df9d75905..457189b48e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -309,7 +309,7 @@ void main()
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
+ vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(texture2D(lightFunc, vec2(sa, spec.a)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
diff --git a/indra/newview/llfloaterdebugmaterials.cpp b/indra/newview/llfloaterdebugmaterials.cpp
new file mode 100644
index 0000000000..5bb4aa93d4
--- /dev/null
+++ b/indra/newview/llfloaterdebugmaterials.cpp
@@ -0,0 +1,1626 @@
+/**
+* @file llfloaterdebugmaterials.cpp
+* @brief Implementation of llfloaterdebugmaterials
+* @author Stinson@lindenlab.com
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, 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 "llfloaterdebugmaterials.h"
+
+#include <string>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcolorswatch.h"
+#include "llenvmanager.h"
+#include "llfloater.h"
+#include "llfontgl.h"
+#include "llhttpclient.h"
+#include "lllineeditor.h"
+#include "llmaterialid.h"
+#include "llresmgr.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llselectmgr.h"
+#include "llspinctrl.h"
+#include "llstring.h"
+#include "llstyle.h"
+#include "lltextbase.h"
+#include "lltexturectrl.h"
+#include "lltextvalidate.h"
+#include "lluicolortable.h"
+#include "lluictrl.h"
+#include "lluuid.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "v4color.h"
+#include "v4coloru.h"
+
+#define MATERIALS_CAPABILITY_NAME "RenderMaterials"
+
+#define MATERIALS_CAP_ZIP_FIELD "Zipped"
+
+#define MATERIALS_CAP_FULL_PER_FACE_FIELD "FullMaterialsPerFace"
+#define MATERIALS_CAP_FACE_FIELD "Face"
+#define MATERIALS_CAP_MATERIAL_FIELD "Material"
+#define MATERIALS_CAP_OBJECT_ID_FIELD "ID"
+#define MATERIALS_CAP_MATERIAL_ID_FIELD "MaterialID"
+
+#define MATERIALS_CAP_NORMAL_MAP_FIELD "NormMap"
+#define MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD "NormOffsetX"
+#define MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD "NormOffsetY"
+#define MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD "NormRepeatX"
+#define MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD "NormRepeatY"
+#define MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD "NormRotation"
+
+#define MATERIALS_CAP_SPECULAR_MAP_FIELD "SpecMap"
+#define MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD "SpecOffsetX"
+#define MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD "SpecOffsetY"
+#define MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD "SpecRepeatX"
+#define MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD "SpecRepeatY"
+#define MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD "SpecRotation"
+
+#define MATERIALS_CAP_SPECULAR_COLOR_FIELD "SpecColor"
+#define MATERIALS_CAP_SPECULAR_EXP_FIELD "SpecExp"
+#define MATERIALS_CAP_ENV_INTENSITY_FIELD "EnvIntensity"
+#define MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD "AlphaMaskCutoff"
+#define MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD "DiffuseAlphaMode"
+
+class MaterialsResponder : public LLHTTPClient::Responder
+{
+public:
+ typedef boost::function<void (bool, const LLSD&)> CallbackFunction;
+
+ MaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
+ virtual ~MaterialsResponder();
+
+ virtual void result(const LLSD& pContent);
+ virtual void error(U32 pStatus, const std::string& pReason);
+
+protected:
+
+private:
+ std::string mMethod;
+ std::string mCapabilityURL;
+ CallbackFunction mCallback;
+};
+
+BOOL LLFloaterDebugMaterials::postBuild()
+{
+ mStatusText = findChild<LLTextBase>("material_status");
+ llassert(mStatusText != NULL);
+
+ mGetButton = findChild<LLButton>("get_button");
+ llassert(mGetButton != NULL);
+ mGetButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onGetClicked, this));
+
+ mParsingStatusText = findChild<LLTextBase>("loading_status");
+ llassert(mParsingStatusText != NULL);
+
+ mGetNormalMapScrollList = findChild<LLScrollListCtrl>("get_normal_map_scroll_list");
+ llassert(mGetNormalMapScrollList != NULL);
+ mGetNormalMapScrollList->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onGetScrollListSelectionChange, this, _1));
+
+ mGetSpecularMapScrollList = findChild<LLScrollListCtrl>("get_specular_map_scroll_list");
+ llassert(mGetSpecularMapScrollList != NULL);
+ mGetSpecularMapScrollList->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onGetScrollListSelectionChange, this, _1));
+
+ mGetOtherDataScrollList = findChild<LLScrollListCtrl>("get_other_data_scroll_list");
+ llassert(mGetOtherDataScrollList != NULL);
+ mGetOtherDataScrollList->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onGetScrollListSelectionChange, this, _1));
+
+ mNormalMap = findChild<LLTextureCtrl>("normal_map");
+ llassert(mNormalMap != NULL);
+
+ mNormalMapOffsetX = findChild<LLLineEditor>("normal_map_offset_x");
+ llassert(mNormalMapOffsetX != NULL);
+ mNormalMapOffsetX->setPrevalidate(LLTextValidate::validateInt);
+ mNormalMapOffsetX->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mNormalMapOffsetY = findChild<LLLineEditor>("normal_map_offset_y");
+ llassert(mNormalMapOffsetY != NULL);
+ mNormalMapOffsetY->setPrevalidate(LLTextValidate::validateInt);
+ mNormalMapOffsetY->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mNormalMapRepeatX = findChild<LLLineEditor>("normal_map_repeat_x");
+ llassert(mNormalMapRepeatX != NULL);
+ mNormalMapRepeatX->setPrevalidate(LLTextValidate::validateInt);
+ mNormalMapRepeatX->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mNormalMapRepeatY = findChild<LLLineEditor>("normal_map_repeat_y");
+ llassert(mNormalMapRepeatY != NULL);
+ mNormalMapRepeatY->setPrevalidate(LLTextValidate::validateInt);
+ mNormalMapRepeatY->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mNormalMapRotation = findChild<LLLineEditor>("normal_map_rotation");
+ llassert(mNormalMapRotation != NULL);
+ mNormalMapRotation->setPrevalidate(LLTextValidate::validateInt);
+ mNormalMapRotation->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularMap = findChild<LLTextureCtrl>("specular_map");
+ llassert(mSpecularMap != NULL);
+
+ mSpecularMapOffsetX = findChild<LLLineEditor>("specular_map_offset_x");
+ llassert(mSpecularMapOffsetX != NULL);
+ mSpecularMapOffsetX->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularMapOffsetX->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularMapOffsetY = findChild<LLLineEditor>("specular_map_offset_y");
+ llassert(mSpecularMapOffsetY != NULL);
+ mSpecularMapOffsetY->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularMapOffsetY->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularMapRepeatX = findChild<LLLineEditor>("specular_map_repeat_x");
+ llassert(mSpecularMapRepeatX != NULL);
+ mSpecularMapRepeatX->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularMapRepeatX->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularMapRepeatY = findChild<LLLineEditor>("specular_map_repeat_y");
+ llassert(mSpecularMapRepeatY != NULL);
+ mSpecularMapRepeatY->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularMapRepeatY->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularMapRotation = findChild<LLLineEditor>("specular_map_rotation");
+ llassert(mSpecularMapRotation != NULL);
+ mSpecularMapRotation->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularMapRotation->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mSpecularColor = findChild<LLColorSwatchCtrl>("specular_color");
+ llassert(mSpecularColor != NULL);
+
+ mSpecularColorAlpha = findChild<LLSpinCtrl>("specular_color_alpha");
+ llassert(mSpecularColorAlpha != NULL);
+
+ mSpecularExponent = findChild<LLLineEditor>("specular_exponent");
+ llassert(mSpecularExponent != NULL);
+ mSpecularExponent->setPrevalidate(LLTextValidate::validateInt);
+ mSpecularExponent->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mEnvironmentExponent = findChild<LLLineEditor>("environment_exponent");
+ llassert(mEnvironmentExponent != NULL);
+ mEnvironmentExponent->setPrevalidate(LLTextValidate::validateInt);
+ mEnvironmentExponent->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mAlphaMaskCutoff = findChild<LLLineEditor>("alpha_mask_cutoff");
+ llassert(mAlphaMaskCutoff != NULL);
+ mAlphaMaskCutoff->setPrevalidate(LLTextValidate::validateInt);
+ mAlphaMaskCutoff->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mDiffuseAlphaMode = findChild<LLLineEditor>("diffuse_alpha_mode");
+ llassert(mDiffuseAlphaMode != NULL);
+ mDiffuseAlphaMode->setPrevalidate(LLTextValidate::validateInt);
+ mDiffuseAlphaMode->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onValueEntered, this, _1));
+
+ mPutSetButton = findChild<LLButton>("put_set_button");
+ llassert(mPutSetButton != NULL);
+ mPutSetButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onPutSetClicked, this));
+
+ mPutClearButton = findChild<LLButton>("put_clear_button");
+ llassert(mPutClearButton != NULL);
+ mPutClearButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onPutClearClicked, this));
+
+ LLButton* resetPutValuesButton = findChild<LLButton>("reset_put_values_button");
+ llassert(resetPutValuesButton != NULL);
+ resetPutValuesButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onResetPutValuesClicked, this));
+
+ mPutScrollList = findChild<LLScrollListCtrl>("put_scroll_list");
+ llassert(mPutScrollList != NULL);
+
+ mQueryViewableObjectsButton = findChild<LLButton>("query_viewable_objects_button");
+ llassert(mQueryViewableObjectsButton != NULL);
+ mQueryViewableObjectsButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onQueryVisibleObjectsClicked, this));
+
+ mViewableObjectsScrollList = findChild<LLScrollListCtrl>("viewable_objects_scroll_list");
+ llassert(mViewableObjectsScrollList != NULL);
+
+ mGoodPostButton = findChild<LLButton>("good_post_button");
+ llassert(mGoodPostButton != NULL);
+ mGoodPostButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onGoodPostClicked, this));
+
+ mBadPostButton = findChild<LLButton>("bad_post_button");
+ llassert(mBadPostButton != NULL);
+ mBadPostButton->setCommitCallback(boost::bind(&LLFloaterDebugMaterials::onBadPostClicked, this));
+
+ mPostNormalMapScrollList = findChild<LLScrollListCtrl>("post_normal_map_scroll_list");
+ llassert(mPostNormalMapScrollList != NULL);
+
+ mPostSpecularMapScrollList = findChild<LLScrollListCtrl>("post_specular_map_scroll_list");
+ llassert(mPostSpecularMapScrollList != NULL);
+
+ mPostOtherDataScrollList = findChild<LLScrollListCtrl>("post_other_data_scroll_list");
+ llassert(mPostOtherDataScrollList != NULL);
+
+ mDefaultSpecularColor = LLUIColorTable::instance().getColor("White");
+
+ mWarningColor = LLUIColorTable::instance().getColor("MaterialWarningColor");
+ mErrorColor = LLUIColorTable::instance().getColor("MaterialErrorColor");
+
+ setState(kNoRegion);
+
+ return LLFloater::postBuild();
+}
+
+void LLFloaterDebugMaterials::onOpen(const LLSD& pKey)
+{
+ LLFloater::onOpen(pKey);
+
+ if (!mRegionCrossConnection.connected())
+ {
+ mRegionCrossConnection = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterDebugMaterials::onRegionCross, this));
+ }
+
+ if (!mTeleportFailedConnection.connected())
+ {
+ mTeleportFailedConnection = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLFloaterDebugMaterials::onRegionCross, this));
+ }
+
+ if (!mSelectionUpdateConnection.connected())
+ {
+ mSelectionUpdateConnection = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterDebugMaterials::onInWorldSelectionChange, this));
+ }
+
+ checkRegionMaterialStatus();
+ resetObjectEditInputs();
+ clearGetResults();
+ clearPutResults();
+ clearViewableObjectsResults();
+ clearPostResults();
+}
+
+void LLFloaterDebugMaterials::onClose(bool pIsAppQuitting)
+{
+ resetObjectEditInputs();
+ clearGetResults();
+ clearPutResults();
+ clearViewableObjectsResults();
+ clearPostResults();
+
+ if (mSelectionUpdateConnection.connected())
+ {
+ mSelectionUpdateConnection.disconnect();
+ }
+
+ if (mTeleportFailedConnection.connected())
+ {
+ mTeleportFailedConnection.disconnect();
+ }
+
+ if (mRegionCrossConnection.connected())
+ {
+ mRegionCrossConnection.disconnect();
+ }
+
+ LLFloater::onClose(pIsAppQuitting);
+}
+
+void LLFloaterDebugMaterials::draw()
+{
+ if (mUnparsedGetData.isDefined())
+ {
+ parseGetResponse();
+ }
+ LLFloater::draw();
+}
+
+LLFloaterDebugMaterials::LLFloaterDebugMaterials(const LLSD& pParams)
+ : LLFloater(pParams),
+ mStatusText(NULL),
+ mGetButton(NULL),
+ mParsingStatusText(NULL),
+ mGetNormalMapScrollList(NULL),
+ mGetSpecularMapScrollList(NULL),
+ mGetOtherDataScrollList(NULL),
+ mNormalMap(NULL),
+ mNormalMapOffsetX(NULL),
+ mNormalMapOffsetY(NULL),
+ mNormalMapRepeatX(NULL),
+ mNormalMapRepeatY(NULL),
+ mNormalMapRotation(NULL),
+ mSpecularMap(NULL),
+ mSpecularMapOffsetX(NULL),
+ mSpecularMapOffsetY(NULL),
+ mSpecularMapRepeatX(NULL),
+ mSpecularMapRepeatY(NULL),
+ mSpecularMapRotation(NULL),
+ mSpecularColor(NULL),
+ mSpecularColorAlpha(NULL),
+ mSpecularExponent(NULL),
+ mEnvironmentExponent(NULL),
+ mAlphaMaskCutoff(NULL),
+ mDiffuseAlphaMode(NULL),
+ mPutSetButton(NULL),
+ mPutClearButton(NULL),
+ mPutScrollList(NULL),
+ mQueryViewableObjectsButton(NULL),
+ mViewableObjectsScrollList(NULL),
+ mGoodPostButton(NULL),
+ mBadPostButton(NULL),
+ mPostNormalMapScrollList(NULL),
+ mPostSpecularMapScrollList(NULL),
+ mPostOtherDataScrollList(NULL),
+ mState(kNoRegion),
+ mWarningColor(),
+ mErrorColor(),
+ mRegionCrossConnection(),
+ mTeleportFailedConnection(),
+ mSelectionUpdateConnection(),
+ mUnparsedGetData(),
+ mNextUnparsedGetDataIndex(-1)
+{
+}
+
+LLFloaterDebugMaterials::~LLFloaterDebugMaterials()
+{
+}
+
+void LLFloaterDebugMaterials::onGetClicked()
+{
+ requestGetMaterials();
+}
+
+void LLFloaterDebugMaterials::onValueEntered(LLUICtrl* pUICtrl)
+{
+ LLLineEditor *pLineEditor = static_cast<LLLineEditor *>(pUICtrl);
+ llassert(pLineEditor != NULL);
+
+ const std::string &valueString = pLineEditor->getText();
+
+ S32 intValue = 0;
+ bool doResetValue = (!valueString.empty() && !LLStringUtil::convertToS32(valueString, intValue));
+
+ if (doResetValue)
+ {
+ LL_WARNS("debugMaterials") << "cannot parse string '" << valueString << "' to an S32 value" <<LL_ENDL;
+ LLSD value = static_cast<LLSD::Integer>(intValue);
+ pLineEditor->setValue(value);
+ }
+}
+
+void LLFloaterDebugMaterials::onPutSetClicked()
+{
+ requestPutMaterials(true);
+}
+
+void LLFloaterDebugMaterials::onPutClearClicked()
+{
+ requestPutMaterials(false);
+}
+
+void LLFloaterDebugMaterials::onResetPutValuesClicked()
+{
+ resetObjectEditInputs();
+}
+
+void LLFloaterDebugMaterials::onQueryVisibleObjectsClicked()
+{
+ queryViewableObjects();
+}
+
+void LLFloaterDebugMaterials::onGoodPostClicked()
+{
+ requestPostMaterials(true);
+}
+
+void LLFloaterDebugMaterials::onBadPostClicked()
+{
+ requestPostMaterials(false);
+}
+
+void LLFloaterDebugMaterials::onRegionCross()
+{
+ checkRegionMaterialStatus();
+ clearGetResults();
+ clearPutResults();
+ clearViewableObjectsResults();
+ clearPostResults();
+}
+
+void LLFloaterDebugMaterials::onInWorldSelectionChange()
+{
+ updateControls();
+}
+
+void LLFloaterDebugMaterials::onGetScrollListSelectionChange(LLUICtrl* pUICtrl)
+{
+ LLScrollListCtrl* scrollListCtrl = dynamic_cast<LLScrollListCtrl*>(pUICtrl);
+ llassert(scrollListCtrl != NULL);
+
+ if (scrollListCtrl != mGetNormalMapScrollList)
+ {
+ mGetNormalMapScrollList->deselectAllItems(TRUE);
+ }
+ if (scrollListCtrl != mGetSpecularMapScrollList)
+ {
+ mGetSpecularMapScrollList->deselectAllItems(TRUE);
+ }
+ if (scrollListCtrl != mGetOtherDataScrollList)
+ {
+ mGetOtherDataScrollList->deselectAllItems(TRUE);
+ }
+
+ std::vector<LLScrollListItem*> selectedItems = scrollListCtrl->getAllSelected();
+ if (!selectedItems.empty())
+ {
+ llassert(selectedItems.size() == 1);
+ LLScrollListItem* selectedItem = selectedItems.front();
+
+ llassert(selectedItem != NULL);
+ const LLSD& selectedIdValue = selectedItem->getValue();
+
+ if (scrollListCtrl != mGetNormalMapScrollList)
+ {
+ mGetNormalMapScrollList->selectByValue(selectedIdValue);
+ }
+ if (scrollListCtrl != mGetSpecularMapScrollList)
+ {
+ mGetSpecularMapScrollList->selectByValue(selectedIdValue);
+ }
+ if (scrollListCtrl != mGetOtherDataScrollList)
+ {
+ mGetOtherDataScrollList->selectByValue(selectedIdValue);
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::onDeferredCheckRegionMaterialStatus(LLUUID regionId)
+{
+ checkRegionMaterialStatus(regionId);
+}
+
+void LLFloaterDebugMaterials::onDeferredRequestGetMaterials(LLUUID regionId)
+{
+ requestGetMaterials(regionId);
+}
+
+void LLFloaterDebugMaterials::onDeferredRequestPutMaterials(LLUUID regionId, bool pIsDoSet)
+{
+ requestPutMaterials(regionId, pIsDoSet);
+}
+
+void LLFloaterDebugMaterials::onDeferredRequestPostMaterials(LLUUID regionId, bool pUseGoodData)
+{
+ requestPostMaterials(regionId, pUseGoodData);
+}
+
+void LLFloaterDebugMaterials::onGetResponse(bool pRequestStatus, const LLSD& pContent)
+{
+ clearGetResults();
+ if (pRequestStatus)
+ {
+ setState(kRequestCompleted);
+ setUnparsedGetData(pContent);
+ }
+ else
+ {
+ setState(kError);
+ }
+}
+
+void LLFloaterDebugMaterials::onPutResponse(bool pRequestStatus, const LLSD& pContent)
+{
+ if (pRequestStatus)
+ {
+ setState(kRequestCompleted);
+ parsePutResponse(pContent);
+ }
+ else
+ {
+ setState(kError);
+ }
+}
+
+void LLFloaterDebugMaterials::onPostResponse(bool pRequestStatus, const LLSD& pContent)
+{
+ if (pRequestStatus)
+ {
+ setState(kRequestCompleted);
+ parsePostResponse(pContent);
+ }
+ else
+ {
+ setState(kError);
+ }
+}
+
+void LLFloaterDebugMaterials::checkRegionMaterialStatus()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+
+ if (region == NULL)
+ {
+ LL_WARNS("debugMaterials") << "Region is NULL" << LL_ENDL;
+ setState(kNoRegion);
+ }
+ else if (!region->capabilitiesReceived())
+ {
+ setState(kCapabilitiesLoading);
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterDebugMaterials::onDeferredCheckRegionMaterialStatus, this, region->getRegionID()));
+ }
+ else
+ {
+ std::string capURL = region->getCapability(MATERIALS_CAPABILITY_NAME);
+
+ if (capURL.empty())
+ {
+ LL_WARNS("debugMaterials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on the current region '" << region->getName() << "'" << LL_ENDL;
+ setState(kNotEnabled);
+ }
+ else
+ {
+ setState(kReady);
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::checkRegionMaterialStatus(const LLUUID& regionId)
+{
+ const LLViewerRegion *region = gAgent.getRegion();
+
+ if ((region != NULL) && (region->getRegionID() == regionId))
+ {
+ checkRegionMaterialStatus();
+ }
+}
+
+void LLFloaterDebugMaterials::requestGetMaterials()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+
+ if (region == NULL)
+ {
+ LL_WARNS("debugMaterials") << "Region is NULL" << LL_ENDL;
+ setState(kNoRegion);
+ }
+ else if (!region->capabilitiesReceived())
+ {
+ setState(kCapabilitiesLoading);
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterDebugMaterials::onDeferredRequestGetMaterials, this, region->getRegionID()));
+ }
+ else
+ {
+ std::string capURL = region->getCapability(MATERIALS_CAPABILITY_NAME);
+
+ if (capURL.empty())
+ {
+ LL_WARNS("debugMaterials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on the current region '" << region->getName() << "'" << LL_ENDL;
+ setState(kNotEnabled);
+ }
+ else
+ {
+ setState(kRequestStarted);
+ LLHTTPClient::ResponderPtr materialsResponder = new MaterialsResponder("GET", capURL, boost::bind(&LLFloaterDebugMaterials::onGetResponse, this, _1, _2));
+ LLHTTPClient::get(capURL, materialsResponder);
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::requestGetMaterials(const LLUUID& regionId)
+{
+ const LLViewerRegion *region = gAgent.getRegion();
+
+ if ((region != NULL) && (region->getRegionID() == regionId))
+ {
+ requestGetMaterials();
+ }
+}
+
+void LLFloaterDebugMaterials::requestPutMaterials(bool pIsDoSet)
+{
+ LLViewerRegion *region = gAgent.getRegion();
+
+ if (region == NULL)
+ {
+ LL_WARNS("debugMaterials") << "Region is NULL" << LL_ENDL;
+ setState(kNoRegion);
+ }
+ else if (!region->capabilitiesReceived())
+ {
+ setState(kCapabilitiesLoading);
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterDebugMaterials::onDeferredRequestPutMaterials, this, region->getRegionID(), pIsDoSet));
+ }
+ else
+ {
+ std::string capURL = region->getCapability(MATERIALS_CAPABILITY_NAME);
+
+ if (capURL.empty())
+ {
+ LL_WARNS("debugMaterials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on the current region '" << region->getName() << "'" << LL_ENDL;
+ setState(kNotEnabled);
+ }
+ else
+ {
+ setState(kRequestStarted);
+
+ LLSD facesData = LLSD::emptyArray();
+
+ LLSD materialData = LLSD::emptyMap();
+ if (pIsDoSet)
+ {
+ materialData[MATERIALS_CAP_NORMAL_MAP_FIELD] = mNormalMap->getImageAssetID();
+ materialData[MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD] = static_cast<LLSD::Integer>(getNormalMapOffsetX());
+ materialData[MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD] = static_cast<LLSD::Integer>(getNormalMapOffsetY());
+ materialData[MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD] = static_cast<LLSD::Integer>(getNormalMapRepeatX());
+ materialData[MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD] = static_cast<LLSD::Integer>(getNormalMapRepeatY());
+ materialData[MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD] = static_cast<LLSD::Integer>(getNormalMapRotation());
+
+ materialData[MATERIALS_CAP_SPECULAR_MAP_FIELD] = mSpecularMap->getImageAssetID();
+ materialData[MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD] = static_cast<LLSD::Integer>(getSpecularMapOffsetX());
+ materialData[MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD] = static_cast<LLSD::Integer>(getSpecularMapOffsetY());
+ materialData[MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD] = static_cast<LLSD::Integer>(getSpecularMapRepeatX());
+ materialData[MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD] = static_cast<LLSD::Integer>(getSpecularMapRepeatY());
+ materialData[MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD] = static_cast<LLSD::Integer>(getSpecularMapRotation());
+
+ LLColor4U specularColor = getSpecularColor();
+ materialData[MATERIALS_CAP_SPECULAR_COLOR_FIELD] = specularColor.getValue();
+ materialData[MATERIALS_CAP_SPECULAR_EXP_FIELD] = static_cast<LLSD::Integer>(getSpecularExponent());
+ materialData[MATERIALS_CAP_ENV_INTENSITY_FIELD] = static_cast<LLSD::Integer>(getEnvironmentExponent());
+ materialData[MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD] = static_cast<LLSD::Integer>(getAlphMaskCutoff());
+ materialData[MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD] = static_cast<LLSD::Integer>(getDiffuseAlphaMode());
+ }
+
+ LLObjectSelectionHandle selectionHandle = LLSelectMgr::getInstance()->getEditSelection();
+ for (LLObjectSelection::valid_iterator objectIter = selectionHandle->valid_begin();
+ objectIter != selectionHandle->valid_end(); ++objectIter)
+ {
+ LLSelectNode* objectNode = *objectIter;
+ LLViewerObject* viewerObject = objectNode->getObject();
+
+ if (viewerObject != NULL)
+ {
+ const LLViewerRegion* viewerRegion = viewerObject->getRegion();
+ if (region != viewerRegion)
+ {
+ LL_ERRS("debugMaterials") << "cannot currently edit an object on a different region through the debug materials floater" << llendl;
+ }
+ S32 numTEs = llmin(static_cast<S32>(viewerObject->getNumTEs()), viewerObject->getNumFaces());
+ for (S32 curTEIndex = 0; curTEIndex < numTEs; ++curTEIndex)
+ {
+ if (objectNode->isTESelected(curTEIndex))
+ {
+ LLSD faceData = LLSD::emptyMap();
+ faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(curTEIndex);
+ faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(viewerObject->getLocalID());
+ if (pIsDoSet)
+ {
+ faceData[MATERIALS_CAP_MATERIAL_FIELD] = materialData;
+ }
+ facesData.append(faceData);
+ }
+ }
+ }
+ }
+
+ LLSD materialsData = LLSD::emptyMap();
+ materialsData[MATERIALS_CAP_FULL_PER_FACE_FIELD] = facesData;
+
+ std::string materialString = zip_llsd(materialsData);
+ S32 materialSize = materialString.size();
+
+ if (materialSize <= 0)
+ {
+ LL_ERRS("debugMaterials") << "cannot zip LLSD binary content" << LL_ENDL;
+ }
+ else
+ {
+ LLSD::Binary materialBinary;
+ materialBinary.resize(materialSize);
+ memcpy(materialBinary.data(), materialString.data(), materialSize);
+
+ LLSD putData = LLSD::emptyMap();
+ putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
+
+ LLHTTPClient::ResponderPtr materialsResponder = new MaterialsResponder("PUT", capURL, boost::bind(&LLFloaterDebugMaterials::onPutResponse, this, _1, _2));
+ LLHTTPClient::put(capURL, putData, materialsResponder);
+ }
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::requestPutMaterials(const LLUUID& regionId, bool pIsDoSet)
+{
+ const LLViewerRegion *region = gAgent.getRegion();
+
+ if ((region != NULL) && (region->getRegionID() == regionId))
+ {
+ requestPutMaterials(pIsDoSet);
+ }
+}
+
+void LLFloaterDebugMaterials::requestPostMaterials(bool pUseGoodData)
+{
+#if 0
+ LLViewerRegion *region = gAgent.getRegion();
+
+ if (region == NULL)
+ {
+ LL_WARNS("debugMaterials") << "Region is NULL" << LL_ENDL;
+ setState(kNoRegion);
+ }
+ else if (!region->capabilitiesReceived())
+ {
+ setState(kCapabilitiesLoading);
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterDebugMaterials::onDeferredRequestPostMaterials, this, region->getRegionID(), pUseGoodData));
+ }
+ else
+ {
+ std::string capURL = region->getCapability(MATERIALS_CAPABILITY_NAME);
+
+ if (capURL.empty())
+ {
+ LL_WARNS("debugMaterials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on the current region '" << region->getName() << "'" << LL_ENDL;
+ setState(kNotEnabled);
+ }
+ else
+ {
+ setState(kRequestStarted);
+ LLSD postData = LLSD::emptyArray();
+
+ if (pUseGoodData)
+ {
+ std::vector<LLScrollListItem*> selectedItems = mGetScrollList->getAllSelected();
+ for (std::vector<LLScrollListItem*>::const_iterator selectedItemIter = selectedItems.begin();
+ selectedItemIter != selectedItems.end(); ++selectedItemIter)
+ {
+ const LLScrollListItem* selectedItem = *selectedItemIter;
+ postData.append(selectedItem->getValue());
+ }
+ }
+ else
+ {
+ S32 crapArray[4];
+ for (int i = 0; i < 4; ++i)
+ {
+ crapArray[i] = ll_rand();
+ if (ll_frand() < 0.5)
+ {
+ crapArray[i] = -crapArray[i];
+ }
+ }
+
+ std::vector<unsigned char> crapMem;
+ crapMem.resize(16);
+ memcpy(&crapMem[0], &crapArray, 16 * sizeof(unsigned char));
+
+ LLSD::Binary crapBinary = crapMem;
+ LLSD crapData = crapBinary;
+ postData.append(crapData);
+ }
+
+ LLHTTPClient::ResponderPtr materialsResponder = new MaterialsResponder("POST", capURL, boost::bind(&LLFloaterDebugMaterials::onPostResponse, this, _1, _2));
+ LLHTTPClient::post(capURL, postData, materialsResponder);
+ }
+ }
+#endif
+}
+
+void LLFloaterDebugMaterials::requestPostMaterials(const LLUUID& regionId, bool pUseGoodData)
+{
+ const LLViewerRegion *region = gAgent.getRegion();
+
+ if ((region != NULL) && (region->getRegionID() == regionId))
+ {
+ requestPostMaterials(pUseGoodData);
+ }
+}
+
+void LLFloaterDebugMaterials::queryViewableObjects()
+{
+ clearViewableObjectsResults();
+
+ LLScrollListCell::Params cellParams;
+ LLScrollListItem::Params rowParams;
+
+ S32 numViewerObjects = gObjectList.getNumObjects();
+ for (S32 viewerObjectIndex = 0; viewerObjectIndex < numViewerObjects; ++viewerObjectIndex)
+ {
+ const LLViewerObject *viewerObject = gObjectList.getObject(viewerObjectIndex);
+ if ((viewerObject != NULL) && !viewerObject->isDead())
+ {
+ U8 objectNumTEs = viewerObject->getNumTEs();
+
+ if (objectNumTEs > 0U)
+ {
+ const LLUUID& objectId = viewerObject->getID();
+ U32 objectLocalId = viewerObject->getLocalID();
+ const LLViewerRegion* objectRegion = viewerObject->getRegion();
+
+ for (U8 curTEIndex = 0U; curTEIndex < objectNumTEs; ++curTEIndex)
+ {
+ const LLTextureEntry* objectTE = viewerObject->getTE(curTEIndex);
+ llassert(objectTE != NULL);
+ const LLMaterialID& objectMaterialID = objectTE->getMaterialID();
+ if (!objectMaterialID.isNull())
+ {
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ cellParams.column = "object_id";
+ cellParams.value = objectId.asString();
+ rowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontSansSerif();
+
+ cellParams.column = "region";
+ cellParams.value = ((objectRegion == NULL) ? "<null>" : objectRegion->getName());
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "local_id";
+ cellParams.value = llformat("%d", objectLocalId);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "face_index";
+ cellParams.value = llformat("%u", static_cast<unsigned int>(curTEIndex));
+ rowParams.columns.add(cellParams);
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ std::string materialIDString = convertToPrintableMaterialID(objectMaterialID);
+ cellParams.column = "material_id";
+ cellParams.value = materialIDString;
+ rowParams.columns.add(cellParams);
+
+ rowParams.value = objectId;
+
+ mViewableObjectsScrollList->addRow(rowParams);
+ }
+ }
+ }
+
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::parseGetResponse()
+{
+ llassert(mUnparsedGetData.isDefined());
+ llassert(mNextUnparsedGetDataIndex >= 0);
+
+ if (mUnparsedGetData.isDefined())
+ {
+ LLScrollListCell::Params cellParams;
+ LLScrollListItem::Params normalMapRowParams;
+ LLScrollListItem::Params specularMapRowParams;
+ LLScrollListItem::Params otherDataRowParams;
+
+ llassert(mUnparsedGetData.isArray());
+ LLSD::array_const_iterator materialIter = mUnparsedGetData.beginArray();
+ S32 materialIndex;
+
+ for (materialIndex = 0;
+ (materialIndex < mNextUnparsedGetDataIndex) && (materialIter != mUnparsedGetData.endArray());
+ ++materialIndex, ++materialIter)
+ {
+ }
+
+ for (S32 currentParseCount = 0;
+ (currentParseCount < 10) && (materialIter != mUnparsedGetData.endArray());
+ ++currentParseCount, ++materialIndex, ++materialIter)
+ {
+ const LLSD &material = *materialIter;
+ llassert(material.isMap());
+ llassert(material.has(MATERIALS_CAP_OBJECT_ID_FIELD));
+ llassert(material.get(MATERIALS_CAP_OBJECT_ID_FIELD).isBinary());
+ const LLSD &materialID = material.get(MATERIALS_CAP_OBJECT_ID_FIELD);
+ std::string materialIDString = convertToPrintableMaterialID(materialID);
+
+ llassert(material.has(MATERIALS_CAP_MATERIAL_FIELD));
+ const LLSD &materialData = material.get(MATERIALS_CAP_MATERIAL_FIELD);
+ llassert(materialData.isMap());
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_FIELD).isUUID());
+ const LLUUID &normalMapID = materialData.get(MATERIALS_CAP_NORMAL_MAP_FIELD).asUUID();
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD).isInteger());
+ S32 normalMapOffsetX = materialData.get(MATERIALS_CAP_NORMAL_MAP_OFFSET_X_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD).isInteger());
+ S32 normalMapOffsetY = materialData.get(MATERIALS_CAP_NORMAL_MAP_OFFSET_Y_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD).isInteger());
+ S32 normalMapRepeatX = materialData.get(MATERIALS_CAP_NORMAL_MAP_REPEAT_X_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD).isInteger());
+ S32 normalMapRepeatY = materialData.get(MATERIALS_CAP_NORMAL_MAP_REPEAT_Y_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD).isInteger());
+ S32 normalMapRotation = materialData.get(MATERIALS_CAP_NORMAL_MAP_ROTATION_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_FIELD).isUUID());
+ const LLUUID &specularMapID = materialData.get(MATERIALS_CAP_SPECULAR_MAP_FIELD).asUUID();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD).isInteger());
+ S32 specularMapOffsetX = materialData.get(MATERIALS_CAP_SPECULAR_MAP_OFFSET_X_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD).isInteger());
+ S32 specularMapOffsetY = materialData.get(MATERIALS_CAP_SPECULAR_MAP_OFFSET_Y_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD).isInteger());
+ S32 specularMapRepeatX = materialData.get(MATERIALS_CAP_SPECULAR_MAP_REPEAT_X_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD).isInteger());
+ S32 specularMapRepeatY = materialData.get(MATERIALS_CAP_SPECULAR_MAP_REPEAT_Y_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD).isInteger());
+ S32 specularMapRotation = materialData.get(MATERIALS_CAP_SPECULAR_MAP_ROTATION_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_COLOR_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_COLOR_FIELD).isArray());
+ LLColor4U specularColor;
+ specularColor.setValue(materialData.get(MATERIALS_CAP_SPECULAR_COLOR_FIELD));
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_EXP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_EXP_FIELD).isInteger());
+ S32 specularExp = materialData.get(MATERIALS_CAP_SPECULAR_EXP_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_ENV_INTENSITY_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_ENV_INTENSITY_FIELD).isInteger());
+ S32 envIntensity = materialData.get(MATERIALS_CAP_ENV_INTENSITY_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD).isInteger());
+ S32 alphaMaskCutoff = materialData.get(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD).isInteger());
+ S32 diffuseAlphaMode = materialData.get(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD).asInteger();
+
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ cellParams.column = "id";
+ cellParams.value = materialIDString;
+ normalMapRowParams.columns.add(cellParams);
+ specularMapRowParams.columns.add(cellParams);
+ otherDataRowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map_list_map";
+ cellParams.value = normalMapID.asString();
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontSansSerif();
+
+ cellParams.column = "normal_map_list_offset_x";
+ cellParams.value = llformat("%d", normalMapOffsetX);
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map_list_offset_y";
+ cellParams.value = llformat("%d", normalMapOffsetY);
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map_list_repeat_x";
+ cellParams.value = llformat("%d", normalMapRepeatX);
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map_list_repeat_y";
+ cellParams.value = llformat("%d", normalMapRepeatY);
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map_list_rotation";
+ cellParams.value = llformat("%d", normalMapRotation);
+ normalMapRowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ cellParams.column = "specular_map_list_map";
+ cellParams.value = specularMapID.asString();
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontSansSerif();
+
+ cellParams.column = "specular_map_list_offset_x";
+ cellParams.value = llformat("%d", specularMapOffsetX);
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_map_list_offset_y";
+ cellParams.value = llformat("%d", specularMapOffsetY);
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_map_list_repeat_x";
+ cellParams.value = llformat("%d", specularMapRepeatX);
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_map_list_repeat_y";
+ cellParams.value = llformat("%d", specularMapRepeatY);
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_map_list_rotation";
+ cellParams.value = llformat("%d", specularMapRotation);
+ specularMapRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_color";
+ cellParams.value = llformat("(%d, %d, %d, %d)", specularColor.mV[0],
+ specularColor.mV[1], specularColor.mV[2], specularColor.mV[3]);
+ otherDataRowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_exponent";
+ cellParams.value = llformat("%d", specularExp);
+ otherDataRowParams.columns.add(cellParams);
+
+ cellParams.column = "env_intensity";
+ cellParams.value = llformat("%d", envIntensity);
+ otherDataRowParams.columns.add(cellParams);
+
+ cellParams.column = "alpha_mask_cutoff";
+ cellParams.value = llformat("%d", alphaMaskCutoff);
+ otherDataRowParams.columns.add(cellParams);
+
+ cellParams.column = "diffuse_alpha_mode";
+ cellParams.value = llformat("%d", diffuseAlphaMode);
+ otherDataRowParams.columns.add(cellParams);
+
+ normalMapRowParams.value = materialIDString;
+ specularMapRowParams.value = materialIDString;
+ otherDataRowParams.value = materialIDString;
+
+ mGetNormalMapScrollList->addRow(normalMapRowParams);
+ mGetSpecularMapScrollList->addRow(specularMapRowParams);
+ mGetOtherDataScrollList->addRow(otherDataRowParams);
+ }
+
+ if (materialIter != mUnparsedGetData.endArray())
+ {
+ mNextUnparsedGetDataIndex = materialIndex;
+ updateGetParsingStatus();
+ }
+ else
+ {
+ clearUnparsedGetData();
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::parsePutResponse(const LLSD& pContent)
+{
+ clearPutResults();
+
+ LLScrollListCell::Params cellParams;
+ LLScrollListItem::Params rowParams;
+
+ llassert(pContent.isMap());
+ llassert(pContent.has(MATERIALS_CAP_ZIP_FIELD));
+ llassert(pContent.get(MATERIALS_CAP_ZIP_FIELD).isBinary());
+
+ LLSD::Binary responseBinary = pContent.get(MATERIALS_CAP_ZIP_FIELD).asBinary();
+ S32 responseSize = static_cast<S32>(responseBinary.size());
+ std::string responseString(reinterpret_cast<const char*>(responseBinary.data()), responseSize);
+
+ std::istringstream responseStream(responseString);
+
+ LLSD responseContent;
+ if (!unzip_llsd(responseContent, responseStream, responseSize))
+ {
+ LL_ERRS("debugMaterials") << "cannot unzip LLSD binary content" << LL_ENDL;
+ }
+ else
+ {
+ llassert(responseContent.isArray());
+ for (LLSD::array_const_iterator faceIter = responseContent.beginArray(); faceIter != responseContent.endArray();
+ ++faceIter)
+ {
+ const LLSD &face = *faceIter;
+ llassert(face.isMap());
+
+ llassert(face.has(MATERIALS_CAP_FACE_FIELD));
+ llassert(face.get(MATERIALS_CAP_FACE_FIELD).isInteger());
+ S32 faceId = face.get(MATERIALS_CAP_FACE_FIELD).asInteger();
+
+ llassert(face.has(MATERIALS_CAP_OBJECT_ID_FIELD));
+ llassert(face.get(MATERIALS_CAP_OBJECT_ID_FIELD).isInteger());
+ S32 objectId = face.get(MATERIALS_CAP_OBJECT_ID_FIELD).asInteger();
+
+ llassert(face.has(MATERIALS_CAP_MATERIAL_ID_FIELD));
+ llassert(face.get(MATERIALS_CAP_MATERIAL_ID_FIELD).isBinary());
+ std::string materialIDString = convertToPrintableMaterialID(face.get(MATERIALS_CAP_MATERIAL_ID_FIELD));
+
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ cellParams.column = "material_id";
+ cellParams.value = materialIDString;
+ rowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontSansSerif();
+
+ cellParams.column = "object_id";
+ cellParams.value = llformat("%d", objectId);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "face_index";
+ cellParams.value = llformat("%d", faceId);
+ rowParams.columns.add(cellParams);
+
+ mPutScrollList->addRow(rowParams);
+ }
+ }
+}
+
+void LLFloaterDebugMaterials::parsePostResponse(const LLSD& pContent)
+{
+#if 0
+ clearPostResults();
+
+ LLScrollListCell::Params cellParams;
+ LLScrollListItem::Params rowParams;
+
+ llassert(pContent.isArray());
+ for (LLSD::array_const_iterator materialIter = pContent.beginArray(); materialIter != pContent.endArray();
+ ++materialIter)
+ {
+ const LLSD &material = *materialIter;
+ llassert(material.isMap());
+ llassert(material.has(MATERIALS_CAP_OBJECT_ID_FIELD));
+ llassert(material.get(MATERIALS_CAP_OBJECT_ID_FIELD).isBinary());
+ const LLSD &materialID = material.get(MATERIALS_CAP_OBJECT_ID_FIELD);
+ std::string materialIDString = convertToPrintableMaterialID(materialID);
+
+ llassert(material.has(MATERIALS_CAP_MATERIAL_FIELD));
+ const LLSD &materialData = material.get(MATERIALS_CAP_MATERIAL_FIELD);
+ llassert(materialData.isMap());
+
+ llassert(materialData.has(MATERIALS_CAP_NORMAL_MAP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_NORMAL_MAP_FIELD).isUUID());
+ const LLUUID &normalMapID = materialData.get(MATERIALS_CAP_NORMAL_MAP_FIELD).asUUID();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_MAP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_MAP_FIELD).isUUID());
+ const LLUUID &specularMapID = materialData.get(MATERIALS_CAP_SPECULAR_MAP_FIELD).asUUID();
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_COLOR_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_COLOR_FIELD).isArray());
+ LLColor4U specularColor;
+ specularColor.setValue(materialData.get(MATERIALS_CAP_SPECULAR_COLOR_FIELD));
+
+ llassert(materialData.has(MATERIALS_CAP_SPECULAR_EXP_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_SPECULAR_EXP_FIELD).isInteger());
+ S32 specularExp = materialData.get(MATERIALS_CAP_SPECULAR_EXP_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_ENV_INTENSITY_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_ENV_INTENSITY_FIELD).isInteger());
+ S32 envIntensity = materialData.get(MATERIALS_CAP_ENV_INTENSITY_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD).isInteger());
+ S32 alphaMaskCutoff = materialData.get(MATERIALS_CAP_ALPHA_MASK_CUTOFF_FIELD).asInteger();
+
+ llassert(materialData.has(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD));
+ llassert(materialData.get(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD).isInteger());
+ S32 diffuseAlphaMode = materialData.get(MATERIALS_CAP_DIFFUSE_ALPHA_MODE_FIELD).asInteger();
+
+
+ cellParams.font = LLFontGL::getFontMonospace();
+
+ cellParams.column = "id";
+ cellParams.value = materialIDString;
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "normal_map";
+ cellParams.value = normalMapID.asString();
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_map";
+ cellParams.value = specularMapID.asString();
+ rowParams.columns.add(cellParams);
+
+ cellParams.font = LLFontGL::getFontSansSerif();
+
+ cellParams.column = "specular_color";
+ cellParams.value = llformat("(%d, %d, %d, %d)", specularColor.mV[0],
+ specularColor.mV[1], specularColor.mV[2], specularColor.mV[3]);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "specular_exponent";
+ cellParams.value = llformat("%d", specularExp);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "env_intensity";
+ cellParams.value = llformat("%d", envIntensity);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "alpha_mask_cutoff";
+ cellParams.value = llformat("%d", alphaMaskCutoff);
+ rowParams.columns.add(cellParams);
+
+ cellParams.column = "diffuse_alpha_mode";
+ cellParams.value = llformat("%d", diffuseAlphaMode);
+ rowParams.columns.add(cellParams);
+ rowParams.value = materialID;
+
+ mPostScrollList->addRow(rowParams);
+ }
+#endif
+}
+
+void LLFloaterDebugMaterials::setState(EState pState)
+{
+ mState = pState;
+ updateStatusMessage();
+ updateControls();
+}
+
+void LLFloaterDebugMaterials::resetObjectEditInputs()
+{
+ const LLSD zeroValue = static_cast<LLSD::Integer>(0);
+ const LLSD maxAlphaValue = static_cast<LLSD::Integer>(255);
+
+ mNormalMap->clear();
+ mNormalMapOffsetX->setValue(zeroValue);
+ mNormalMapOffsetY->setValue(zeroValue);
+ mNormalMapRepeatX->setValue(zeroValue);
+ mNormalMapRepeatY->setValue(zeroValue);
+ mNormalMapRotation->setValue(zeroValue);
+
+ mSpecularMap->clear();
+ mSpecularMapOffsetX->setValue(zeroValue);
+ mSpecularMapOffsetY->setValue(zeroValue);
+ mSpecularMapRepeatX->setValue(zeroValue);
+ mSpecularMapRepeatY->setValue(zeroValue);
+ mSpecularMapRotation->setValue(zeroValue);
+
+ mSpecularColor->set(mDefaultSpecularColor);
+ mSpecularColorAlpha->setValue(maxAlphaValue);
+ mSpecularExponent->setValue(zeroValue);
+ mEnvironmentExponent->setValue(zeroValue);
+ mAlphaMaskCutoff->setValue(zeroValue);
+ mDiffuseAlphaMode->setValue(zeroValue);
+}
+
+void LLFloaterDebugMaterials::clearGetResults()
+{
+ mGetNormalMapScrollList->deleteAllItems();
+ mGetSpecularMapScrollList->deleteAllItems();
+ mGetOtherDataScrollList->deleteAllItems();
+ clearUnparsedGetData();
+}
+
+void LLFloaterDebugMaterials::clearPutResults()
+{
+ mPutScrollList->deleteAllItems();
+}
+
+void LLFloaterDebugMaterials::clearPostResults()
+{
+ mPostNormalMapScrollList->deleteAllItems();
+ mPostSpecularMapScrollList->deleteAllItems();
+ mPostOtherDataScrollList->deleteAllItems();
+}
+
+void LLFloaterDebugMaterials::clearViewableObjectsResults()
+{
+ mViewableObjectsScrollList->deleteAllItems();
+}
+
+void LLFloaterDebugMaterials::setUnparsedGetData(const LLSD& pGetData)
+{
+ llassert(pGetData.isMap());
+ llassert(pGetData.has(MATERIALS_CAP_ZIP_FIELD));
+ llassert(pGetData.get(MATERIALS_CAP_ZIP_FIELD).isBinary());
+
+ LLSD::Binary getDataBinary = pGetData.get(MATERIALS_CAP_ZIP_FIELD).asBinary();
+ S32 getDataSize = static_cast<S32>(getDataBinary.size());
+ std::string getDataString(reinterpret_cast<const char*>(getDataBinary.data()), getDataSize);
+
+ std::istringstream getDataStream(getDataString);
+
+ llassert(!mUnparsedGetData.isDefined());
+ if (!unzip_llsd(mUnparsedGetData, getDataStream, getDataSize))
+ {
+ LL_ERRS("debugMaterials") << "cannot unzip LLSD binary content" << LL_ENDL;
+ }
+ mNextUnparsedGetDataIndex = 0;
+
+ updateGetParsingStatus();
+}
+
+void LLFloaterDebugMaterials::clearUnparsedGetData()
+{
+ mUnparsedGetData.clear();
+ mNextUnparsedGetDataIndex = -1;
+
+ updateGetParsingStatus();
+}
+
+void LLFloaterDebugMaterials::updateGetParsingStatus()
+{
+ std::string parsingStatus;
+
+ if (mUnparsedGetData.isDefined())
+ {
+ LLLocale locale(LLStringUtil::getLocale());
+ std::string numProcessedString;
+ LLResMgr::getInstance()->getIntegerString(numProcessedString, mNextUnparsedGetDataIndex);
+
+ std::string numTotalString;
+ LLResMgr::getInstance()->getIntegerString(numTotalString, mUnparsedGetData.size());
+
+ LLStringUtil::format_map_t stringArgs;
+ stringArgs["[NUM_PROCESSED]"] = numProcessedString;
+ stringArgs["[NUM_TOTAL]"] = numTotalString;
+
+ parsingStatus = getString("loading_status_in_progress", stringArgs);
+ }
+ else
+ {
+ parsingStatus = getString("loading_status_done");
+ }
+
+ mParsingStatusText->setText(static_cast<const LLStringExplicit>(parsingStatus));
+}
+
+void LLFloaterDebugMaterials::updateStatusMessage()
+{
+ std::string statusText;
+ LLStyle::Params styleParams;
+
+ switch (getState())
+ {
+ case kNoRegion :
+ statusText = getString("status_no_region");
+ styleParams.color = mErrorColor;
+ break;
+ case kCapabilitiesLoading :
+ statusText = getString("status_capabilities_loading");
+ styleParams.color = mWarningColor;
+ break;
+ case kReady :
+ statusText = getString("status_ready");
+ break;
+ case kRequestStarted :
+ statusText = getString("status_request_started");
+ styleParams.color = mWarningColor;
+ break;
+ case kRequestCompleted :
+ statusText = getString("status_request_completed");
+ break;
+ case kNotEnabled :
+ statusText = getString("status_not_enabled");
+ styleParams.color = mErrorColor;
+ break;
+ case kError :
+ statusText = getString("status_error");
+ styleParams.color = mErrorColor;
+ break;
+ default :
+ statusText = getString("status_ready");
+ llassert(0);
+ break;
+ }
+
+ mStatusText->setText((LLStringExplicit)statusText, styleParams);
+}
+
+void LLFloaterDebugMaterials::updateControls()
+{
+ LLObjectSelectionHandle selectionHandle = LLSelectMgr::getInstance()->getEditSelection();
+ bool isPutEnabled = (selectionHandle->valid_begin() != selectionHandle->valid_end());
+
+ bool isGoodPostEnabled = false;
+
+ switch (getState())
+ {
+ case kNoRegion :
+ case kCapabilitiesLoading :
+ case kRequestStarted :
+ case kNotEnabled :
+ mGetButton->setEnabled(FALSE);
+ mPutSetButton->setEnabled(FALSE);
+ mPutClearButton->setEnabled(FALSE);
+ mGoodPostButton->setEnabled(FALSE);
+ mBadPostButton->setEnabled(FALSE);
+ break;
+ case kReady :
+ case kRequestCompleted :
+ case kError :
+ mGetButton->setEnabled(TRUE);
+ mPutSetButton->setEnabled(isPutEnabled);
+ mPutClearButton->setEnabled(isPutEnabled);
+ mGoodPostButton->setEnabled(isGoodPostEnabled);
+ mBadPostButton->setEnabled(FALSE && TRUE);
+ break;
+ default :
+ mGetButton->setEnabled(TRUE);
+ mPutSetButton->setEnabled(isPutEnabled);
+ mPutClearButton->setEnabled(isPutEnabled);
+ mGoodPostButton->setEnabled(isGoodPostEnabled);
+ mBadPostButton->setEnabled(FALSE && TRUE);
+ llassert(0);
+ break;
+ }
+}
+
+std::string LLFloaterDebugMaterials::convertToPrintableMaterialID(const LLSD& pBinaryHash) const
+{
+ llassert(pBinaryHash.isBinary());
+ const LLSD::Binary &materialIDValue = pBinaryHash.asBinary();
+ unsigned int valueSize = materialIDValue.size();
+
+ llassert(valueSize == 16);
+ std::string materialID(reinterpret_cast<const char *>(&materialIDValue[0]), valueSize);
+ std::string materialIDString;
+ for (unsigned int i = 0U; i < (valueSize / 4); ++i)
+ {
+ if (i != 0U)
+ {
+ materialIDString += "-";
+ }
+ const U32 *value = reinterpret_cast<const U32*>(&materialID.c_str()[i * 4]);
+ materialIDString += llformat("%08x", *value);
+ }
+ return materialIDString;
+}
+
+std::string LLFloaterDebugMaterials::convertToPrintableMaterialID(const LLMaterialID& pMaterialID) const
+{
+ std::string materialID(reinterpret_cast<const char *>(pMaterialID.get()), 16);
+ std::string materialIDString;
+ for (unsigned int i = 0U; i < 4; ++i)
+ {
+ if (i != 0U)
+ {
+ materialIDString += "-";
+ }
+ const U32 *value = reinterpret_cast<const U32*>(&materialID.c_str()[i * 4]);
+ materialIDString += llformat("%08x", *value);
+ }
+ return materialIDString;
+}
+
+S32 LLFloaterDebugMaterials::getNormalMapOffsetX() const
+{
+ return getLineEditorValue(mNormalMapOffsetX);
+}
+
+S32 LLFloaterDebugMaterials::getNormalMapOffsetY() const
+{
+ return getLineEditorValue(mNormalMapOffsetY);
+}
+
+S32 LLFloaterDebugMaterials::getNormalMapRepeatX() const
+{
+ return getLineEditorValue(mNormalMapRepeatX);
+}
+
+S32 LLFloaterDebugMaterials::getNormalMapRepeatY() const
+{
+ return getLineEditorValue(mNormalMapRepeatY);
+}
+
+S32 LLFloaterDebugMaterials::getNormalMapRotation() const
+{
+ return getLineEditorValue(mNormalMapRotation);
+}
+
+S32 LLFloaterDebugMaterials::getSpecularMapOffsetX() const
+{
+ return getLineEditorValue(mSpecularMapOffsetX);
+}
+
+S32 LLFloaterDebugMaterials::getSpecularMapOffsetY() const
+{
+ return getLineEditorValue(mSpecularMapOffsetY);
+}
+
+S32 LLFloaterDebugMaterials::getSpecularMapRepeatX() const
+{
+ return getLineEditorValue(mSpecularMapRepeatX);
+}
+
+S32 LLFloaterDebugMaterials::getSpecularMapRepeatY() const
+{
+ return getLineEditorValue(mSpecularMapRepeatY);
+}
+
+S32 LLFloaterDebugMaterials::getSpecularMapRotation() const
+{
+ return getLineEditorValue(mSpecularMapRotation);
+}
+
+LLColor4U LLFloaterDebugMaterials::getSpecularColor() const
+{
+ const LLColor4& specularColor = mSpecularColor->get();
+ LLColor4U specularColor4U = specularColor;
+
+ specularColor4U.setAlpha(static_cast<U8>(llclamp(llround(mSpecularColorAlpha->get()), 0, 255)));
+
+ return specularColor4U;
+}
+
+S32 LLFloaterDebugMaterials::getSpecularExponent() const
+{
+ return getLineEditorValue(mSpecularExponent);
+}
+
+S32 LLFloaterDebugMaterials::getEnvironmentExponent() const
+{
+ return getLineEditorValue(mEnvironmentExponent);
+}
+
+S32 LLFloaterDebugMaterials::getAlphMaskCutoff() const
+{
+ return getLineEditorValue(mAlphaMaskCutoff);
+}
+
+S32 LLFloaterDebugMaterials::getDiffuseAlphaMode() const
+{
+ return getLineEditorValue(mDiffuseAlphaMode);
+}
+
+S32 LLFloaterDebugMaterials::getLineEditorValue(const LLLineEditor *pLineEditor) const
+{
+ S32 value = 0;
+
+ LLStringUtil::convertToS32(pLineEditor->getText(), value);
+
+ return value;
+}
+
+MaterialsResponder::MaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback)
+ : LLHTTPClient::Responder(),
+ mMethod(pMethod),
+ mCapabilityURL(pCapabilityURL),
+ mCallback(pCallback)
+{
+}
+
+MaterialsResponder::~MaterialsResponder()
+{
+}
+
+void MaterialsResponder::result(const LLSD& pContent)
+{
+ mCallback(true, pContent);
+}
+
+void MaterialsResponder::error(U32 pStatus, const std::string& pReason)
+{
+ LL_WARNS("debugMaterials") << "--------------------------------------------------------------------------" << LL_ENDL;
+ LL_WARNS("debugMaterials") << mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
+ << "' with url '" << mCapabilityURL << "' because " << pReason << LL_ENDL;
+ LL_WARNS("debugMaterials") << "--------------------------------------------------------------------------" << LL_ENDL;
+
+ LLSD emptyResult;
+ mCallback(false, emptyResult);
+}
diff --git a/indra/newview/llfloaterdebugmaterials.h b/indra/newview/llfloaterdebugmaterials.h
new file mode 100644
index 0000000000..b3983ecd6c
--- /dev/null
+++ b/indra/newview/llfloaterdebugmaterials.h
@@ -0,0 +1,208 @@
+/**
+* @file llfloaterdebugmaterials.h
+* @brief Header file for llfloaterdebugmaterials
+* @author Stinson@lindenlab.com
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, 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$
+*/
+#ifndef LL_LLFLOATERDEBUGMATERIALS_H
+#define LL_LLFLOATERDEBUGMATERIALS_H
+
+#include <string>
+
+#include <boost/signals2.hpp>
+
+#include "llfloater.h"
+#include "lluuid.h"
+#include "v4color.h"
+
+class LLButton;
+class LLColorSwatchCtrl;
+class LLColor4U;
+class LLLineEditor;
+class LLMaterialID;
+class LLScrollListCtrl;
+class LLSD;
+class LLSpinCtrl;
+class LLTextBase;
+class LLTextureCtrl;
+class LLUICtrl;
+
+class LLFloaterDebugMaterials : public LLFloater
+{
+public:
+ virtual BOOL postBuild();
+
+ virtual void onOpen(const LLSD& pKey);
+ virtual void onClose(bool pIsAppQuitting);
+
+ virtual void draw();
+
+protected:
+
+private:
+ friend class LLFloaterReg;
+
+ typedef enum {
+ kNoRegion,
+ kCapabilitiesLoading,
+ kReady,
+ kRequestStarted,
+ kRequestCompleted,
+ kNotEnabled,
+ kError
+ } EState;
+
+ LLFloaterDebugMaterials(const LLSD& pParams);
+ virtual ~LLFloaterDebugMaterials();
+
+ void onGetClicked();
+ void onValueEntered(LLUICtrl* pUICtrl);
+ void onPutSetClicked();
+ void onPutClearClicked();
+ void onResetPutValuesClicked();
+ void onQueryVisibleObjectsClicked();
+ void onGoodPostClicked();
+ void onBadPostClicked();
+ void onRegionCross();
+ void onInWorldSelectionChange();
+ void onGetScrollListSelectionChange(LLUICtrl* pUICtrl);
+ void onDeferredCheckRegionMaterialStatus(LLUUID regionId);
+ void onDeferredRequestGetMaterials(LLUUID regionId);
+ void onDeferredRequestPutMaterials(LLUUID regionId, bool pIsDoSet);
+ void onDeferredRequestPostMaterials(LLUUID regionId, bool pUseGoodData);
+ void onGetResponse(bool pRequestStatus, const LLSD& pContent);
+ void onPutResponse(bool pRequestStatus, const LLSD& pContent);
+ void onPostResponse(bool pRequestStatus, const LLSD& pContent);
+
+ void checkRegionMaterialStatus();
+ void checkRegionMaterialStatus(const LLUUID& regionId);
+
+ void requestGetMaterials();
+ void requestGetMaterials(const LLUUID& regionId);
+
+ void requestPutMaterials(bool pIsDoSet);
+ void requestPutMaterials(const LLUUID& regionId, bool pIsDoSet);
+
+ void requestPostMaterials(bool pUseGoodData);
+ void requestPostMaterials(const LLUUID& regionId, bool pUseGoodData);
+
+ void queryViewableObjects();
+
+ void parseGetResponse();
+ void parsePutResponse(const LLSD& pContent);
+ void parsePostResponse(const LLSD& pContent);
+
+ void setState(EState pState);
+ inline EState getState() const;
+
+ void resetObjectEditInputs();
+ void clearGetResults();
+ void clearPutResults();
+ void clearPostResults();
+ void clearViewableObjectsResults();
+
+ void setUnparsedGetData(const LLSD& pGetData);
+ void clearUnparsedGetData();
+ void updateGetParsingStatus();
+
+ void updateStatusMessage();
+ void updateControls();
+ std::string convertToPrintableMaterialID(const LLSD& pBinaryHash) const;
+ std::string convertToPrintableMaterialID(const LLMaterialID& pMaterialID) const;
+
+ S32 getNormalMapOffsetX() const;
+ S32 getNormalMapOffsetY() const;
+ S32 getNormalMapRepeatX() const;
+ S32 getNormalMapRepeatY() const;
+ S32 getNormalMapRotation() const;
+
+ S32 getSpecularMapOffsetX() const;
+ S32 getSpecularMapOffsetY() const;
+ S32 getSpecularMapRepeatX() const;
+ S32 getSpecularMapRepeatY() const;
+ S32 getSpecularMapRotation() const;
+
+ LLColor4U getSpecularColor() const;
+ S32 getSpecularExponent() const;
+ S32 getEnvironmentExponent() const;
+ S32 getAlphMaskCutoff() const;
+ S32 getDiffuseAlphaMode() const;
+ S32 getLineEditorValue(const LLLineEditor *pLineEditor) const;
+
+ LLTextBase* mStatusText;
+ LLButton* mGetButton;
+ LLTextBase* mParsingStatusText;
+ LLScrollListCtrl* mGetNormalMapScrollList;
+ LLScrollListCtrl* mGetSpecularMapScrollList;
+ LLScrollListCtrl* mGetOtherDataScrollList;
+ LLTextureCtrl* mNormalMap;
+ LLLineEditor* mNormalMapOffsetX;
+ LLLineEditor* mNormalMapOffsetY;
+ LLLineEditor* mNormalMapRepeatX;
+ LLLineEditor* mNormalMapRepeatY;
+ LLLineEditor* mNormalMapRotation;
+ LLTextureCtrl* mSpecularMap;
+ LLLineEditor* mSpecularMapOffsetX;
+ LLLineEditor* mSpecularMapOffsetY;
+ LLLineEditor* mSpecularMapRepeatX;
+ LLLineEditor* mSpecularMapRepeatY;
+ LLLineEditor* mSpecularMapRotation;
+ LLColorSwatchCtrl* mSpecularColor;
+ LLSpinCtrl* mSpecularColorAlpha;
+ LLLineEditor* mSpecularExponent;
+ LLLineEditor* mEnvironmentExponent;
+ LLLineEditor* mAlphaMaskCutoff;
+ LLLineEditor* mDiffuseAlphaMode;
+ LLButton* mPutSetButton;
+ LLButton* mPutClearButton;
+ LLScrollListCtrl* mPutScrollList;
+ LLButton* mQueryViewableObjectsButton;
+ LLScrollListCtrl* mViewableObjectsScrollList;
+ LLButton* mGoodPostButton;
+ LLButton* mBadPostButton;
+ LLScrollListCtrl* mPostNormalMapScrollList;
+ LLScrollListCtrl* mPostSpecularMapScrollList;
+ LLScrollListCtrl* mPostOtherDataScrollList;
+
+ LLColor4 mDefaultSpecularColor;
+
+ EState mState;
+ LLColor4 mWarningColor;
+ LLColor4 mErrorColor;
+
+ boost::signals2::connection mRegionCrossConnection;
+ boost::signals2::connection mTeleportFailedConnection;
+ boost::signals2::connection mSelectionUpdateConnection;
+
+ LLSD mUnparsedGetData;
+ S32 mNextUnparsedGetDataIndex;
+};
+
+
+
+LLFloaterDebugMaterials::EState LLFloaterDebugMaterials::getState() const
+{
+ return mState;
+}
+
+#endif // LL_LLFLOATERDEBUGMATERIALS_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 1f7cf0cdd4..b630b5bbe6 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -50,6 +50,7 @@
#include "llfloaterbump.h"
#include "llfloaterbvhpreview.h"
#include "llfloatercamera.h"
+#include "llfloaterdebugmaterials.h"
#include "llfloaterdeleteenvpreset.h"
#include "llfloaterdisplayname.h"
#include "llfloatereditdaycycle.h"
@@ -255,6 +256,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("pathfinding_characters", "floater_pathfinding_characters.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingCharacters>);
LLFloaterReg::add("pathfinding_linksets", "floater_pathfinding_linksets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingLinksets>);
LLFloaterReg::add("pathfinding_console", "floater_pathfinding_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingConsole>);
+ LLFloaterReg::add("floater_debug_materials", "floater_debug_materials.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDebugMaterials>);
LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f9342a9736..54fc31cf9f 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -41,6 +41,7 @@
#include "llframetimer.h"
#include "llinventory.h"
#include "llinventorydefines.h"
+#include "llmaterialid.h"
#include "llmaterialtable.h"
#include "llmutelist.h"
#include "llnamevalue.h"
@@ -4252,6 +4253,26 @@ S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow)
return retval;
}
+S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (pMaterialID != tep->getMaterialID())
+ {
+ retval = LLPrimitive::setTEMaterialID(te, pMaterialID);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+ return retval;
+}
+
S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t)
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 1fb30db8f2..255d0cd080 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -56,6 +56,7 @@ class LLDrawable;
class LLHost;
class LLHUDText;
class LLWorld;
+class LLMaterialID;
class LLNameValue;
class LLNetMap;
class LLMessageSystem;
@@ -88,18 +89,6 @@ typedef void (*inventory_callback)(LLViewerObject*,
S32 serial_num,
void*);
-// for exporting textured materials from SL
-struct LLMaterialExportInfo
-{
-public:
- LLMaterialExportInfo(S32 mat_index, S32 texture_index, LLColor4 color) :
- mMaterialIndex(mat_index), mTextureIndex(texture_index), mColor(color) {};
-
- S32 mMaterialIndex;
- S32 mTextureIndex;
- LLColor4 mColor;
-};
-
struct PotentialReturnableObject
{
LLBBox box;
@@ -320,6 +309,7 @@ public:
/*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright );
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags );
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
+ /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
/*virtual*/ BOOL setMaterial(const U8 material);
virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive
virtual void changeTEImage(S32 index, LLViewerTexture* new_image) ;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b607afbd9d..7c4cce2439 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1557,6 +1557,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ProductInfoRequest");
capabilityNames.append("ProvisionVoiceAccountRequest");
capabilityNames.append("RemoteParcelRequest");
+ capabilityNames.append("RenderMaterials");
capabilityNames.append("RequestTextureDownload");
capabilityNames.append("ResourceCostSelected");
capabilityNames.append("RetrieveNavMeshSrc");
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 4b0e0598f6..43de7450c8 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -826,12 +826,14 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) );
}
shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) );
-
+
+ boost::unordered_map<std::string, std::string> attribs;
+
// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
for (U32 i = 0; i < shaders.size(); i++)
{
// Note usage of GL_VERTEX_SHADER_ARB
- if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB) == 0)
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, attribs) == 0)
{
return FALSE;
}
@@ -879,11 +881,11 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
-
+
for (U32 i = 0; i < shaders.size(); i++)
{
// Note usage of GL_FRAGMENT_SHADER_ARB
- if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, index_channels[i]) == 0)
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, attribs, index_channels[i]) == 0)
{
return FALSE;
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 5d1c335078..50ba7e47a4 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -36,6 +36,7 @@
#include "lldir.h"
#include "llflexibleobject.h"
#include "llfloatertools.h"
+#include "llmaterialid.h"
#include "llmaterialtable.h"
#include "llprimitive.h"
#include "llvolume.h"
@@ -1976,6 +1977,17 @@ S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
return res;
}
+S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
+{
+ S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID);
+ if (res)
+ {
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
+ }
+ return res;
+}
+
S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
{
S32 res = LLViewerObject::setTEScale(te, s, t);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 5482c80f2b..ff6dca9737 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -37,6 +37,7 @@
class LLViewerTextureAnim;
class LLDrawPool;
+class LLMaterialID;
class LLSelectNode;
class LLObjectMediaDataClient;
class LLObjectMediaNavigateClient;
@@ -185,6 +186,7 @@ public:
/*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump);
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags);
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
+ /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
/*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
/*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
/*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 91dd441319..351dc1731a 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -397,7 +397,7 @@ void validate_framebuffer_object();
bool addDeferredAttachments(LLRenderTarget& target)
{
return target.addColorAttachment(GL_RGBA) && //specular
- target.addColorAttachment(GL_RGBA); //normal+z
+ target.addColorAttachment(GL_RGB10_A2); //normal+z
}
LLPipeline::LLPipeline() :
@@ -865,7 +865,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
if (!addDeferredAttachments(mDeferredScreen)) return false;
-
+
if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
if (samples > 0)
{
@@ -1208,6 +1208,11 @@ void LLPipeline::createGLBuffers()
gBumpImageList.restoreGL();
}
+F32 lerpf(F32 a, F32 b, F32 w)
+{
+ return a + w * (b - a);
+}
+
void LLPipeline::createLUTBuffers()
{
if (sRenderDeferred)
@@ -1216,45 +1221,40 @@ void LLPipeline::createLUTBuffers()
{
U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
- U8* ls = new U8[lightResX*lightResY];
- F32 specExp = gSavedSettings.getF32("RenderSpecularExponent");
- // Calculate the (normalized) Blinn-Phong specular lookup texture.
+ F32* ls = new F32[lightResX*lightResY];
+ //F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Note: only use this when creating new specular lighting functions.
+ // Calculate the (normalized) Gaussian specular lookup texture. (with a few tweaks)
for (U32 y = 0; y < lightResY; ++y)
{
for (U32 x = 0; x < lightResX; ++x)
{
ls[y*lightResX+x] = 0;
F32 sa = (F32) x/(lightResX-1);
- F32 spec = (F32) y/(lightResY-1);
- F32 n = spec * spec * specExp;
+ F32 spec = (F32) y/(lightResY);
+ F32 n = spec;
- // Nothing special here. Just your typical blinn-phong term.
- spec = powf(sa, n);
+ float angleNormalHalf = acosf(sa);
+ float exponent = angleNormalHalf / ((1 - n));
+ exponent = -(exponent * exponent);
+ spec = expf(exponent);
// Apply our normalization function.
- // Note: This is the full equation that applies the full normalization curve, not an approximation.
- // This is fine, given we only need to create our LUT once per buffer initialization.
- // The only trade off is we have a really low dynamic range.
- // This means we have to account for things not being able to exceed 0 to 1 in our shaders.
- spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n)));
+ // This is based around the phong normalization function, trading n+2 for n+1 instead.
+ // Since we're using a gaussian model here, we actually don't really need as large of an exponent as blinn-phong shading.
+ // Instead, we assume that the correct exponent is 8 here.
+ // This was achieved through much tweaking to find a decent "middleground" with our specular highlights with the gaussian term.
+ // Bigger highlights don't look too soft, smaller highlights don't look too bright, and everything in the middle seems to have a well maintained highlight curvature.
+ // There isn't really much theory behind this one. This was done purely to produce a nice and mostly customizable BRDF.
- // Always sample at a 1.0/2.2 curve.
- // This "Gamma corrects" our specular term, boosting our lower exponent reflections.
- spec = powf(spec, 1.f/2.2f);
+ spec = lerpf(spec, spec * (n * 8 + 1) / 4.5, n);
- // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders.
- // This allows for our specular term to exceed a value of 1 in our shaders.
- // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1.
- // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times.
- // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents.
- // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable.
- ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255);
+ ls[y*lightResX+x] = spec;
}
}
- LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc);
+ LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R16F, 1, &mLightFunc);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R16F, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 9bf2922033..48a9430fdc 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -645,6 +645,15 @@
name="PathfindingGoodColor"
reference="LtGreen" />
<color
+ name="MaterialErrorColor"
+ reference="LtRed" />
+ <color
+ name="MaterialWarningColor"
+ reference="DrYellow" />
+ <color
+ name="MaterialGoodColor"
+ reference="LtGreen" />
+ <color
name="PathfindingDefaultBeaconColor"
reference="Red_80" />
<color
diff --git a/indra/newview/skins/default/xui/en/floater_debug_materials.xml b/indra/newview/skins/default/xui/en/floater_debug_materials.xml
new file mode 100644
index 0000000000..cdc1e63ce1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_debug_materials.xml
@@ -0,0 +1,1075 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ positioning="cascading"
+ can_tear_off="false"
+ can_resize="true"
+ height="725"
+ width="1040"
+ min_height="750"
+ min_width="1040"
+ layout="topleft"
+ name="floater_debug_materials"
+ reuse_instance="true"
+ save_rect="false"
+ single_instance="true"
+ title="Debug materials">
+ <floater.string name="status_no_region">No current region available.</floater.string>
+ <floater.string name="status_capabilities_loading">Region capabilities are loading.</floater.string>
+ <floater.string name="status_ready">Materials are enabled for this region.</floater.string>
+ <floater.string name="status_request_started">Request sent.</floater.string>
+ <floater.string name="status_request_completed">Request received.</floater.string>
+ <floater.string name="status_not_enabled">Materials are not enabled for this region.</floater.string>
+ <floater.string name="status_error">An error occurred during the request.</floater.string>
+ <floater.string name="loading_status_in_progress">Processing [NUM_PROCESSED] out of [NUM_TOTAL]</floater.string>
+ <floater.string name="loading_status_done">Complete</floater.string>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top"
+ layout="topleft"
+ left="12"
+ top_pad="10"
+ height="61"
+ width="214">
+ <text
+ height="13"
+ word_wrap="true"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ layout="topleft"
+ left="0"
+ top_pad="0"
+ width="214">
+ Status
+ </text>
+ <text
+ height="40"
+ word_wrap="true"
+ use_ellipses="false"
+ type="string"
+ text_color="MaterialGoodColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ name="material_status"
+ top_pad="8"
+ width="214">
+ </text>
+ </panel>
+ <tab_container
+ follows="left|top|right"
+ layout="topleft"
+ tab_position="top"
+ left="10"
+ top_pad="10"
+ height="620"
+ width="1020">
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ label="Current region"
+ height="620"
+ top_pad="10"
+ width="1020">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="479"
+ top_pad="10"
+ width="1020">
+ <button
+ follows="left|top"
+ height="22"
+ label="Get"
+ layout="topleft"
+ name="get_button"
+ top_pad="0"
+ width="214"/>
+ <text
+ height="13"
+ word_wrap="true"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="2"
+ top_pad="8"
+ width="150">
+ Loading Status
+ </text>
+ <text
+ height="13"
+ word_wrap="true"
+ use_ellipses="false"
+ type="string"
+ text_color="MaterialGoodColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="loading_status"
+ top_pad="-13"
+ width="400">
+ </text>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ left="0"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="false"
+ name="get_other_data_scroll_list"
+ width="775">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Specular Color"
+ name="specular_color"
+ width="120" />
+ <scroll_list.columns
+ label="Specular Exponent"
+ name="specular_exponent"
+ width="112" />
+ <scroll_list.columns
+ label="Env Intensity"
+ name="env_intensity"
+ width="80" />
+ <scroll_list.columns
+ label="Alpha Mask Cutoff"
+ name="alpha_mask_cutoff"
+ width="110" />
+ <scroll_list.columns
+ label="Diffuse Alpha Mode"
+ name="diffuse_alpha_mode"
+ width="118" />
+ </scroll_list>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="false"
+ name="get_specular_map_scroll_list"
+ width="1020">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Specular Map"
+ name="specular_map_list_map"
+ width="225" />
+ <scroll_list.columns
+ label="Offset X"
+ name="specular_map_list_offset_x"
+ width="112" />
+ <scroll_list.columns
+ label="Offset Y"
+ name="specular_map_list_offset_y"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat X"
+ name="specular_map_list_repeat_x"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat Y"
+ name="specular_map_list_repeat_y"
+ width="112" />
+ <scroll_list.columns
+ label="Rotation"
+ name="specular_map_list_rotation"
+ width="112" />
+ </scroll_list>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="false"
+ name="get_normal_map_scroll_list"
+ width="1020">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Normal Map"
+ name="normal_map_list_map"
+ width="225" />
+ <scroll_list.columns
+ label="Offset X"
+ name="normal_map_list_offset_x"
+ width="112" />
+ <scroll_list.columns
+ label="Offset Y"
+ name="normal_map_list_offset_y"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat X"
+ name="normal_map_list_repeat_x"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat Y"
+ name="normal_map_list_repeat_y"
+ width="112" />
+ <scroll_list.columns
+ label="Rotation"
+ name="normal_map_list_rotation"
+ width="112" />
+ </scroll_list>
+ </panel>
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ label="Object editing"
+ height="620"
+ top_pad="10"
+ width="1010">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ left="2"
+ top_pad="10"
+ height="420"
+ width="810">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="265"
+ top_pad="0"
+ width="810">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="226"
+ top_pad="0"
+ width="263">
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ top_pad="38"
+ width="160">
+ Normal Map
+ </text>
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ left_pad="0"
+ top_pad="-50"
+ label_width="0"
+ height="100"
+ width="100"
+ mouse_opaque="true"
+ name="normal_map"
+ tool_tip="Click to open texture picker" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-260"
+ top_pad="10"
+ width="160">
+ Normal Map Offset X
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="normal_map_offset_x"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Normal Map Offset Y
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="normal_map_offset_y"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Normal Map Repeat X
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="normal_map_repeat_x"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Normal Map Repeat Y
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="normal_map_repeat_y"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Normal Map Rotation
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="normal_map_rotation"
+ width="80" />
+ </panel>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="226"
+ top_pad="-226"
+ left_pad="20"
+ width="263">
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ top_pad="38"
+ width="160">
+ Specular Map
+ </text>
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ left_pad="0"
+ top_pad="-50"
+ label_width="0"
+ height="100"
+ width="100"
+ mouse_opaque="true"
+ name="specular_map"
+ tool_tip="Click to open texture picker" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-260"
+ top_pad="10"
+ width="160">
+ Specular Map Offset X
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_map_offset_x"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Specular Map Offset Y
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_map_offset_y"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Specular Map Repeat X
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_map_repeat_x"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Specular Map Repeat Y
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_map_repeat_y"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Specular Map Rotation
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_map_rotation"
+ width="80" />
+ </panel>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="162"
+ top_pad="-226"
+ left_pad="20"
+ width="243">
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ top_pad="10"
+ width="160">
+ Specular Color
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="1 1 1 1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ label_height="0"
+ label_width="0"
+ left_pad="0"
+ top_pad="-22"
+ name="specular_color"
+ tool_tip="Click to open color picker"
+ width="40" />
+ <spinner
+ follows="left|top"
+ height="20"
+ initial_value="255"
+ max_val="255"
+ min_val="0"
+ increment="1"
+ decimal_digits="0"
+ allow_text_entry="true"
+ layout="topleft"
+ label_width="160"
+ left="0"
+ top_pad="10"
+ label="Specular Color Alpha"
+ name="specular_color_alpha"
+ width="240" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="13"
+ width="160">
+ Specular Exponent
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="specular_exponent"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Environment Exponent
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="environment_exponent"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Alpha Mask Cuttoff
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="alpha_mask_cutoff"
+ width="80" />
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="-240"
+ top_pad="10"
+ width="160">
+ Diffuse Alpha Mode
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ default_text="0"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ top_pad="-18"
+ max_length_chars="255"
+ name="diffuse_alpha_mode"
+ width="80" />
+ </panel>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="22"
+ left="0"
+ top_pad="80"
+ width="810">
+ <button
+ follows="left|top"
+ height="22"
+ label="Set Face Data"
+ layout="topleft"
+ name="put_set_button"
+ left="0"
+ top="0"
+ width="214"/>
+ <button
+ follows="left|top"
+ height="22"
+ label="Clear Face Data"
+ layout="topleft"
+ name="put_clear_button"
+ left_pad="20"
+ width="214"/>
+ <button
+ follows="left|top"
+ height="22"
+ label="Reset Input Values"
+ layout="topleft"
+ name="reset_put_values_button"
+ left_pad="146"
+ width="214"/>
+ </panel>
+ </panel>
+ <view_border
+ bevel_style="none"
+ follows="left|top"
+ height="0"
+ layout="topleft"
+ name="horiz_separator"
+ top_pad="10"
+ left="0"
+ width="810"/>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="125"
+ top_pad="20"
+ width="400">
+ <text
+ height="13"
+ word_wrap="false"
+ use_ellipses="false"
+ type="string"
+ text_color="LabelTextColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ top_pad="0"
+ width="160">
+ Results
+ </text>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="100"
+ layout="topleft"
+ left="0"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="true"
+ name="put_scroll_list"
+ width="400">
+ <scroll_list.columns
+ label="Object ID"
+ name="object_id"
+ width="80" />
+ <scroll_list.columns
+ label="Face Index"
+ name="face_index"
+ width="70" />
+ <scroll_list.columns
+ label="MaterialID"
+ name="material_id"
+ dynamic_width="true" />
+ </scroll_list>
+ </panel>
+ </panel>
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ label="Viewable objects"
+ height="620"
+ top_pad="10"
+ width="1020">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="620"
+ top_pad="0"
+ width="1020">
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top_pad="10"
+ height="132"
+ width="835">
+ <button
+ follows="left|top"
+ height="22"
+ label="Query Viewable Objects"
+ layout="topleft"
+ name="query_viewable_objects_button"
+ top_pad="0"
+ width="214"/>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="100"
+ layout="topleft"
+ top_pad="10"
+ left="0"
+ tab_stop="false"
+ multi_select="true"
+ name="viewable_objects_scroll_list"
+ width="835">
+ <scroll_list.columns
+ label="Object ID"
+ name="object_id"
+ width="225" />
+ <scroll_list.columns
+ label="Region"
+ name="region"
+ width="225" />
+ <scroll_list.columns
+ label="Local ID"
+ name="local_id"
+ width="70" />
+ <scroll_list.columns
+ label="Face"
+ name="face_index"
+ width="70" />
+ <scroll_list.columns
+ label="Material ID"
+ name="material_id"
+ dynamic_width="true" />
+ </scroll_list>
+ </panel>
+ <view_border
+ bevel_style="none"
+ follows="left|right|top"
+ height="0"
+ layout="topleft"
+ name="horiz_separator"
+ top_pad="10"
+ left="0"
+ width="1020"/>
+ <panel
+ border="false"
+ bevel_style="none"
+ follows="left|top|right"
+ layout="topleft"
+ height="458"
+ top_pad="10"
+ width="1020">
+ <button
+ follows="left|top"
+ height="22"
+ label="Post Good Material ID"
+ layout="topleft"
+ name="good_post_button"
+ top_pad="0"
+ width="214"/>
+ <button
+ follows="left|top"
+ height="22"
+ label="Post Bad Material ID"
+ layout="topleft"
+ name="bad_post_button"
+ left_pad="20"
+ width="214"/>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ top_pad="10"
+ left="0"
+ tab_stop="false"
+ multi_select="false"
+ name="post_other_data_scroll_list"
+ width="775">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Specular Color"
+ name="specular_color"
+ width="120" />
+ <scroll_list.columns
+ label="Specular Exponent"
+ name="specular_exponent"
+ width="112" />
+ <scroll_list.columns
+ label="Env Intensity"
+ name="env_intensity"
+ width="80" />
+ <scroll_list.columns
+ label="Alpha Mask Cutoff"
+ name="alpha_mask_cutoff"
+ width="110" />
+ <scroll_list.columns
+ label="Diffuse Alpha Mode"
+ name="diffuse_alpha_mode"
+ width="118" />
+ </scroll_list>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="false"
+ name="post_specular_map_scroll_list"
+ width="1020">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Specular Map"
+ name="specular_map_list_map"
+ width="225" />
+ <scroll_list.columns
+ label="Offset X"
+ name="specular_map_list_offset_x"
+ width="112" />
+ <scroll_list.columns
+ label="Offset Y"
+ name="specular_map_list_offset_y"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat X"
+ name="specular_map_list_repeat_x"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat Y"
+ name="specular_map_list_repeat_y"
+ width="112" />
+ <scroll_list.columns
+ label="Rotation"
+ name="specular_map_list_rotation"
+ width="112" />
+ </scroll_list>
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ height="135"
+ layout="topleft"
+ top_pad="10"
+ tab_stop="false"
+ multi_select="false"
+ name="post_normal_map_scroll_list"
+ width="1020">
+ <scroll_list.columns
+ label="Material ID"
+ name="id"
+ dynamic_width="true" />
+ <scroll_list.columns
+ label="Normal Map"
+ name="normal_map_list_map"
+ width="225" />
+ <scroll_list.columns
+ label="Offset X"
+ name="normal_map_list_offset_x"
+ width="112" />
+ <scroll_list.columns
+ label="Offset Y"
+ name="normal_map_list_offset_y"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat X"
+ name="normal_map_list_repeat_x"
+ width="112" />
+ <scroll_list.columns
+ label="Repeat Y"
+ name="normal_map_list_repeat_y"
+ width="112" />
+ <scroll_list.columns
+ label="Rotation"
+ name="normal_map_list_rotation"
+ width="112" />
+ </scroll_list>
+ </panel>
+ </panel>
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1aa55acf2d..2ac7c0dd46 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2611,6 +2611,17 @@
<menu_item_check.on_enable
function="Advanced.EnableRenderDeferredOptions" />
</menu_item_check>
+
+ <menu_item_separator/>
+
+ <menu_item_call
+ label="Debug materials ..."
+ name="DebugMaterialsMenu">
+ <menu_item_call.on_click
+ function="Floater.ToggleOrBringToFront"
+ parameter="floater_debug_materials" />
+ </menu_item_call>
+
<menu_item_separator />
<menu_item_check
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 0254c5881f..37f94b82df 100644
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -39,6 +39,7 @@
#include "../llvovolume.h"
#include "../../llprimitive/llmediaentry.cpp"
+#include "../../llprimitive/llmaterialid.cpp"
#include "../../llprimitive/lltextureentry.cpp"
#include "../../llmessage/tests/llcurl_stub.cpp"
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 8338a27140..fdf26519d6 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -196,7 +196,7 @@ class ViewerManifest(LLManifest):
grid_flags = ''
if not self.default_grid():
grid_flags = "--grid %(grid)s "\
- "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\
+ %\
{'grid':self.grid()}
# set command line flags for channel