diff options
Diffstat (limited to 'indra/newview')
27 files changed, 1461 insertions, 91 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85b943c70..54134fb610 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 @@ -859,6 +860,7 @@ set(viewer_HEADER_FILES lllistbrowser.h lllistcontextmenu.h lllistview.h + lllocalbitmaps.h lllocaltextureobject.h lllocationhistory.h lllocationinputctrl.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 49fbdbf1df..1174d108d2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1487,6 +1487,9 @@ void LLAppViewer::flushVFSIO() bool LLAppViewer::cleanup() { + //ditch LLVOAvatarSelf instance + gAgentAvatarp = NULL; + // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index a42677845e..91cf630932 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; } @@ -178,7 +179,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 +212,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 +278,7 @@ public: return; } - queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(message); + queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM); } private: @@ -464,7 +465,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 +638,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 +691,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 +746,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/lldrawpool.h b/indra/newview/lldrawpool.h index 5a2981e749..64774d06df 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -133,6 +133,7 @@ public: PASS_ALPHA, PASS_ALPHA_MASK, PASS_FULLBRIGHT_ALPHA_MASK, + PASS_ALPHA_INVISIBLE, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ddb7d3ceeb..5b62dbc560 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -337,6 +337,7 @@ void LLDrawPoolAlpha::render(S32 pass) pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); if(shaders) { diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 8f47d3c5e5..64eb11fc9b 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -139,7 +139,7 @@ void LLDriverParamInfo::toStream(std::ostream &out) } else { - llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp << " for driver parameter " << getID() << llendl; + llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << gAgentAvatarp.get() << " for driver parameter " << getID() << llendl; } out << std::endl; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cebe93f042..c0065a94e6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -73,7 +73,7 @@ #include "llwearablelist.h" // Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0 +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 #define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0 #define BLOCK_WORN_ITEMS_IN_OUTBOX 1 diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp new file mode 100644 index 0000000000..b96fc06226 --- /dev/null +++ b/indra/newview/lllocalbitmaps.cpp @@ -0,0 +1,925 @@ +/** + * @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" + +/*=======================================*/ +/* 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. + true means the unit's update is running for the first time so it will not check + for current usage nor will it attempt to replace the old, non existent image */ + mValid = updateSelf(true); +} + +LLLocalBitmap::~LLLocalBitmap() +{ + // replace IDs with defaults, if set to do so. + if(LL_LOCAL_REPLACE_ON_DEL) + { + 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(bool first_update) +{ + 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 (!first_update && !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 (!first_update) + { + // 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; + + 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; + + 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 + { + 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..c6d05c1763 --- /dev/null +++ b/indra/newview/lllocalbitmaps.h @@ -0,0 +1,130 @@ +/** + * @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(); + bool updateSelf(bool first_update = false); + + public: /* accessors */ + std::string getFilename(); + std::string getShortName(); + LLUUID getTrackingID(); + LLUUID getWorldID(); + bool getValid(); + + private: /* maintenance */ + bool decodeBitmap(LLPointer<LLImageRaw> raw); + void replaceIDs(LLUUID old_id, LLUUID new_id); + + private: /* id replacement */ + 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: /* 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/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index a3f0a6062c..93dd82957f 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llhttpclient.h" +#include "lltimer.h" #include "lltrans.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -115,6 +116,9 @@ namespace LLMarketplaceImport static U32 sImportResultStatus = 0; static LLSD sImportResults = LLSD::emptyMap(); + static LLTimer slmGetTimer; + static LLTimer slmPostTimer; + // Responders class LLImportPostResponder : public LLHTTPClient::Responder @@ -124,11 +128,15 @@ namespace LLMarketplaceImport void completed(U32 status, const std::string& reason, const LLSD& content) { + slmPostTimer.stop(); + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { llinfos << " SLM POST status: " << status << llendl; llinfos << " SLM POST reason: " << reason << llendl; llinfos << " SLM POST content: " << content.asString() << llendl; + + llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; } if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || @@ -167,11 +175,15 @@ namespace LLMarketplaceImport void completed(U32 status, const std::string& reason, const LLSD& content) { + slmGetTimer.stop(); + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { llinfos << " SLM GET status: " << status << llendl; llinfos << " SLM GET reason: " << reason << llendl; llinfos << " SLM GET content: " << content.asString() << llendl; + + llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; } if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || @@ -247,6 +259,7 @@ namespace LLMarketplaceImport llinfos << " SLM GET: " << url << llendl; } + slmGetTimer.start(); LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders()); return true; @@ -277,6 +290,7 @@ namespace LLMarketplaceImport llinfos << " SLM GET: " << url << llendl; } + slmGetTimer.start(); LLHTTPClient::get(url, new LLImportGetResponder(), headers); return true; @@ -310,6 +324,7 @@ namespace LLMarketplaceImport llinfos << " SLM POST: " << url << llendl; } + slmPostTimer.start(); LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); return true; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index de22f2ae6b..6a64e6d76a 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; @@ -1126,7 +1260,7 @@ void LLTextureCtrl::onFloaterClose() mFloaterHandle.markDead(); } -void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) +void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); @@ -1139,14 +1273,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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99540ccce9..5087930dba 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6513,31 +6513,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(); @@ -6546,6 +6552,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/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8a713ae22c..e0653fec30 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2021,6 +2021,12 @@ void LLViewerWindow::shutdownGL() gSky.cleanup(); stop_glerror(); + llinfos << "Cleaning up pipeline" << llendl; + gPipeline.cleanup(); + stop_glerror(); + + //MUST clean up pipeline before cleaning up wearables + llinfos << "Cleaning up wearables" << llendl; LLWearableList::instance().cleanup() ; gTextureList.shutdown(); @@ -2031,10 +2037,6 @@ void LLViewerWindow::shutdownGL() LLWorldMapView::cleanupTextures(); - llinfos << "Cleaning up pipeline" << llendl; - gPipeline.cleanup(); - stop_glerror(); - LLViewerTextureManager::cleanup() ; LLImageGL::cleanupClass() ; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bc7f5a9744..f46cedfc4b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7533,11 +7533,15 @@ 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() ; + apr_file_t* file = outfile.getFileHandle(); if (!file) { return; } + else + { + llinfos << "xmlfile write handle obtained : " << gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"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" ); @@ -7577,6 +7581,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/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f1df67494f..e525d6bad0 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -66,10 +66,11 @@ #include <boost/lexical_cast.hpp> -LLVOAvatarSelf *gAgentAvatarp = NULL; +LLPointer<LLVOAvatarSelf> gAgentAvatarp = NULL; + BOOL isAgentAvatarValid() { - return (gAgentAvatarp && + return (gAgentAvatarp.notNull() && (gAgentAvatarp->getRegion() != NULL) && (!gAgentAvatarp->isDead())); } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 54dbe81993..655fb3a012 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -383,7 +383,7 @@ private: }; -extern LLVOAvatarSelf *gAgentAvatarp; +extern LLPointer<LLVOAvatarSelf> gAgentAvatarp; BOOL isAgentAvatarValid(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7492a06784..03d4c51aff 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4433,10 +4433,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { if (te->getColor().mV[3] > 0.f) - { + { //only treat as alpha in the pipeline if < 100% transparent drawablep->setState(LLDrawable::HAS_ALPHA); - alpha_faces.push_back(facep); } + alpha_faces.push_back(facep); } } else @@ -4947,7 +4947,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: if (is_alpha) { // can we safely treat this as an alpha mask? - if (facep->canRenderAsMask()) + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask()) { if (te->getFullbright() || LLPipeline::sNoAlpha) { diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index d8aa0b7d5c..402504933c 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -221,7 +221,7 @@ void LLWearable::createVisualParams() param->resetDrivenParams(); if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp,_1 ), true)) + if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) { llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; continue; @@ -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 <o) { 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 <o); void addVisualParam(LLVisualParam *param); 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_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml index 498a9b6ce0..6f387f4800 100644 --- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml +++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml @@ -132,16 +132,16 @@ </panel> <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> <layout_panel /> - <layout_panel height="45" auto_resize="false"> - <layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all"> + <layout_panel height="24" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all"> <layout_panel width="0" /> - <layout_panel width="45" auto_resize="false"> + <layout_panel width="24" auto_resize="false"> <loading_indicator - height="45" + height="24" layout="topleft" left="0" top="0" - width="45" /> + width="24" /> </layout_panel> <layout_panel width="0" /> </layout_stack> 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/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index cd8550b00d..1d11abcf73 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -153,6 +153,13 @@ function="BuyCurrency" /> </menu_item_call> <menu_item_call + label="Merchant Outbox..." + name="MerchantOutbox"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="outbox" /> + </menu_item_call> + <menu_item_call label="Account dashboard..." name="Manage My Account"> <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index fcba937bdb..29aa6d1039 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -112,7 +112,7 @@ bg_opaque_color="InventoryBackgroundColor" background_visible="true" background_opaque="true" - tool_tip="Drag and drop items to your inventory to manage and use them" + tool_tip="Drag and drop items to your inventory to use them" > <text name="inbox_inventory_placeholder" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3351ffe00f..4bc72be49b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2037,7 +2037,7 @@ Returns a string with the requested data about the region <string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string> <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string> - <string name="InventoryInboxNoItems">Certain items you receive, such as premium gifts, will appear here. You may then drag them into your inventory.</string> + <string name="InventoryInboxNoItems">Your Marketplace purchases will appear here. You may then drag them into your inventory to use them.</string> <string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> <string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> <string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string> |