summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sh4
-rw-r--r--doc/contributions.txt7
-rw-r--r--indra/llimage/llimagepng.cpp12
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl4
-rw-r--r--indra/newview/llassetuploadqueue.cpp4
-rw-r--r--indra/newview/llcompilequeue.cpp16
-rw-r--r--indra/newview/lllocalbitmaps.cpp942
-rw-r--r--indra/newview/lllocalbitmaps.h136
-rw-r--r--indra/newview/lltexturectrl.cpp172
-rw-r--r--indra/newview/lltexturectrl.h2
-rw-r--r--indra/newview/lltoastnotifypanel.cpp6
-rw-r--r--indra/newview/llviewercontrol.cpp16
-rw-r--r--indra/newview/llviewermenu.cpp7
-rw-r--r--indra/newview/llviewertexturelist.h1
-rw-r--r--indra/newview/llvoavatar.cpp13
-rw-r--r--indra/newview/llwearable.cpp14
-rw-r--r--indra/newview/llwearable.h1
-rw-r--r--indra/newview/pipeline.cpp82
-rw-r--r--indra/newview/pipeline.h2
-rw-r--r--indra/newview/skins/default/xui/en/floater_image_preview.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_ctrl.xml192
-rw-r--r--indra/newview/skins/default/xui/en/floater_window_size.xml60
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml27
28 files changed, 1603 insertions, 137 deletions
diff --git a/build.sh b/build.sh
index c7c89fe3c2..7c11308f0c 100755
--- a/build.sh
+++ b/build.sh
@@ -132,10 +132,6 @@ if test -f scripts/update_version_files.py ; then
end_section UpdateVer
fi
-# Now retrieve the version for use in the version manager
-# First three parts only, $revision will be appended automatically.
-build_viewer_update_version_manager_version=`python scripts/get_version.py --viewer-version | sed 's/\.[0-9]*$//'`
-
if [ -z "$AUTOBUILD" ]
then
export autobuild_dir="$here/../../../autobuild/bin/"
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 3851e62cfb..5a24c43d5a 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -396,6 +396,8 @@ Frontera Thor
Fury Rosewood
Gaberoonie Zanzibar
Ganymedes Costagravas
+Geenz Spad
+ STORM-1823
Gene Frostbite
GeneJ Composer
Geneko Nemeth
@@ -622,6 +624,8 @@ Jonathan Yap
STORM-1796
STORM-1807
STORM-1808
+ STORM-637
+ STORM-1822
STORM-1809
STORM-1793
STORM-1810
@@ -868,6 +872,7 @@ Nicky Perian
OPEN-1
STORM-1087
STORM-1090
+ STORM-1828
Nicoladie Gymnast
Nounouch Hapmouche
VWR-238
@@ -1187,6 +1192,8 @@ Unlikely Quintessa
UsikuFarasi Kanarik
Vadim Bigbear
VWR-2681
+Vaalith Jinn
+ STORM-64
Vector Hastings
VWR-8726
Veritas Raymaker
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index 8d493ecde0..294f68b122 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -60,6 +60,12 @@ BOOL LLImagePNG::updateData()
// Decode the PNG data and extract sizing information
LLPngWrapper pngWrapper;
+ if (!pngWrapper.isValidPng(getData()))
+ {
+ setLastError("LLImagePNG data does not have a valid PNG header!");
+ return FALSE;
+ }
+
LLPngWrapper::ImageInfo infop;
if (! pngWrapper.readPng(getData(), NULL, &infop))
{
@@ -90,6 +96,12 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
// Decode the PNG data into the raw image
LLPngWrapper pngWrapper;
+ if (!pngWrapper.isValidPng(getData()))
+ {
+ setLastError("LLImagePNG data does not have a valid PNG header!");
+ return FALSE;
+ }
+
if (! pngWrapper.readPng(getData(), raw_image))
{
setLastError(pngWrapper.getErrorMessage());
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 64fa35543d..7e6ffb35c3 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -303,6 +303,7 @@ set(viewer_SOURCE_FILES
lllistbrowser.cpp
lllistcontextmenu.cpp
lllistview.cpp
+ lllocalbitmaps.cpp
lllocaltextureobject.cpp
lllocationhistory.cpp
lllocationinputctrl.cpp
@@ -858,6 +859,7 @@ set(viewer_HEADER_FILES
lllistbrowser.h
lllistcontextmenu.h
lllistview.h
+ lllocalbitmaps.h
lllocaltextureobject.h
lllocationhistory.h
lllocationinputctrl.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 15da381e2f..05c05b9393 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -8239,7 +8239,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <real>128</real>
+ <real>512</real>
</map>
<key>RenderSpecularResY</key>
@@ -8263,7 +8263,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>8</real>
+ <real>384</real>
</map>
<key>RenderDeferred</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 53a2a13392..4d01eeb64e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -128,7 +128,7 @@ void main()
if (sa > 0.0)
{
- sa = texture2D(lightFunc,vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
+ sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
sa *= noise;
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 a5e04fba57..19800a8b8e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -109,7 +109,7 @@ void main()
float sa = dot(normalize(lv-normalize(pos)),norm);
if (sa > 0.0)
{
- sa = texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
+ sa = 6 * texture2D(lightFunc, vec2(sa, spec.a)).r * min(dist_atten*4.0, 1.0);
sa *= noise;
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 b5501c2820..66e3cf6d13 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -301,11 +301,11 @@ void main()
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).r;
+ vec3 dumbshiny = vary_SunlitColor*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib);
+ bloom = dot(spec_contrib, spec_contrib) / 4;
col += spec_contrib;
//add environmentmap
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 61a7f1e32f..a137bea30f 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -309,11 +309,11 @@ void main()
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).r;
+ vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib);
+ bloom = dot(spec_contrib, spec_contrib) / 4;
col += spec_contrib;
//add environmentmap
diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp
index 7e50098a17..f943759bb8 100644
--- a/indra/newview/llassetuploadqueue.cpp
+++ b/indra/newview/llassetuploadqueue.cpp
@@ -123,7 +123,9 @@ public:
for(LLSD::array_const_iterator line = compile_errors.beginArray();
line < compile_errors.endArray(); line++)
{
- mSupplier->log(line->asString());
+ std::string str = line->asString();
+ str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
+ mSupplier->log(str);
llinfos << content["errors"] << llendl;
}
}
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index a42677845e..4f5f9e22b6 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -100,6 +100,7 @@ BOOL LLFloaterScriptQueue::postBuild()
{
childSetAction("close",onCloseBtn,this);
getChildView("close")->setEnabled(FALSE);
+ setVisible(true);
return TRUE;
}
@@ -158,7 +159,6 @@ void LLFloaterScriptQueue::addObject(const LLUUID& id)
BOOL LLFloaterScriptQueue::start()
{
- //llinfos << "LLFloaterCompileQueue::start()" << llendl;
std::string buffer;
LLSelectMgr *mgr = LLSelectMgr::getInstance();
@@ -178,7 +178,7 @@ BOOL LLFloaterScriptQueue::start()
args["[COUNT]"] = llformat ("%d", mObjectIDs.count());
buffer = getString ("Starting", args);
- getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
return nextObject();
}
@@ -211,7 +211,7 @@ BOOL LLFloaterScriptQueue::nextObject()
if(isDone() && !mDone)
{
mDone = true;
- getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("Done"));
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM);
getChildView("close")->setEnabled(TRUE);
}
return successful_start;
@@ -277,7 +277,7 @@ public:
return;
}
- queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(message);
+ queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
}
private:
@@ -464,7 +464,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
}
if(queue && (buffer.size() > 0))
{
- queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
+ queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
}
delete data;
}
@@ -637,7 +637,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
std::string buffer;
buffer = getString("Resetting") + (": ") + item->getName();
- getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ScriptReset);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -690,7 +690,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
std::string buffer;
buffer = getString("Running") + (": ") + item->getName();
- list->setCommentText(buffer);
+ list->addSimpleElement(buffer, ADD_BOTTOM);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
@@ -745,7 +745,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
std::string buffer;
buffer = getString("NotRunning") + (": ") +item->getName();
- list->setCommentText(buffer);
+ list->addSimpleElement(buffer, ADD_BOTTOM);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
new file mode 100644
index 0000000000..459e52c4f4
--- /dev/null
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -0,0 +1,942 @@
+/**
+ * @file lllocalbitmaps.cpp
+ * @author Vaalith Jinn
+ * @brief Local Bitmaps source
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+/* precompiled headers */
+#include "llviewerprecompiledheaders.h"
+
+/* own header */
+#include "lllocalbitmaps.h"
+
+/* boost: will not compile unless equivalent is undef'd, beware. */
+#ifdef equivalent
+#undef equivalent
+#endif
+#include <boost/filesystem.hpp>
+
+/* image compression headers. */
+#include "llimagebmp.h"
+#include "llimagetga.h"
+#include "llimagejpeg.h"
+#include "llimagepng.h"
+
+/* time headers */
+#include <time.h>
+#include <ctime>
+
+/* misc headers */
+#include "llscrolllistctrl.h"
+#include "llfilepicker.h"
+#include "llviewertexturelist.h"
+#include "llviewerobjectlist.h"
+#include "llviewerobject.h"
+#include "llface.h"
+#include "llvoavatarself.h"
+#include "llwearable.h"
+#include "llagentwearables.h"
+#include "lltexlayerparams.h"
+#include "llvovolume.h"
+#include "llnotificationsutil.h"
+
+/*=======================================*/
+/* Formal declarations, constants, etc. */
+/*=======================================*/
+std::list<LLLocalBitmap*> LLLocalBitmapMgr::sBitmapList;
+LLLocalBitmapTimer LLLocalBitmapMgr::sTimer;
+bool LLLocalBitmapMgr::sNeedsRebake;
+
+static const F32 LL_LOCAL_TIMER_HEARTBEAT = 3.0;
+static const BOOL LL_LOCAL_USE_MIPMAPS = true;
+static const S32 LL_LOCAL_DISCARD_LEVEL = 0;
+static const U32 LL_LOCAL_TEXLAYER_FOR_IDX = 0;
+static const bool LL_LOCAL_SLAM_FOR_DEBUG = true;
+static const bool LL_LOCAL_REPLACE_ON_DEL = true;
+static const S32 LL_LOCAL_UPDATE_RETRIES = 5;
+
+/*=======================================*/
+/* LLLocalBitmap: unit class */
+/*=======================================*/
+LLLocalBitmap::LLLocalBitmap(std::string filename)
+ : mFilename(filename)
+ , mShortName(gDirUtilp->getBaseFileName(filename, true))
+ , mValid(false)
+ , mLastModified()
+ , mLinkStatus(LS_ON)
+ , mUpdateRetries(LL_LOCAL_UPDATE_RETRIES)
+{
+ mTrackingID.generate();
+
+ /* extension */
+ std::string temp_exten = gDirUtilp->getExtension(mFilename);
+
+ if (temp_exten == "bmp")
+ {
+ mExtension = ET_IMG_BMP;
+ }
+ else if (temp_exten == "tga")
+ {
+ mExtension = ET_IMG_TGA;
+ }
+ else if (temp_exten == "jpg" || temp_exten == "jpeg")
+ {
+ mExtension = ET_IMG_JPG;
+ }
+ else if (temp_exten == "png")
+ {
+ mExtension = ET_IMG_PNG;
+ }
+ else
+ {
+ llwarns << "File of no valid extension given, local bitmap creation aborted." << "\n"
+ << "Filename: " << mFilename << llendl;
+ return; // no valid extension.
+ }
+
+ /* next phase of unit creation is nearly the same as an update cycle.
+ we're running updateSelf as a special case with the optional UT_FIRSTUSE
+ which omits the parts associated with removing the outdated texture */
+ mValid = updateSelf(UT_FIRSTUSE);
+}
+
+LLLocalBitmap::~LLLocalBitmap()
+{
+ // replace IDs with defaults, if set to do so.
+ if(LL_LOCAL_REPLACE_ON_DEL && mValid) // fix for STORM-1837
+ {
+ replaceIDs(mWorldID, IMG_DEFAULT);
+ LLLocalBitmapMgr::doRebake();
+ }
+
+ // delete self from gimagelist
+ LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID);
+ gTextureList.deleteImage(image);
+
+ if (image)
+ {
+ image->unref();
+ }
+}
+
+/* accessors */
+std::string LLLocalBitmap::getFilename()
+{
+ return mFilename;
+}
+
+std::string LLLocalBitmap::getShortName()
+{
+ return mShortName;
+}
+
+LLUUID LLLocalBitmap::getTrackingID()
+{
+ return mTrackingID;
+}
+
+LLUUID LLLocalBitmap::getWorldID()
+{
+ return mWorldID;
+}
+
+bool LLLocalBitmap::getValid()
+{
+ return mValid;
+}
+
+/* update functions */
+bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
+{
+ bool updated = false;
+
+ if (mLinkStatus == LS_ON)
+ {
+ // verifying that the file exists
+ if (gDirUtilp->fileExists(mFilename))
+ {
+ // verifying that the file has indeed been modified
+ const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
+ LLSD new_last_modified = asctime(localtime(&temp_time));
+
+ if (mLastModified.asString() != new_last_modified.asString())
+ {
+ /* loading the image file and decoding it, here is a critical point which,
+ if fails, invalidates the whole update (or unit creation) process. */
+ LLPointer<LLImageRaw> raw_image = new LLImageRaw();
+ if (decodeBitmap(raw_image))
+ {
+ // decode is successful, we can safely proceed.
+ LLUUID old_id = LLUUID::null;
+ if (!(optional_firstupdate == UT_FIRSTUSE) && !mWorldID.isNull())
+ {
+ old_id = mWorldID;
+ }
+ mWorldID.generate();
+ mLastModified = new_last_modified;
+
+ LLPointer<LLViewerFetchedTexture> texture = new LLViewerFetchedTexture
+ ("file://"+mFilename, mWorldID, LL_LOCAL_USE_MIPMAPS);
+
+ texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image);
+ texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image);
+ texture->ref();
+
+ gTextureList.addImage(texture);
+
+ if (!optional_firstupdate == UT_FIRSTUSE)
+ {
+ // seek out everything old_id uses and replace it with mWorldID
+ replaceIDs(old_id, mWorldID);
+
+ // remove old_id from gimagelist
+ LLViewerFetchedTexture* image = gTextureList.findImage(old_id);
+ gTextureList.deleteImage(image);
+ image->unref();
+ }
+
+ mUpdateRetries = LL_LOCAL_UPDATE_RETRIES;
+ updated = true;
+ }
+
+ // if decoding failed, we get here and it will attempt to decode it in the next cycles
+ // until mUpdateRetries runs out. this is done because some software lock the bitmap while writing to it
+ else
+ {
+ if (mUpdateRetries)
+ {
+ mUpdateRetries--;
+ }
+ else
+ {
+ llwarns << "During the update process the following file was found" << "\n"
+ << "but could not be opened or decoded for " << LL_LOCAL_UPDATE_RETRIES << " attempts." << "\n"
+ << "Filename: " << mFilename << "\n"
+ << "Disabling further update attempts for this file." << llendl;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = mFilename;
+ notif_args["NRETRIES"] = LL_LOCAL_UPDATE_RETRIES;
+ LLNotificationsUtil::add("LocalBitmapsUpdateFailedFinal", notif_args);
+
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+ }
+
+ } // end if file exists
+
+ else
+ {
+ llwarns << "During the update process, the following file was not found." << "\n"
+ << "Filename: " << mFilename << "\n"
+ << "Disabling further update attempts for this file." << llendl;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = mFilename;
+ LLNotificationsUtil::add("LocalBitmapsUpdateFileNotFound", notif_args);
+
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+
+ return updated;
+}
+
+bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg)
+{
+ bool decode_successful = false;
+
+ switch (mExtension)
+ {
+ case ET_IMG_BMP:
+ {
+ LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+ if (bmp_image->load(mFilename) && bmp_image->decode(rawimg, 0.0f))
+ {
+ rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ decode_successful = true;
+ }
+ break;
+ }
+
+ case ET_IMG_TGA:
+ {
+ LLPointer<LLImageTGA> tga_image = new LLImageTGA;
+ if ((tga_image->load(mFilename) && tga_image->decode(rawimg))
+ && ((tga_image->getComponents() == 3) || (tga_image->getComponents() == 4)))
+ {
+ rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ decode_successful = true;
+ }
+ break;
+ }
+
+ case ET_IMG_JPG:
+ {
+ LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
+ if (jpeg_image->load(mFilename) && jpeg_image->decode(rawimg, 0.0f))
+ {
+ rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ decode_successful = true;
+ }
+ break;
+ }
+
+ case ET_IMG_PNG:
+ {
+ LLPointer<LLImagePNG> png_image = new LLImagePNG;
+ if (png_image->load(mFilename) && png_image->decode(rawimg, 0.0f))
+ {
+ rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ decode_successful = true;
+ }
+ break;
+ }
+
+ default:
+ {
+ // separating this into -several- llwarns calls because in the extremely unlikely case that this happens
+ // accessing mFilename and any other object properties might very well crash the viewer.
+ // getting here should be impossible, or there's been a pretty serious bug.
+
+ llwarns << "During a decode attempt, the following local bitmap had no properly assigned extension." << llendl;
+ llwarns << "Filename: " << mFilename << llendl;
+ llwarns << "Disabling further update attempts for this file." << llendl;
+ mLinkStatus = LS_BROKEN;
+ }
+ }
+
+ return decode_successful;
+}
+
+void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id)
+{
+ // checking for misuse.
+ if (old_id == new_id)
+ {
+ llinfos << "An attempt was made to replace a texture with itself. (matching UUIDs)" << "\n"
+ << "Texture UUID: " << old_id.asString() << llendl;
+ return;
+ }
+
+ updateUserPrims(old_id, new_id);
+ updateUserSculpts(old_id, new_id); // isn't there supposed to be an IMG_DEFAULT_SCULPT or something?
+
+ // default safeguard image for layers
+ if( new_id == IMG_DEFAULT )
+ {
+ new_id = IMG_DEFAULT_AVATAR;
+ }
+
+ /* It doesn't actually update all of those, it merely checks if any of them
+ contain the referenced ID and if so, updates. */
+ updateUserLayers(old_id, new_id, LLWearableType::WT_ALPHA);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_EYES);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_GLOVES);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_JACKET);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_PANTS);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_SHIRT);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_SHOES);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_SKIN);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_SKIRT);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_SOCKS);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_TATTOO);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERPANTS);
+ updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERSHIRT);
+}
+
+// this function sorts the faces from a getFaceList[getNumFaces] into a list of objects
+// in order to prevent multiple sendTEUpdate calls per object during updateUserPrims
+std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id)
+{
+ std::vector<LLViewerObject*> obj_list;
+ LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id);
+
+ for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(); face_iterator++)
+ {
+ // getting an object from a face
+ LLFace* face_to_object = (*old_texture->getFaceList())[face_iterator];
+
+ if(face_to_object)
+ {
+ LLViewerObject* affected_object = face_to_object->getViewerObject();
+
+ if(affected_object)
+ {
+
+ // we have an object, we'll take it's UUID and compare it to
+ // whatever we already have in the returnable object list.
+ // if there is a match - we do not add (to prevent duplicates)
+ LLUUID mainlist_obj_id = affected_object->getID();
+ bool add_object = true;
+
+ // begin looking for duplicates
+ std::vector<LLViewerObject*>::iterator objlist_iter = obj_list.begin();
+ for(; (objlist_iter != obj_list.end()) && add_object; objlist_iter++)
+ {
+ LLViewerObject* obj = *objlist_iter;
+ if (obj->getID() == mainlist_obj_id)
+ {
+ add_object = false; // duplicate found.
+ }
+ }
+ // end looking for duplicates
+
+ if(add_object)
+ {
+ obj_list.push_back(affected_object);
+ }
+
+ }
+
+ }
+
+ } // end of face-iterating for()
+
+ return obj_list;
+}
+
+void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id)
+{
+ std::vector<LLViewerObject*> objectlist = prepUpdateObjects(old_id);
+
+ for(std::vector<LLViewerObject*>::iterator object_iterator = objectlist.begin();
+ object_iterator != objectlist.end(); object_iterator++)
+ {
+ LLViewerObject* object = *object_iterator;
+
+ if(object)
+ {
+ bool update_obj = false;
+ S32 num_faces = object->getNumFaces();
+
+ for (U8 face_iter = 0; face_iter < num_faces; face_iter++)
+ {
+ if (object->mDrawable)
+ {
+ LLFace* face = object->mDrawable->getFace(face_iter);
+ if (face && face->getTexture() && face->getTexture()->getID() == old_id)
+ {
+ object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture
+ (new_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
+
+ update_obj = true;
+ }
+ }
+ }
+
+ if (update_obj)
+ {
+ object->sendTEUpdate();
+ }
+ }
+ }
+
+}
+
+void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)
+{
+ LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id);
+ for(U32 volume_iter = 0; volume_iter < old_texture->getNumVolumes(); volume_iter++)
+ {
+ LLVOVolume* volume_to_object = (*old_texture->getVolumeList())[volume_iter];
+ LLViewerObject* object = (LLViewerObject*)volume_to_object;
+
+ if(object)
+ {
+ if (object->isSculpted() && object->getVolume() &&
+ object->getVolume()->getParams().getSculptID() == old_id)
+ {
+ LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLSculptParams new_params(*old_params);
+ new_params.setSculptTexture(new_id);
+ object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE);
+ }
+ }
+ }
+}
+
+void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type)
+{
+ U32 count = gAgentWearables.getWearableCount(type);
+ for(U32 wearable_iter = 0; wearable_iter < count; wearable_iter++)
+ {
+ LLWearable* wearable = gAgentWearables.getWearable(type, wearable_iter);
+ if (wearable)
+ {
+ std::vector<LLLocalTextureObject*> texture_list = wearable->getLocalTextureListSeq();
+ for(std::vector<LLLocalTextureObject*>::iterator texture_iter = texture_list.begin();
+ texture_iter != texture_list.end(); texture_iter++)
+ {
+ LLLocalTextureObject* lto = *texture_iter;
+
+ if (lto && lto->getID() == old_id)
+ {
+ U32 local_texlayer_index = 0; /* can't keep that as static const, gives errors, so i'm leaving this var here */
+ LLVOAvatarDefines::EBakedTextureIndex baked_texind =
+ lto->getTexLayer(local_texlayer_index)->getTexLayerSet()->getBakedTexIndex();
+
+ LLVOAvatarDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind);
+ if (reg_texind != LLVOAvatarDefines::TEX_NUM_INDICES)
+ {
+ U32 index = gAgentWearables.getWearableIndex(wearable);
+ gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
+ gAgentAvatarp->wearableUpdated(type, FALSE);
+
+ /* telling the manager to rebake once update cycle is fully done */
+ LLLocalBitmapMgr::setNeedsRebake();
+ }
+
+ }
+ }
+ }
+ }
+}
+
+LLVOAvatarDefines::ETextureIndex LLLocalBitmap::getTexIndex(
+ LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind)
+{
+ LLVOAvatarDefines::ETextureIndex result = LLVOAvatarDefines::TEX_NUM_INDICES; // using as a default/fail return.
+
+ switch(type)
+ {
+ case LLWearableType::WT_ALPHA:
+ {
+ switch(baked_texind)
+ {
+ case LLVOAvatarDefines::BAKED_EYES:
+ {
+ result = LLVOAvatarDefines::TEX_EYES_ALPHA;
+ break;
+ }
+
+ case LLVOAvatarDefines::BAKED_HAIR:
+ {
+ result = LLVOAvatarDefines::TEX_HAIR_ALPHA;
+ break;
+ }
+
+ case LLVOAvatarDefines::BAKED_HEAD:
+ {
+ result = LLVOAvatarDefines::TEX_HEAD_ALPHA;
+ break;
+ }
+
+ case LLVOAvatarDefines::BAKED_LOWER:
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_ALPHA;
+ break;
+ }
+ case LLVOAvatarDefines::BAKED_UPPER:
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_ALPHA;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ }
+ break;
+
+ }
+
+ case LLWearableType::WT_EYES:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_EYES)
+ {
+ result = LLVOAvatarDefines::TEX_EYES_IRIS;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_GLOVES:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_UPPER)
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_GLOVES;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_JACKET:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_LOWER)
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_JACKET;
+ }
+ else if (baked_texind == LLVOAvatarDefines::BAKED_UPPER)
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_JACKET;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_PANTS:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_LOWER)
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_PANTS;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_SHIRT:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_UPPER)
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_SHIRT;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_SHOES:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_LOWER)
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_SHOES;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_SKIN:
+ {
+ switch(baked_texind)
+ {
+ case LLVOAvatarDefines::BAKED_HEAD:
+ {
+ result = LLVOAvatarDefines::TEX_HEAD_BODYPAINT;
+ break;
+ }
+
+ case LLVOAvatarDefines::BAKED_LOWER:
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_BODYPAINT;
+ break;
+ }
+ case LLVOAvatarDefines::BAKED_UPPER:
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_BODYPAINT;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ }
+ break;
+ }
+
+ case LLWearableType::WT_SKIRT:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_SKIRT)
+ {
+ result = LLVOAvatarDefines::TEX_SKIRT;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_SOCKS:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_LOWER)
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_SOCKS;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_TATTOO:
+ {
+ switch(baked_texind)
+ {
+ case LLVOAvatarDefines::BAKED_HEAD:
+ {
+ result = LLVOAvatarDefines::TEX_HEAD_TATTOO;
+ break;
+ }
+
+ case LLVOAvatarDefines::BAKED_LOWER:
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_TATTOO;
+ break;
+ }
+ case LLVOAvatarDefines::BAKED_UPPER:
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_TATTOO;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ }
+ break;
+ }
+
+ case LLWearableType::WT_UNDERPANTS:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_LOWER)
+ {
+ result = LLVOAvatarDefines::TEX_LOWER_UNDERPANTS;
+ }
+
+ break;
+ }
+
+ case LLWearableType::WT_UNDERSHIRT:
+ {
+ if (baked_texind == LLVOAvatarDefines::BAKED_UPPER)
+ {
+ result = LLVOAvatarDefines::TEX_UPPER_UNDERSHIRT;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ llwarns << "Unknown wearable type: " << (int)type << "\n"
+ << "Baked Texture Index: " << (int)baked_texind << "\n"
+ << "Filename: " << mFilename << "\n"
+ << "TrackingID: " << mTrackingID << "\n"
+ << "InworldID: " << mWorldID << llendl;
+ }
+
+ }
+ return result;
+}
+
+/*=======================================*/
+/* LLLocalBitmapTimer: timer class */
+/*=======================================*/
+LLLocalBitmapTimer::LLLocalBitmapTimer() : LLEventTimer(LL_LOCAL_TIMER_HEARTBEAT)
+{
+}
+
+LLLocalBitmapTimer::~LLLocalBitmapTimer()
+{
+}
+
+void LLLocalBitmapTimer::startTimer()
+{
+ mEventTimer.start();
+}
+
+void LLLocalBitmapTimer::stopTimer()
+{
+ mEventTimer.stop();
+}
+
+bool LLLocalBitmapTimer::isRunning()
+{
+ return mEventTimer.getStarted();
+}
+
+BOOL LLLocalBitmapTimer::tick()
+{
+ LLLocalBitmapMgr::doUpdates();
+ return FALSE;
+}
+
+/*=======================================*/
+/* LLLocalBitmapMgr: manager class */
+/*=======================================*/
+LLLocalBitmapMgr::LLLocalBitmapMgr()
+{
+ // The class is all made of static members, should i even bother instantiating?
+}
+
+LLLocalBitmapMgr::~LLLocalBitmapMgr()
+{
+}
+
+bool LLLocalBitmapMgr::addUnit()
+{
+ bool add_successful = false;
+
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
+ {
+ sTimer.stopTimer();
+
+ std::string filename = picker.getFirstFile();
+ while(!filename.empty())
+ {
+ LLLocalBitmap* unit = new LLLocalBitmap(filename);
+
+ if (unit->getValid())
+ {
+ sBitmapList.push_back(unit);
+ add_successful = true;
+ }
+ else
+ {
+ llwarns << "Attempted to add invalid or unreadable image file, attempt cancelled.\n"
+ << "Filename: " << filename << llendl;
+
+ LLSD notif_args;
+ notif_args["FNAME"] = filename;
+ LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args);
+
+ delete unit;
+ unit = NULL;
+ }
+
+ filename = picker.getNextFile();
+ }
+
+ sTimer.startTimer();
+ }
+
+ return add_successful;
+}
+
+void LLLocalBitmapMgr::delUnit(LLUUID tracking_id)
+{
+ if (!sBitmapList.empty())
+ {
+ std::vector<LLLocalBitmap*> to_delete;
+ for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++)
+ { /* finding which ones we want deleted and making a separate list */
+ LLLocalBitmap* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ to_delete.push_back(unit);
+ }
+ }
+
+ for(std::vector<LLLocalBitmap*>::iterator del_iter = to_delete.begin();
+ del_iter != to_delete.end(); del_iter++)
+ { /* iterating over a temporary list, hence preserving the iterator validity while deleting. */
+ LLLocalBitmap* unit = *del_iter;
+ sBitmapList.remove(unit);
+ delete unit;
+ unit = NULL;
+ }
+ }
+}
+
+LLUUID LLLocalBitmapMgr::getWorldID(LLUUID tracking_id)
+{
+ LLUUID world_id = LLUUID::null;
+
+ for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++)
+ {
+ LLLocalBitmap* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ world_id = unit->getWorldID();
+ }
+ }
+
+ return world_id;
+}
+
+std::string LLLocalBitmapMgr::getFilename(LLUUID tracking_id)
+{
+ std::string filename = "";
+
+ for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++)
+ {
+ LLLocalBitmap* unit = *iter;
+ if (unit->getTrackingID() == tracking_id)
+ {
+ filename = unit->getFilename();
+ }
+ }
+
+ return filename;
+}
+
+void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)
+{
+ if (ctrl)
+ {
+ ctrl->clearRows();
+
+ if (!sBitmapList.empty())
+ {
+ for (local_list_iter iter = sBitmapList.begin();
+ iter != sBitmapList.end(); iter++)
+ {
+ LLSD element;
+ element["columns"][0]["column"] = "unit_name";
+ element["columns"][0]["type"] = "text";
+ element["columns"][0]["value"] = (*iter)->getShortName();
+
+ element["columns"][1]["column"] = "unit_id_HIDDEN";
+ element["columns"][1]["type"] = "text";
+ element["columns"][1]["value"] = (*iter)->getTrackingID();
+
+ ctrl->addElement(element);
+ }
+ }
+ }
+
+}
+
+void LLLocalBitmapMgr::doUpdates()
+{
+ // preventing theoretical overlap in cases with huge number of loaded images.
+ sTimer.stopTimer();
+ sNeedsRebake = false;
+
+ for (local_list_iter iter = sBitmapList.begin(); iter != sBitmapList.end(); iter++)
+ {
+ (*iter)->updateSelf();
+ }
+
+ doRebake();
+ sTimer.startTimer();
+}
+
+void LLLocalBitmapMgr::setNeedsRebake()
+{
+ sNeedsRebake = true;
+}
+
+void LLLocalBitmapMgr::doRebake()
+{ /* separated that from doUpdates to insure a rebake can be called separately during deletion */
+ if (sNeedsRebake)
+ {
+ gAgentAvatarp->forceBakeAllTextures(LL_LOCAL_SLAM_FOR_DEBUG);
+ sNeedsRebake = false;
+ }
+}
+
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
new file mode 100644
index 0000000000..7a23c7ef6e
--- /dev/null
+++ b/indra/newview/lllocalbitmaps.h
@@ -0,0 +1,136 @@
+/**
+ * @file lllocalbitmaps.h
+ * @author Vaalith Jinn
+ * @brief Local Bitmaps header
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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_LOCALBITMAPS_H
+#define LL_LOCALBITMAPS_H
+
+#include "lleventtimer.h"
+#include "llwearabletype.h"
+#include "llvoavatardefines.h"
+
+class LLScrollListCtrl;
+
+class LLLocalBitmap
+{
+ public: /* main */
+ LLLocalBitmap(std::string filename);
+ ~LLLocalBitmap();
+
+ public: /* accessors */
+ std::string getFilename();
+ std::string getShortName();
+ LLUUID getTrackingID();
+ LLUUID getWorldID();
+ bool getValid();
+
+ public: /* self update public section */
+ enum EUpdateType
+ {
+ UT_FIRSTUSE,
+ UT_REGUPDATE
+ };
+
+ bool updateSelf(EUpdateType = UT_REGUPDATE);
+
+ private: /* self update private section */
+ bool decodeBitmap(LLPointer<LLImageRaw> raw);
+ void replaceIDs(LLUUID old_id, LLUUID new_id);
+ std::vector<LLViewerObject*> prepUpdateObjects(LLUUID old_id);
+ void updateUserPrims(LLUUID old_id, LLUUID new_id);
+ void updateUserSculpts(LLUUID old_id, LLUUID new_id);
+ void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type);
+ LLVOAvatarDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLVOAvatarDefines::EBakedTextureIndex baked_texind);
+
+ private: /* private enums */
+ enum ELinkStatus
+ {
+ LS_ON,
+ LS_BROKEN,
+ };
+
+ enum EExtension
+ {
+ ET_IMG_BMP,
+ ET_IMG_TGA,
+ ET_IMG_JPG,
+ ET_IMG_PNG
+ };
+
+ private: /* members */
+ std::string mFilename;
+ std::string mShortName;
+ LLUUID mTrackingID;
+ LLUUID mWorldID;
+ bool mValid;
+ LLSD mLastModified;
+ EExtension mExtension;
+ ELinkStatus mLinkStatus;
+ S32 mUpdateRetries;
+
+};
+
+class LLLocalBitmapTimer : public LLEventTimer
+{
+ public:
+ LLLocalBitmapTimer();
+ ~LLLocalBitmapTimer();
+
+ public:
+ void startTimer();
+ void stopTimer();
+ bool isRunning();
+ BOOL tick();
+
+};
+
+class LLLocalBitmapMgr
+{
+ public:
+ LLLocalBitmapMgr();
+ ~LLLocalBitmapMgr();
+
+ public:
+ static bool addUnit();
+ static void delUnit(LLUUID tracking_id);
+
+ static LLUUID getWorldID(LLUUID tracking_id);
+ static std::string getFilename(LLUUID tracking_id);
+
+ static void feedScrollList(LLScrollListCtrl* ctrl);
+ static void doUpdates();
+ static void setNeedsRebake();
+ static void doRebake();
+
+ private:
+ static std::list<LLLocalBitmap*> sBitmapList;
+ static LLLocalBitmapTimer sTimer;
+ static bool sNeedsRebake;
+ typedef std::list<LLLocalBitmap*>::iterator local_list_iter;
+};
+
+#endif
+
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 19a944e88e..ed9faa0706 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -67,6 +67,9 @@
#include "lluictrlfactory.h"
#include "lltrans.h"
+#include "llradiogroup.h"
+#include "llfloaterreg.h"
+#include "lllocalbitmaps.h"
static const S32 HPAD = 4;
static const S32 VPAD = 4;
@@ -78,6 +81,8 @@ static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
static const F32 CONTEXT_FADE_TIME = 0.08f;
+static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
+
//static const char CURRENT_IMAGE_NAME[] = "Current Texture";
//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
//static const char NO_IMAGE_NAME[] = "None";
@@ -142,6 +147,12 @@ public:
static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
void onTextureSelect( const LLTextureEntry& te );
+ static void onModeSelect(LLUICtrl* ctrl, void *userdata);
+ static void onBtnAdd(void* userdata);
+ static void onBtnRemove(void* userdata);
+ static void onBtnUpload(void* userdata);
+ static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata);
+
protected:
LLPointer<LLViewerTexture> mTexturep;
LLTextureCtrl* mOwner;
@@ -169,8 +180,10 @@ protected:
BOOL mNoCopyTextureSelected;
F32 mContextConeOpacity;
LLSaveFolderState mSavedFolderState;
-
BOOL mSelectedItemPinned;
+
+ LLRadioGroup* mModeSelector;
+ LLScrollListCtrl* mLocalScrollCtrl;
};
LLFloaterTexturePicker::LLFloaterTexturePicker(
@@ -437,6 +450,17 @@ BOOL LLFloaterTexturePicker::postBuild()
mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
}
+ mModeSelector = getChild<LLRadioGroup>("mode_selection");
+ mModeSelector->setCommitCallback(onModeSelect, this);
+ mModeSelector->setSelectedIndex(0, 0);
+
+ childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this);
+ childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this);
+ childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this);
+
+ mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list");
+ mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this);
+ LLLocalBitmapMgr::feedScrollList(mLocalScrollCtrl);
mNoCopyTextureSelected = FALSE;
@@ -464,7 +488,6 @@ BOOL LLFloaterTexturePicker::postBuild()
// virtual
void LLFloaterTexturePicker::draw()
{
- S32 floater_header_size = getHeaderHeight();
if (mOwner)
{
// draw cone of context pointing back to texture swatch
@@ -554,10 +577,7 @@ void LLFloaterTexturePicker::draw()
}
// Border
- LLRect border( BORDER_PAD,
- getRect().getHeight() - floater_header_size - BORDER_PAD,
- ((getMinWidth() / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD,
- BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - getMinHeight()));
+ LLRect border = getChildView("preview_widget")->getRect();
gl_rect_2d( border, LLColor4::black, FALSE );
@@ -748,7 +768,15 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
if (self->mOwner)
{
- self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT);
+ LLUUID local_id = LLUUID::null;
+
+ if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())
+ {
+ LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
+ local_id = LLLocalBitmapMgr::getWorldID(temp_id);
+ }
+
+ self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT, local_id);
}
self->closeFloater();
}
@@ -792,6 +820,112 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem
}
// static
+void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ bool mode = (self->mModeSelector->getSelectedIndex() == 0);
+
+ self->getChild<LLButton>("Default")->setVisible(mode);
+ self->getChild<LLButton>("Blank")->setVisible(mode);
+ self->getChild<LLButton>("None")->setVisible(mode);
+ self->getChild<LLButton>("Pipette")->setVisible(mode);
+ self->getChild<LLFilterEditor>("inventory search editor")->setVisible(mode);
+ self->getChild<LLInventoryPanel>("inventory panel")->setVisible(mode);
+
+ /*self->getChild<LLCheckBox>("show_folders_check")->setVisible(mode);
+ no idea under which conditions the above is even shown, needs testing. */
+
+ self->getChild<LLButton>("l_add_btn")->setVisible(!mode);
+ self->getChild<LLButton>("l_rem_btn")->setVisible(!mode);
+ self->getChild<LLButton>("l_upl_btn")->setVisible(!mode);
+ self->getChild<LLScrollListCtrl>("l_name_list")->setVisible(!mode);
+}
+
+// static
+void LLFloaterTexturePicker::onBtnAdd(void* userdata)
+{
+ if (LLLocalBitmapMgr::addUnit() == true)
+ {
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl);
+ }
+}
+
+// static
+void LLFloaterTexturePicker::onBtnRemove(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+
+ if (!selected_items.empty())
+ {
+ for(std::vector<LLScrollListItem*>::iterator iter = selected_items.begin();
+ iter != selected_items.end(); iter++)
+ {
+ LLScrollListItem* list_item = *iter;
+ if (list_item)
+ {
+ LLUUID tracking_id = list_item->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID();
+ LLLocalBitmapMgr::delUnit(tracking_id);
+ }
+ }
+
+ self->getChild<LLButton>("l_rem_btn")->setEnabled(false);
+ self->getChild<LLButton>("l_upl_btn")->setEnabled(false);
+ LLLocalBitmapMgr::feedScrollList(self->mLocalScrollCtrl);
+ }
+
+}
+
+// static
+void LLFloaterTexturePicker::onBtnUpload(void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+
+ if (selected_items.empty())
+ {
+ return;
+ }
+
+ /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!)
+ in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */
+
+ LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
+ std::string filename = LLLocalBitmapMgr::getFilename(tracking_id);
+
+ if (!filename.empty())
+ {
+ LLFloaterReg::showInstance("upload_image", LLSD(filename));
+ }
+
+}
+
+//static
+void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)
+{
+ LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
+ std::vector<LLScrollListItem*> selected_items = self->mLocalScrollCtrl->getAllSelected();
+ bool has_selection = !selected_items.empty();
+
+ self->getChild<LLButton>("l_rem_btn")->setEnabled(has_selection);
+ self->getChild<LLButton>("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2));
+ /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */
+
+ if (has_selection)
+ {
+ LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);
+ LLUUID inworld_id = LLLocalBitmapMgr::getWorldID(tracking_id);
+ self->mOwner->setImageAssetID(inworld_id);
+
+ if (self->childGetValue("apply_immediate_check").asBoolean())
+ {
+ self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, inworld_id);
+ }
+ }
+}
+
+// static
void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data)
{
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
@@ -1133,7 +1267,7 @@ void LLTextureCtrl::onFloaterClose()
mFloaterHandle.markDead();
}
-void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
+void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)
{
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
@@ -1146,14 +1280,24 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
else if (mCommitOnSelection || op == TEXTURE_SELECT)
mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
-
- if( floaterp->isDirty() )
+
+ if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work.
{
setTentative( FALSE );
- mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
- lldebugs << "mImageItemID: " << mImageItemID << llendl;
- mImageAssetID = floaterp->getAssetID();
- lldebugs << "mImageAssetID: " << mImageAssetID << llendl;
+
+ if (id.notNull())
+ {
+ mImageItemID = id;
+ mImageAssetID = id;
+ }
+ else
+ {
+ mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
+ lldebugs << "mImageItemID: " << mImageItemID << llendl;
+ mImageAssetID = floaterp->getAssetID();
+ lldebugs << "mImageAssetID: " << mImageAssetID << llendl;
+ }
+
if (op == TEXTURE_SELECT && mOnSelectCallback)
{
mOnSelectCallback( this, LLSD() );
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index b1312d641f..3abe84dcc3 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -157,7 +157,7 @@ public:
void closeDependentFloater();
void onFloaterClose();
- void onFloaterCommit(ETexturePickOp op);
+ void onFloaterCommit(ETexturePickOp op, LLUUID id = LLUUID::null);
// This call is returned when a drag is detected. Your callback
// should return TRUE if the drag is acceptable.
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index de305bf3d9..a8060649ba 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -243,8 +243,8 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
mBtnCallbackData.push_back(userdata);
LLButton::Params p;
- bool is_ignore_btn = form_element["index"].asInteger() == -1;
- const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog
+ bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2;
+ const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog
p.name(form_element["name"].asString());
p.label(form_element["text"].asString());
p.font(font);
@@ -264,7 +264,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
p.rect.width = 1;
p.auto_resize = true;
}
- else if (mIsScriptDialog && is_ignore_btn)
+ else if (mIsScriptDialog && make_small_btn)
{
// this is ignore button, make it smaller
p.rect.height = BTN_HEIGHT_SMALL;
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 093b84413a..ab45aae5cc 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -181,6 +181,16 @@ static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
return true;
}
+static bool handleLUTBufferChanged(const LLSD& newvalue)
+{
+ if (gPipeline.isInit())
+ {
+ gPipeline.releaseLUTBuffers();
+ gPipeline.createLUTBuffers();
+ }
+ return true;
+}
+
static bool handleAnisotropicChanged(const LLSD& newvalue)
{
LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean();
@@ -569,9 +579,9 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
- gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
- gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
- gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
+ gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
+ gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2));
gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 37cf916423..7481414b5c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6556,31 +6556,37 @@ class LLToolsSelectedScriptAction : public view_listener_t
std::string action = userdata.asString();
bool mono = false;
std::string msg, name;
+ std::string title;
if (action == "compile mono")
{
name = "compile_queue";
mono = true;
msg = "Recompile";
+ title = LLTrans::getString("CompileQueueTitle");
}
if (action == "compile lsl")
{
name = "compile_queue";
msg = "Recompile";
+ title = LLTrans::getString("CompileQueueTitle");
}
else if (action == "reset")
{
name = "reset_queue";
msg = "Reset";
+ title = LLTrans::getString("ResetQueueTitle");
}
else if (action == "start")
{
name = "start_queue";
msg = "SetRunning";
+ title = LLTrans::getString("RunQueueTitle");
}
else if (action == "stop")
{
name = "stop_queue";
msg = "SetRunningNot";
+ title = LLTrans::getString("NotRunQueueTitle");
}
LLUUID id; id.generate();
@@ -6589,6 +6595,7 @@ class LLToolsSelectedScriptAction : public view_listener_t
{
queue->setMono(mono);
queue_actions(queue, msg);
+ queue->setTitle(title);
}
else
{
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index e0a362596d..b386c73d2a 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -65,6 +65,7 @@ class LLViewerTextureList
friend class LLTextureView;
friend class LLViewerTextureManager;
+ friend class LLLocalBitmap;
public:
static BOOL createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 413eab9888..a7a4281860 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7537,12 +7537,16 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
void LLVOAvatar::dumpArchetypeXML( void* )
{
LLAPRFile outfile;
- outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB );
- apr_file_t* file = outfile.getFileHandle() ;
+ outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml"), LL_APR_WB );
+ apr_file_t* file = outfile.getFileHandle();
if (!file)
{
return;
}
+ else
+ {
+ llinfos << "xmlfile write handle obtained : " << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"new archetype.xml") << llendl;
+ }
apr_file_printf( file, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n" );
apr_file_printf( file, "<linden_genepool version=\"1.0\">\n" );
@@ -7582,6 +7586,11 @@ void LLVOAvatar::dumpArchetypeXML( void* )
}
apr_file_printf( file, "\t</archetype>\n" );
apr_file_printf( file, "\n</linden_genepool>\n" );
+ //explictly close the file if it is still open which it should be
+ if (file)
+ {
+ outfile.close();
+ }
}
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index 0f7f63061b..402504933c 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -810,6 +810,20 @@ const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const
return NULL;
}
+std::vector<LLLocalTextureObject*> LLWearable::getLocalTextureListSeq()
+{
+ std::vector<LLLocalTextureObject*> result;
+
+ for(te_map_t::const_iterator iter = mTEMap.begin();
+ iter != mTEMap.end(); iter++)
+ {
+ LLLocalTextureObject* lto = iter->second;
+ result.push_back(lto);
+ }
+
+ return result;
+}
+
void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject &lto)
{
if( mTEMap.find(index) != mTEMap.end() )
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index fd614ade64..3d8c53a755 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -106,6 +106,7 @@ public:
LLLocalTextureObject* getLocalTextureObject(S32 index);
const LLLocalTextureObject* getLocalTextureObject(S32 index) const;
+ std::vector<LLLocalTextureObject*> getLocalTextureListSeq();
void setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
void addVisualParam(LLVisualParam *param);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e2cb22e307..ab994c71cb 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1035,11 +1035,7 @@ void LLPipeline::releaseGLBuffers()
mTrueNoiseMap = 0;
}
- if (mLightFunc)
- {
- LLImageGL::deleteTextures(1, &mLightFunc);
- mLightFunc = 0;
- }
+ releaseLUTBuffers();
mWaterRef.release();
mWaterDis.release();
@@ -1055,6 +1051,15 @@ void LLPipeline::releaseGLBuffers()
LLVOAvatar::resetImpostors();
}
+void LLPipeline::releaseLUTBuffers()
+{
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+}
+
void LLPipeline::releaseScreenBuffers()
{
mUIScreen.release();
@@ -1150,50 +1155,69 @@ void LLPipeline::createGLBuffers()
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+ createLUTBuffers();
+ }
+
+ gBumpImageList.restoreGL();
+}
+
+void LLPipeline::createLUTBuffers()
+{
+ if (sRenderDeferred)
+ {
if (!mLightFunc)
{
U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
- U8* lg = new U8[lightResX*lightResY];
-
+ U8* ls = new U8[lightResX*lightResY];
+ F32 specExp = gSavedSettings.getF32("RenderSpecularExponent");
+ // Calculate the (normalized) Blinn-Phong specular lookup texture.
for (U32 y = 0; y < lightResY; ++y)
{
for (U32 x = 0; x < lightResX; ++x)
{
- //spec func
+ ls[y*lightResX+x] = 0;
F32 sa = (F32) x/(lightResX-1);
F32 spec = (F32) y/(lightResY-1);
- //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
-
- //F32 sp = acosf(sa)/(1.f-spec);
-
- sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
- F32 a = acosf(sa*0.25f+0.75f);
- F32 m = llmax(0.5f-spec*0.5f, 0.001f);
- F32 t2 = tanf(a)/m;
- t2 *= t2;
-
- F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
- F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
-
- lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+ F32 n = spec * spec * specExp;
+
+ // Nothing special here. Just your typical blinn-phong term.
+ spec = powf(sa, n);
+
+ // 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)));
+
+ // 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);
+
+ // 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);
}
}
-
+
LLImageGL::generateTextures(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, lg);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-
- delete [] lg;
+
+ delete [] ls;
}
}
-
- gBumpImageList.restoreGL();
}
-void LLPipeline::restoreGL()
+
+void LLPipeline::restoreGL()
{
LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
assertInitialized();
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 3c4e389ce0..b8b4f164fe 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -114,8 +114,10 @@ public:
void doResetVertexBuffers();
void resizeScreenTexture();
void releaseGLBuffers();
+ void releaseLUTBuffers();
void releaseScreenBuffers();
void createGLBuffers();
+ void createLUTBuffers();
void allocateScreenBuffer(U32 resX, U32 resY);
bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
index 86232de1a4..44d2c14cc8 100644
--- a/indra/newview/skins/default/xui/en/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="440"
+ height="460"
layout="topleft"
name="Image Preview"
help_topic="image_preview"
@@ -108,7 +108,7 @@
<text
type="string"
length="1"
- bottom="225"
+ bottom="250"
height="45"
word_wrap="true"
follows="top|left"
@@ -137,7 +137,7 @@ Try saving image as 24 bit Targa (.tga).
layout="topleft"
left="165"
name="cancel_btn"
- top="410"
+ top="430"
width="125" />
<button
follows="bottom|left"
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index cad7d72ed7..ffb8b842f0 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -3,15 +3,17 @@
legacy_header_height="18"
can_minimize="false"
can_resize="true"
- height="290"
+ height="330"
layout="topleft"
- min_height="290"
+ min_height="330"
min_width="410"
name="texture picker"
help_topic="texture_picker"
title="PICK: TEXTURE"
width="410">
- <floater.string
+
+<!-- top static -->
+ <floater.string
name="choose_picture">
Click to choose a picture
</floater.string>
@@ -19,6 +21,16 @@
name="pick title">
Pick:
</floater.string>
+
+ <view
+ left="4"
+ top="20"
+ name="preview_widget"
+ height="165"
+ width="165"
+ follows="left|top"
+ />
+
<text
type="string"
length="1"
@@ -34,70 +46,94 @@
width="163">
Multiple textures
</text>
+
+ <!-- mode selector -->
+ <radio_group
+ control_name="mode_selection"
+ height="20"
+ layout="topleft"
+ left="18"
+ top_pad="80"
+ name="mode_selection"
+ follows="left|top">
+ <radio_item
+ label="Inventory"
+ name="inventory"
+ top_delta="20"
+ layout="topleft"
+ height="16"
+ left="0"
+ value="0"
+ width="80" />
+ <radio_item
+ label="Local"
+ left_pad="0"
+ layout="topleft"
+ top_delta="0"
+ height="16"
+ name="local"
+ value="1"
+ width="75" />
+ </radio_group>
+ <!-- -->
+
<text
type="string"
length="1"
follows="left|top"
height="14"
layout="topleft"
- left_delta="0"
+ left_delta="-12"
name="unknown"
- top_pad="80"
- width="163">
+ top_pad="4"
+ width="">
Size: [DIMENSIONS]
</text>
+
+<!-- middle: inventory mode -->
+
<button
enabled="false"
- follows="left|bottom"
- height="20"
+ follows="left|top"
+ height="18"
label="Default"
label_selected="Default"
layout="topleft"
- left_delta="0"
name="Default"
- top_pad="4"
- width="80" />
+ width="73"
+ left="94"
+ top="215"/>
<button
+ follows="left|top"
+ height="20"
+ label="Blank"
+ label_selected="Blank"
+ layout="topleft"
+ left_delta="0"
+ name="Blank"
+ top_pad="5"
+ width="73" />
+ <button
enabled="false"
- follows="left|bottom"
+ follows="left|top"
height="20"
label="None"
label_selected="None"
layout="topleft"
- left_pad="4"
+ left_delta="0"
name="None"
- top_delta="0"
- width="80" />
- <button
- follows="left|bottom"
- height="20"
- label="Blank"
- label_selected="Blank"
- layout="topleft"
- left="4"
- name="Blank"
top_pad="5"
- width="80" />
- <button
- follows="left|bottom"
+ width="73" />
+ <button
+ follows="left|top"
height="28"
image_selected="eye_button_active.tga"
image_unselected="eye_button_inactive.tga"
layout="topleft"
- left_pad="50"
- top_delta="3"
+ left_delta="-80"
+ top_delta="-25"
name="Pipette"
width="28" />
- <check_box
- follows="left|bottom"
- height="20"
- initial_value="true"
- label="Apply now"
- layout="topleft"
- left="4"
- name="apply_immediate_check"
- top="262"
- width="120" />
<filter_editor
follows="left|top|right"
height="23"
@@ -113,7 +149,7 @@
bg_alpha_color="DkGray2"
border="false"
follows="all"
- height="200"
+ height="233"
layout="topleft"
left_delta="0"
name="inventory panel"
@@ -128,23 +164,89 @@
top_pad="0"
left_delta="-3"
width="200" />
- <button
- follows="right|bottom"
+
+<!-- middle: local mode -->
+ <button
+ follows="left|top"
+ height="18"
+ label="Add"
+ label_selected="Add"
+ layout="topleft"
+ left="94"
+ top="215"
+ name="l_add_btn"
+ width="73"
+ visible="false"/>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Remove"
+ label_selected="Remove"
+ layout="topleft"
+ left_delta="0"
+ name="l_rem_btn"
+ top_pad="5"
+ width="73"
+ visible="false"/>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Upload"
+ label_selected="Upload"
+ layout="topleft"
+ left_delta="0"
+ name="l_upl_btn"
+ top_pad="5"
+ width="73"
+ visible="false"/>
+ <scroll_list
+ name="l_name_list"
+ left="170"
+ top="22"
+ width="235"
+ height="260"
+ follows="left|top|right|bottom"
+ column_padding="0"
+ can_resize="false"
+ draw_heading="true"
+ multi_select="true"
+ search_column="1"
+ visible="false">
+ <column name="unit_name" label="Name" dynamicwidth="true" />
+ <column name="unit_id_HIDDEN" label="ID" width="0" />
+ </scroll_list>
+
+<!-- bottom static -->
+ <button
+ follows="bottom"
height="20"
label="OK"
label_selected="OK"
layout="topleft"
- right="-120"
+ left="95"
+ top="-30"
name="Select"
width="100" />
<button
- follows="right|bottom"
+ follows="bottom"
height="20"
label="Cancel"
label_selected="Cancel"
layout="topleft"
- right="-10"
- left_pad="5"
+ left_delta="120"
+ top_delta="0"
name="Cancel"
width="100" />
+ <check_box
+ follows="left|bottom"
+ height="20"
+ initial_value="true"
+ label="Apply now"
+ layout="topleft"
+ left="6"
+ name="apply_immediate_check"
+ top_delta="0"
+ width="120" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_window_size.xml b/indra/newview/skins/default/xui/en/floater_window_size.xml
index 355d257785..115fe413f3 100644
--- a/indra/newview/skins/default/xui/en/floater_window_size.xml
+++ b/indra/newview/skins/default/xui/en/floater_window_size.xml
@@ -28,22 +28,50 @@
tool_tip="width x height"
top_pad="5"
width="179">
- <combo_box.item
- label="1000 x 700 (default)"
- name="item0"
- value="1000 x 700" />
- <combo_box.item
- label="1024 x 768"
- name="item1"
- value="1024 x 768" />
- <combo_box.item
- label="1280 x 720 (720p)"
- name="item2"
- value="1280 x 720" />
- <combo_box.item
- label="1920 x 1080 (1080p)"
- name="item3"
- value="1920 x 1080" />
+ <combo_box.item
+ label="1000 x 700 (default)"
+ name="item1"
+ value="1000 x 700" />
+ <combo_box.item
+ label="1024 x 768 (4:3 XGA)"
+ name="item2"
+ value="1024 x 768" />
+ <combo_box.item
+ label="1280 x 720 (16:9 HDTV)"
+ name="item3"
+ value="1280 x 720" />
+ <combo_box.item
+ label="1280 x 800 (5:8 WXGA)"
+ name="item4"
+ value="1280 x 800" />
+ <combo_box.item
+ label="1280 x 1024 (5:4 SXGA)"
+ name="item5"
+ value="1280 x 1024" />
+ <combo_box.item
+ label="1440 x 900 (8:5 WSXGA)"
+ name="item7"
+ value="1440 x 900" />
+ <combo_box.item
+ label="1600 x 900 (16:9 HD+)"
+ name="item8"
+ value="1600 x 900" />
+ <combo_box.item
+ label="1600 x 1200 (4:3 UXGA)"
+ name="item9"
+ value="1600 x 1200" />
+ <combo_box.item
+ label="1680 x 1050 (8:5 WSXGA+)"
+ name="item10"
+ value="1680 x 1050" />
+ <combo_box.item
+ label="1920 x 1080 (16:9 HDTV)"
+ name="item11"
+ value="1920 x 1080" />
+ <combo_box.item
+ label="1920 x 1200 (8:5 WUXGA)"
+ name="item12"
+ value="1920 x 1200" />
</combo_box>
<button
follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 59dd17ea9d..afc5b916e7 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7696,4 +7696,31 @@ Otherwise, you can look at the Map and find places marked &quot;Infohub&quot;.
You died and have been teleported to your home location.
</global>
+ <notification
+ icon="alertmodal.tga"
+ name="LocalBitmapsUpdateFileNotFound"
+ persist="true"
+ type="notify">
+[FNAME] could not be updated because the file could no longer be found.
+Disabling future updates for this file.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LocalBitmapsUpdateFailedFinal"
+ persist="true"
+ type="notify">
+[FNAME] could not be opened or decoded for [NRETRIES] attempts, and is now considered broken.
+Disabling future updates for this file.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LocalBitmapsVerifyFail"
+ persist="true"
+ type="notify">
+Attempted to add an invalid or unreadable image file [FNAME] which could not be opened or decoded.
+Attempt cancelled.
+ </notification>
+
</notifications>