diff options
Diffstat (limited to 'indra')
549 files changed, 22670 insertions, 12608 deletions
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index ce5c7142d5..06b4f6c75a 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -151,7 +151,7 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)  	mCachedProcessedTexture(pOther.mCachedProcessedTexture),  	mStaticImageTGA(pOther.mStaticImageTGA),  	mStaticImageRaw(pOther.mStaticImageRaw), -	mNeedsCreateTexture(pOther.mNeedsCreateTexture), +	mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()),  	mStaticImageInvalid(pOther.mStaticImageInvalid),  	mAvgDistortionVec(pOther.mAvgDistortionVec),  	mCachedEffectiveWeight(pOther.mCachedEffectiveWeight) diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index e2440998b3..000f55685e 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -100,7 +100,7 @@ private:  	LLPointer<LLGLTexture>	mCachedProcessedTexture;  	LLPointer<LLImageTGA>	mStaticImageTGA;  	LLPointer<LLImageRaw>	mStaticImageRaw; -	BOOL					mNeedsCreateTexture; +	std::atomic<BOOL>		mNeedsCreateTexture;  	BOOL					mStaticImageInvalid;  	LL_ALIGN_16(LLVector4a				mAvgDistortionVec);  	F32						mCachedEffectiveWeight; diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 59aa731af2..62307c6e26 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -29,6 +29,7 @@ include_directories(  #     ${LLCOMMON_LIBRARIES})  set(llcommon_SOURCE_FILES +    commoncontrol.cpp      indra_constants.cpp      llallocator.cpp      llallocator_heap_profile.cpp @@ -130,6 +131,7 @@ set(llcommon_HEADER_FILES      chrono.h      classic_callback.h +    commoncontrol.h      ctype_workaround.h      fix_macros.h      indra_constants.h diff --git a/indra/llcommon/commoncontrol.cpp b/indra/llcommon/commoncontrol.cpp new file mode 100644 index 0000000000..81e66baf8c --- /dev/null +++ b/indra/llcommon/commoncontrol.cpp @@ -0,0 +1,106 @@ +/** + * @file   commoncontrol.cpp + * @author Nat Goodspeed + * @date   2022-06-08 + * @brief  Implementation for commoncontrol. + *  + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "commoncontrol.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llevents.h" +#include "llsdutil.h" + +LLSD LL::CommonControl::access(const LLSD& params) +{ +    // We can't actually introduce a link-time dependency on llxml, or on any +    // global LLControlGroup (*koff* gSavedSettings *koff*) but we can issue a +    // runtime query. If we're running as part of a viewer with +    // LLViewerControlListener, we can use that to interact with any +    // instantiated LLControGroup. +    LLSD response; +    { +        LLEventStream reply("reply"); +        LLTempBoundListener connection = reply.listen("listener", +                     [&response] (const LLSD& event) +                     { +                         response = event; +                         return false; +                     }); +        LLSD rparams{ params }; +        rparams["reply"] = reply.getName(); +        LLEventPumps::instance().obtain("LLViewerControl").post(rparams); +    } +    // LLViewerControlListener responds immediately. If it's listening at all, +    // it will already have set response. +    if (! response.isDefined()) +    { +        LLTHROW(NoListener("No LLViewerControl listener instantiated")); +    } +    LLSD error{ response["error"] }; +    if (error.isDefined()) +    { +        LLTHROW(ParamError(error)); +    } +    response.erase("error"); +    response.erase("reqid"); +    return response; +} + +/// set control group.key to defined default value +LLSD LL::CommonControl::set_default(const std::string& group, const std::string& key) +{ +    return access(llsd::map("op", "set", +                            "group", group, "key", key))["value"]; +} + +/// set control group.key to specified value +LLSD LL::CommonControl::set(const std::string& group, const std::string& key, const LLSD& value) +{ +    return access(llsd::map("op", "set", +                            "group", group, "key", key, "value", value))["value"]; +} + +/// toggle boolean control group.key +LLSD LL::CommonControl::toggle(const std::string& group, const std::string& key) +{ +    return access(llsd::map("op", "toggle", +                            "group", group, "key", key))["value"]; +} + +/// get the definition for control group.key, (! isDefined()) if bad +/// ["name"], ["type"], ["value"], ["comment"] +LLSD LL::CommonControl::get_def(const std::string& group, const std::string& key) +{ +    return access(llsd::map("op", "get", +                            "group", group, "key", key)); +} + +/// get the value of control group.key +LLSD LL::CommonControl::get(const std::string& group, const std::string& key) +{ +    return access(llsd::map("op", "get", +                            "group", group, "key", key))["value"]; +} + +/// get defined groups +std::vector<std::string> LL::CommonControl::get_groups() +{ +    auto groups{ access(llsd::map("op", "groups"))["groups"] }; +    return { groups.beginArray(), groups.endArray() }; +} + +/// get definitions for all variables in group +LLSD LL::CommonControl::get_vars(const std::string& group) +{ +    return access(llsd::map("op", "vars", "group", group))["vars"]; +} diff --git a/indra/llcommon/commoncontrol.h b/indra/llcommon/commoncontrol.h new file mode 100644 index 0000000000..07d4a45ac5 --- /dev/null +++ b/indra/llcommon/commoncontrol.h @@ -0,0 +1,75 @@ +/** + * @file   commoncontrol.h + * @author Nat Goodspeed + * @date   2022-06-08 + * @brief  Access LLViewerControl LLEventAPI, if process has one. + *  + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_COMMONCONTROL_H) +#define LL_COMMONCONTROL_H + +#include <vector> +#include "llexception.h" +#include "llsd.h" + +namespace LL +{ +    class CommonControl +    { +    public: +        struct Error: public LLException +        { +            Error(const std::string& what): LLException(what) {} +        }; + +        /// Exception thrown if there's no LLViewerControl LLEventAPI +        struct NoListener: public Error +        { +            NoListener(const std::string& what): Error(what) {} +        }; + +        struct ParamError: public Error +        { +            ParamError(const std::string& what): Error(what) {} +        }; + +        /// set control group.key to defined default value +        static +        LLSD set_default(const std::string& group, const std::string& key); + +        /// set control group.key to specified value +        static +        LLSD set(const std::string& group, const std::string& key, const LLSD& value); + +        /// toggle boolean control group.key +        static +        LLSD toggle(const std::string& group, const std::string& key); + +        /// get the definition for control group.key, (! isDefined()) if bad +        /// ["name"], ["type"], ["value"], ["comment"] +        static +        LLSD get_def(const std::string& group, const std::string& key); + +        /// get the value of control group.key +        static +        LLSD get(const std::string& group, const std::string& key); + +        /// get defined groups +        static +        std::vector<std::string> get_groups(); + +        /// get definitions for all variables in group +        static +        LLSD get_vars(const std::string& group); + +    private: +        static +        LLSD access(const LLSD& params); +    }; +} // namespace LL + +#endif /* ! defined(LL_COMMONCONTROL_H) */ diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index db94765871..b537102510 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -526,6 +526,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)  //static  S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)  { +    LL_PROFILE_ZONE_SCOPED;  	//*****************************************  	LLAPRFilePoolScope scope(pool);  	apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);  @@ -570,6 +571,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb  //static  S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)  { +    LL_PROFILE_ZONE_SCOPED;  	apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;  	if (offset < 0)  	{ diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 58af32f1af..1e9920746b 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -29,11 +29,6 @@  #include "llframetimer.h" -// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support -//#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER -//	#include "TracyClient.cpp" -//#endif // LL_PROFILER_CONFIGURATION -  // Static members  //LLTimer	LLFrameTimer::sInternalTimer;  U64 LLFrameTimer::sStartTotalTime = totalTime(); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 849867586a..749b66b472 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -35,6 +35,7 @@  # include <sys/types.h>  # include <mach/task.h>  # include <mach/mach_init.h> +#include <mach/mach_host.h>  #elif LL_LINUX  # include <unistd.h>  #endif @@ -109,6 +110,50 @@ void LLMemory::updateMemoryInfo()  	{  		sAvailPhysicalMemInKB = U32Kilobytes(0);  	} + +#elif defined(LL_DARWIN) +    task_vm_info info; +    mach_msg_type_number_t  infoCount = TASK_VM_INFO_COUNT; +    // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint. +    if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &infoCount) == KERN_SUCCESS) +    { +        // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of +        // memory that the memory manager has committed for a running process", which is rss. +        sAllocatedPageSizeInKB = U32Bytes(info.resident_size); + +        // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size +        // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less. +        //        I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals. +        // +        // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value +        // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint. +        // +        // (On Windows, we use WorkingSetSize.) +        sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable); +     } +    else +    { +        LL_WARNS() << "task_info failed" << LL_ENDL; +    } + +    // Total installed and available physical memory are properties of the host, not just our process. +    vm_statistics64_data_t vmstat; +    mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; +    mach_port_t host = mach_host_self(); +    vm_size_t page_size; +    host_page_size(host, &page_size); +    kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); +    if (result == KERN_SUCCESS) { +        // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.' +        // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure. +        sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size); +        sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize(); +      } +    else +    { +        LL_WARNS() << "task_info failed" << LL_ENDL; +    } +  #else  	//not valid for other systems for now.  	sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index bc46128d21..c0f5868db3 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -134,6 +134,10 @@ extern thread_local bool gProfilerEnabled;          #define LL_PROFILE_ZONE_ERR(name)               LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000  )  // RGB yellow          #define LL_PROFILE_ZONE_INFO(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF  )  // RGB cyan          #define LL_PROFILE_ZONE_WARN(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 )  // RGB red +        //#define LL_PROFILE_ALLOC(ptr, size)             TracyAlloc(ptr, size) // memory allocation tracking currently not working +        //#define LL_PROFILE_FREE(ptr)                    TracyFree(ptr) +        #define LL_PROFILE_ALLOC(ptr, size)             (void)(ptr); (void)(size); +        #define LL_PROFILE_FREE(ptr)                    (void)(ptr);      #endif  #else      #define LL_PROFILER_FRAME_END diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 8cef4293cd..155e32ebae 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -26,20 +26,26 @@  #include "linden_common.h"  #include "llqueuedthread.h" +#include <chrono> +  #include "llstl.h"  #include "lltimer.h"	// ms_sleep() -#include "lltracethreadrecorder.h" +#include "llmutex.h"  //============================================================================  // MAIN THREAD  LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : -	LLThread(name), -	mThreaded(threaded), -	mIdleThread(TRUE), -	mNextHandle(0), -	mStarted(FALSE) +    LLThread(name), +    mIdleThread(TRUE), +    mNextHandle(0), +    mStarted(FALSE), +    mThreaded(threaded), +    mRequestQueue(name, 1024 * 1024)  { +    llassert(threaded); // not threaded implementation is deprecated +    mMainQueue = LL::WorkQueue::getInstance("mainloop"); +  	if (mThreaded)  	{  		if(should_pause) @@ -69,6 +75,11 @@ void LLQueuedThread::shutdown()  	unpause(); // MAIN THREAD  	if (mThreaded)  	{ +        if (mRequestQueue.size() == 0) +        { +            mRequestQueue.close(); +        } +  		S32 timeout = 100;  		for ( ; timeout>0; timeout--)  		{ @@ -104,6 +115,8 @@ void LLQueuedThread::shutdown()  	{  		LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;  	} + +    mRequestQueue.close();  }  //---------------------------------------------------------------------------- @@ -112,6 +125,7 @@ void LLQueuedThread::shutdown()  // virtual  S32 LLQueuedThread::update(F32 max_time_ms)  { +    LL_PROFILE_ZONE_SCOPED;  	if (!mStarted)  	{  		if (!mThreaded) @@ -125,29 +139,34 @@ S32 LLQueuedThread::update(F32 max_time_ms)  S32 LLQueuedThread::updateQueue(F32 max_time_ms)  { -	F64 max_time = (F64)max_time_ms * .001; -	LLTimer timer; -	S32 pending = 1; - +    LL_PROFILE_ZONE_SCOPED;  	// Frame Update  	if (mThreaded)  	{ -		pending = getPending(); -		if(pending > 0) +        // schedule a call to threadedUpdate for every call to updateQueue +        if (!isQuitting()) +        { +            mRequestQueue.post([=]() +                { +                    LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update"); +                    mIdleThread = FALSE; +                    threadedUpdate(); +                    mIdleThread = TRUE; +                } +            ); +        } + +		if(getPending() > 0)  		{ -		unpause(); -	} +		    unpause(); +	    }  	}  	else  	{ -		while (pending > 0) -		{ -			pending = processNextRequest(); -			if (max_time && timer.getElapsedTimeF64() > max_time) -				break; -		} +        mRequestQueue.runFor(std::chrono::microseconds((int) (max_time_ms*1000.f))); +        threadedUpdate();  	} -	return pending; +	return getPending();  }  void LLQueuedThread::incQueue() @@ -166,11 +185,7 @@ void LLQueuedThread::incQueue()  // May be called from any thread  S32 LLQueuedThread::getPending()  { -	S32 res; -	lockData(); -	res = mRequestQueue.size(); -	unlockData(); -	return res; +	return mRequestQueue.size();  }  // MAIN thread @@ -195,35 +210,28 @@ void LLQueuedThread::waitOnPending()  // MAIN thread  void LLQueuedThread::printQueueStats()  { -	lockData(); -	if (!mRequestQueue.empty()) +    U32 size = mRequestQueue.size(); +	if (size > 0)  	{ -		QueuedRequest *req = *mRequestQueue.begin(); -		LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL; +		LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL;  	}  	else  	{  		LL_INFOS() << "Queued Thread Idle" << LL_ENDL;  	} -	unlockData();  }  // MAIN thread  LLQueuedThread::handle_t LLQueuedThread::generateHandle()  { -	lockData(); -	while ((mNextHandle == nullHandle()) || (mRequestHash.find(mNextHandle))) -	{ -		mNextHandle++; -	} -	const LLQueuedThread::handle_t res = mNextHandle++; -	unlockData(); +    U32 res = ++mNextHandle;  	return res;  }  // MAIN thread  bool LLQueuedThread::addRequest(QueuedRequest* req)  { +    LL_PROFILE_ZONE_SCOPED;  	if (mStatus == QUITTING)  	{  		return false; @@ -231,14 +239,14 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)  	lockData();  	req->setStatus(STATUS_QUEUED); -	mRequestQueue.insert(req); -	mRequestHash.insert(req); +    mRequestHash.insert(req);  #if _DEBUG  // 	LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;  #endif  	unlockData(); -	incQueue(); +    llassert(!mDataLock->isSelfLocked()); +    mRequestQueue.post([this, req]() { processRequest(req); });  	return true;  } @@ -246,6 +254,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)  // MAIN thread  bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)  { +    LL_PROFILE_ZONE_SCOPED;  	llassert (handle != nullHandle());  	bool res = false;  	bool waspaused = isPaused(); @@ -312,6 +321,7 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)  void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;  	lockData();  	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);  	if (req) @@ -333,30 +343,9 @@ void LLQueuedThread::setFlags(handle_t handle, U32 flags)  	unlockData();  } -void LLQueuedThread::setPriority(handle_t handle, U32 priority) -{ -	lockData(); -	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); -	if (req) -	{ -		if(req->getStatus() == STATUS_INPROGRESS) -		{ -			// not in list -			req->setPriority(priority); -		} -		else if(req->getStatus() == STATUS_QUEUED) -		{ -			// remove from list then re-insert -			llverify(mRequestQueue.erase(req) == 1); -			req->setPriority(priority); -			mRequestQueue.insert(req); -		} -	} -	unlockData(); -} -  bool LLQueuedThread::completeRequest(handle_t handle)  { +    LL_PROFILE_ZONE_SCOPED;  	bool res = false;  	lockData();  	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); @@ -399,89 +388,115 @@ bool LLQueuedThread::check()  //============================================================================  // Runs on its OWN thread -S32 LLQueuedThread::processNextRequest() +void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)  { -	QueuedRequest *req; +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + +    mIdleThread = FALSE; +    //threadedUpdate(); +  	// Get next request from pool  	lockData(); -	while(1) +	if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))  	{ -		req = NULL; -		if (mRequestQueue.empty()) +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - abort"); +		req->setStatus(STATUS_ABORTED); +		req->finishRequest(false); +		if (req->getFlags() & FLAG_AUTO_COMPLETE)  		{ -			break; -		} -		req = *mRequestQueue.begin(); -		mRequestQueue.erase(mRequestQueue.begin()); -		if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING)) -		{ -			req->setStatus(STATUS_ABORTED); -			req->finishRequest(false); -			if (req->getFlags() & FLAG_AUTO_COMPLETE) -			{ -				mRequestHash.erase(req); -				req->deleteRequest(); -// 				check(); -			} -			continue; -		} -		llassert_always(req->getStatus() == STATUS_QUEUED); -		break; -	} -	U32 start_priority = 0 ; -	if (req) -	{ -		req->setStatus(STATUS_INPROGRESS); -		start_priority = req->getPriority(); -	} -	unlockData(); - -	// This is the only place we will call req->setStatus() after -	// it has initially been seet to STATUS_QUEUED, so it is -	// safe to access req. -	if (req) -	{ -		// process request		 -		bool complete = req->processRequest(); - -		if (complete) -		{ -			lockData(); -			req->setStatus(STATUS_COMPLETE); -			req->finishRequest(true); -			if (req->getFlags() & FLAG_AUTO_COMPLETE) -			{ -				mRequestHash.erase(req); -				req->deleteRequest(); +			mRequestHash.erase(req); +			req->deleteRequest();  // 				check(); -			} -			unlockData();  		} -		else -		{ -			lockData(); -			req->setStatus(STATUS_QUEUED); -			mRequestQueue.insert(req); -			unlockData(); -			if (mThreaded && start_priority < PRIORITY_NORMAL) -			{ -				ms_sleep(1); // sleep the thread a little -			} -		} -		 -		LLTrace::get_thread_recorder()->pushToParent(); +        unlockData();  	} +    else +    { +        llassert_always(req->getStatus() == STATUS_QUEUED); + +        if (req) +        { +            req->setStatus(STATUS_INPROGRESS); +        } +        unlockData(); + +        // This is the only place we will call req->setStatus() after +        // it has initially been seet to STATUS_QUEUED, so it is +        // safe to access req. +        if (req) +        { +            // process request		 +            bool complete = req->processRequest(); + +            if (complete) +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - complete"); +                lockData(); +                req->setStatus(STATUS_COMPLETE); +                req->finishRequest(true); +                if (req->getFlags() & FLAG_AUTO_COMPLETE) +                { +                    mRequestHash.erase(req); +                    req->deleteRequest(); +                    // 				check(); +                } +                unlockData(); +            } +            else +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - retry"); +                //put back on queue and try again in 0.1ms +                lockData(); +                req->setStatus(STATUS_QUEUED); +                 +                unlockData(); + +                llassert(!mDataLock->isSelfLocked()); + +#if 0 +                // try again on next frame +                // NOTE: tried using "post" with a time in the future, but this +                // would invariably cause this thread to wait for a long time (10+ ms) +                // while work is pending +                bool ret = LL::WorkQueue::postMaybe( +                    mMainQueue, +                    [=]() +                    { +                        LL_PROFILE_ZONE_NAMED("processRequest - retry"); +                        mRequestQueue.post([=]() +                            { +                                LL_PROFILE_ZONE_NAMED("processRequest - retry"); // <-- not redundant, track retry on both queues +                                processRequest(req); +                            }); +                    }); +                llassert(ret); +#else +                using namespace std::chrono_literals; +                auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms; +                mRequestQueue.post([=] +                    { +                        LL_PROFILE_ZONE_NAMED("processRequest - retry"); +                        while (LL::WorkQueue::TimePoint::clock::now() < retry_time) +                        { +                            std::this_thread::yield(); //note: don't use LLThread::yield here to avoid  +                        } +                        processRequest(req); +                    }); +#endif +                 +            } +        } +    } -	S32 pending = getPending(); -	return pending; +    mIdleThread = TRUE;  }  // virtual  bool LLQueuedThread::runCondition()  {  	// mRunCondition must be locked here -	if (mRequestQueue.empty() && mIdleThread) +	if (mRequestQueue.size() == 0 && mIdleThread)  		return false;  	else  		return true; @@ -495,18 +510,13 @@ void LLQueuedThread::run()  	startThread();  	mStarted = TRUE; -	while (1) + +	/*while (1)  	{ +        LL_PROFILE_ZONE_SCOPED;  		// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.  		checkPause(); -		if (isQuitting()) -		{ -			LLTrace::get_thread_recorder()->pushToParent(); -			endThread(); -			break; -		} -  		mIdleThread = FALSE;  		threadedUpdate(); @@ -515,12 +525,18 @@ void LLQueuedThread::run()  		if (pending_work == 0)  		{ +            //LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep");  			mIdleThread = TRUE; -			ms_sleep(1); +			//ms_sleep(1);  		}  		//LLThread::yield(); // thread should yield after each request		 -	} +	}*/ +    mRequestQueue.runUntilClose(); + +    endThread();  	LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL; + +      }  // virtual @@ -540,10 +556,9 @@ void LLQueuedThread::threadedUpdate()  //============================================================================ -LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 priority, U32 flags) : +LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 flags) :  	LLSimpleHashEntry<LLQueuedThread::handle_t>(handle),  	mStatus(STATUS_UNKNOWN), -	mPriority(priority),  	mFlags(flags)  {  } diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index 5d3f873646..6b82ccc434 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -36,6 +36,7 @@  #include "llthread.h"  #include "llsimplehash.h" +#include "workqueue.h"  //============================================================================  // Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small @@ -45,15 +46,6 @@ class LL_COMMON_API LLQueuedThread : public LLThread  {  	//------------------------------------------------------------------------  public: -	enum priority_t { -		PRIORITY_IMMEDIATE = 0x7FFFFFFF, -		PRIORITY_URGENT =    0x40000000, -		PRIORITY_HIGH =      0x30000000, -		PRIORITY_NORMAL =    0x20000000, -		PRIORITY_LOW =       0x10000000, -		PRIORITY_LOWBITS =   0x0FFFFFFF, -		PRIORITY_HIGHBITS =  0x70000000 -	};  	enum status_t {  		STATUS_EXPIRED = -1,  		STATUS_UNKNOWN = 0, @@ -82,28 +74,17 @@ public:  		virtual ~QueuedRequest(); // use deleteRequest()  	public: -		QueuedRequest(handle_t handle, U32 priority, U32 flags = 0); +		QueuedRequest(handle_t handle, U32 flags = 0);  		status_t getStatus()  		{  			return mStatus;  		} -		U32 getPriority() const -		{ -			return mPriority; -		}  		U32 getFlags() const  		{  			return mFlags;  		} -		bool higherPriority(const QueuedRequest& second) const -		{ -			if ( mPriority == second.mPriority) -				return mHashKey < second.mHashKey; -			else -				return mPriority > second.mPriority; -		} - +		  	protected:  		status_t setStatus(status_t newstatus)  		{ @@ -121,28 +102,11 @@ public:  		virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted  		virtual void deleteRequest(); // Only method to delete a request -		void setPriority(U32 pri) -		{ -			// Only do this on a request that is not in a queued list! -			mPriority = pri; -		}; -		  	protected:  		LLAtomicBase<status_t> mStatus; -		U32 mPriority;  		U32 mFlags;  	}; -protected: -	struct queued_request_less -	{ -		bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const -		{ -			return lhs->higherPriority(*rhs); // higher priority in front of queue (set) -		} -	}; - -  	//------------------------------------------------------------------------  public: @@ -167,7 +131,7 @@ private:  protected:  	handle_t generateHandle();  	bool addRequest(QueuedRequest* req); -	S32  processNextRequest(void); +	void processRequest(QueuedRequest* req);  	void incQueue();  public: @@ -186,7 +150,6 @@ public:  	status_t getRequestStatus(handle_t handle);  	void abortRequest(handle_t handle, bool autocomplete);  	void setFlags(handle_t handle, U32 flags); -	void setPriority(handle_t handle, U32 priority);  	bool completeRequest(handle_t handle);  	// This is public for support classes like LLWorkerThread,  	// but generally the methods above should be used. @@ -200,8 +163,10 @@ protected:  	BOOL mStarted;  // required when mThreaded is false to call startThread() from update()  	LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle -	typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; -	request_queue_t mRequestQueue; +	//typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; +	//request_queue_t mRequestQueue; +    LL::WorkQueue mRequestQueue; +    LL::WorkQueue::weak_t mMainQueue;  	enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2  	typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t; diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 9b6bb3826c..45417bfa37 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -710,20 +710,28 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)  }  #endif +#if LL_DARWIN +// static +U32Kilobytes LLMemoryInfo::getHardwareMemSize() +{ +    // This might work on Linux as well.  Someone check... +    uint64_t phys = 0; +    int mib[2] = { CTL_HW, HW_MEMSIZE }; + +    size_t len = sizeof(phys); +    sysctl(mib, 2, &phys, &len, NULL, 0); + +    return U64Bytes(phys); +} +#endif +  U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const  {  #if LL_WINDOWS  	return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));  #elif LL_DARWIN -	// This might work on Linux as well.  Someone check... -	uint64_t phys = 0; -	int mib[2] = { CTL_HW, HW_MEMSIZE }; - -	size_t len = sizeof(phys);	 -	sysctl(mib, 2, &phys, &len, NULL, 0); -	 -	return U64Bytes(phys); +    return getHardwareMemSize();  #elif LL_LINUX  	U64 phys = 0; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index cb92cb0ac6..538e61c521 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -117,7 +117,10 @@ public:  	LLMemoryInfo(); ///< Default constructor  	void stream(std::ostream& s) const;	///< output text info to s -	U32Kilobytes getPhysicalMemoryKB() const;  +	U32Kilobytes getPhysicalMemoryKB() const; +#if LL_DARWIN +    static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib. +#endif  	//get the available memory infomation in KiloBytes.  	static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index aaa6df325c..39dfee3755 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -30,6 +30,9 @@  #include "u64.h" +#include <chrono> +#include <thread> +  #if LL_WINDOWS  #	include "llwin32headerslean.h"  #elif LL_LINUX || LL_DARWIN @@ -64,7 +67,13 @@ LLTimer* LLTimer::sTimer = NULL;  #if LL_WINDOWS  void ms_sleep(U32 ms)  { -	Sleep(ms); +    LL_PROFILE_ZONE_SCOPED; +    using TimePoint = std::chrono::steady_clock::time_point; +    auto resume_time = TimePoint::clock::now() + std::chrono::milliseconds(ms); +    while (TimePoint::clock::now() < resume_time) +    { +        std::this_thread::yield(); //note: don't use LLThread::yield here to avoid yielding for too long +    }  }  U32 micro_sleep(U64 us, U32 max_yields) diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 4b91b2caca..02ce4823b8 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -133,11 +133,11 @@ S32 LLWorkerThread::update(F32 max_time_ms)  //---------------------------------------------------------------------------- -LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority) +LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param)  {  	handle_t handle = generateHandle(); -	WorkRequest* req = new WorkRequest(handle, priority, workerclass, param); +	WorkRequest* req = new WorkRequest(handle, workerclass, param);  	bool res = addRequest(req);  	if (!res) @@ -160,8 +160,8 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)  //============================================================================  // Runs on its OWN thread -LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) : -	LLQueuedThread::QueuedRequest(handle, priority), +LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) : +	LLQueuedThread::QueuedRequest(handle),  	mWorkerClass(workerclass),  	mParam(param)  { @@ -180,6 +180,7 @@ void LLWorkerThread::WorkRequest::deleteRequest()  // virtual  bool LLWorkerThread::WorkRequest::processRequest()  { +    LL_PROFILE_ZONE_SCOPED;  	LLWorkerClass* workerclass = getWorkerClass();  	workerclass->setWorking(true);  	bool complete = workerclass->doWork(getParam()); @@ -190,6 +191,7 @@ bool LLWorkerThread::WorkRequest::processRequest()  // virtual  void LLWorkerThread::WorkRequest::finishRequest(bool completed)  { +    LL_PROFILE_ZONE_SCOPED;  	LLWorkerClass* workerclass = getWorkerClass();  	workerclass->finishWork(getParam(), completed);  	U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED); @@ -203,7 +205,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na  	: mWorkerThread(workerthread),  	  mWorkerClassName(name),  	  mRequestHandle(LLWorkerThread::nullHandle()), -	  mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),  	  mMutex(),  	  mWorkFlags(0)  { @@ -292,7 +293,7 @@ bool LLWorkerClass::yield()  //----------------------------------------------------------------------------  // calls startWork, adds doWork() to queue -void LLWorkerClass::addWork(S32 param, U32 priority) +void LLWorkerClass::addWork(S32 param)  {  	mMutex.lock();  	llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK))); @@ -306,7 +307,7 @@ void LLWorkerClass::addWork(S32 param, U32 priority)  	startWork(param);  	clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);  	setFlags(WCF_HAVE_WORK); -	mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority); +	mRequestHandle = mWorkerThread->addWorkRequest(this, param);  	mMutex.unlock();  } @@ -321,7 +322,6 @@ void LLWorkerClass::abortWork(bool autocomplete)  	if (mRequestHandle != LLWorkerThread::nullHandle())  	{  		mWorkerThread->abortRequest(mRequestHandle, autocomplete); -		mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE);  		setFlags(WCF_ABORT_REQUESTED);  	}  	mMutex.unlock(); @@ -395,16 +395,5 @@ void LLWorkerClass::scheduleDelete()  	}  } -void LLWorkerClass::setPriority(U32 priority) -{ -	mMutex.lock(); -	if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority) -	{ -		mRequestPriority = priority; -		mWorkerThread->setPriority(mRequestHandle, priority); -	} -	mMutex.unlock(); -} -  //============================================================================ diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 0387e75c65..06bbb7369e 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -56,7 +56,7 @@ public:  		virtual ~WorkRequest(); // use deleteRequest()  	public: -		WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param); +		WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param);  		S32 getParam()  		{ @@ -90,7 +90,7 @@ public:  	/*virtual*/ S32 update(F32 max_time_ms); -	handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); +	handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param);  	S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug @@ -151,10 +151,6 @@ public:  	bool isWorking() { return getFlags(WCF_WORKING); }  	bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); } -	// setPriority(): changes the priority of a request -	void setPriority(U32 priority); -	U32  getPriority() { return mRequestPriority; } -		  	const std::string& getName() const { return mWorkerClassName; }  protected: @@ -169,7 +165,7 @@ protected:  	void setWorkerThread(LLWorkerThread* workerthread);  	// addWork(): calls startWork, adds doWork() to queue -	void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL); +	void addWork(S32 param);  	// abortWork(): requests that work be aborted  	void abortWork(bool autocomplete); @@ -193,7 +189,6 @@ protected:  	LLWorkerThread* mWorkerThread;  	std::string mWorkerClassName;  	handle_t mRequestHandle; -	U32 mRequestPriority; // last priority set  private:  	LLMutex mMutex; diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ba914035e2..f49dd40a8b 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -17,14 +17,17 @@  // std headers  // external library headers  // other Linden headers +#include "commoncontrol.h"  #include "llerror.h"  #include "llevents.h" +#include "llsd.h"  #include "stringize.h"  LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): +    super(name),      mQueue(name, capacity),      mName("ThreadPool:" + name), -    mThreadCount(threads) +    mThreadCount(getConfiguredWidth(name, threads))  {}  void LL::ThreadPool::start() @@ -86,3 +89,58 @@ void LL::ThreadPool::run()  {      mQueue.runUntilClose();  } + +//static +size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft) +{ +    LLSD poolSizes; +    try +    { +        poolSizes = LL::CommonControl::get("Global", "ThreadPoolSizes"); +        // "ThreadPoolSizes" is actually a map containing the sizes of +        // interest -- or should be, if this process has an +        // LLViewerControlListener instance and its settings include +        // "ThreadPoolSizes". If we failed to retrieve it, perhaps we're in a +        // program that doesn't define that, or perhaps there's no such +        // setting, or perhaps we're asking too early, before the LLEventAPI +        // itself has been instantiated. In any of those cases, it seems worth +        // warning. +        if (! poolSizes.isDefined()) +        { +            // Note: we don't warn about absence of an override key for a +            // particular ThreadPool name, that's fine. This warning is about +            // complete absence of a ThreadPoolSizes setting, which we expect +            // in a normal viewer session. +            LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '" +                                   << name << "'" << LL_ENDL; +        } +    } +    catch (const LL::CommonControl::Error& exc) +    { +        // We don't want ThreadPool to *require* LLViewerControlListener. +        // Just log it and carry on. +        LL_WARNS("ThreadPool") << "Can't check 'ThreadPoolSizes': " << exc.what() << LL_ENDL; +    } + +    LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; +    // LLSD treats an undefined value as an empty map when asked to retrieve a +    // key, so we don't need this to be conditional. +    LLSD sizeSpec{ poolSizes[name] }; +    // We retrieve sizeSpec as LLSD, rather than immediately as LLSD::Integer, +    // so we can distinguish the case when it's undefined. +    return sizeSpec.isInteger() ? sizeSpec.asInteger() : dft; +} + +//static +size_t LL::ThreadPool::getWidth(const std::string& name, size_t dft) +{ +    auto instance{ getInstance(name) }; +    if (instance) +    { +        return instance->getWidth(); +    } +    else +    { +        return getConfiguredWidth(name, dft); +    } +} diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b79c9b9090..b49d511257 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -22,14 +22,25 @@  namespace LL  { -    class ThreadPool +    class ThreadPool: public LLInstanceTracker<ThreadPool, std::string>      { +    private: +        using super = LLInstanceTracker<ThreadPool, std::string>;      public:          /**           * Pass ThreadPool a string name. This can be used to look up the           * relevant WorkQueue. +         * +         * The number of threads you pass sets the compile-time default. But +         * if the user has overridden the LLSD map in the "ThreadPoolSizes" +         * setting with a key matching this ThreadPool name, that setting +         * overrides this parameter. +         * +         * Pass an explicit capacity to limit the size of the queue. +         * Constraining the queue can cause a submitter to block. Do not +         * constrain any ThreadPool accepting work from the main thread.           */ -        ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); +        ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024*1024);          virtual ~ThreadPool();          /** @@ -57,6 +68,25 @@ namespace LL           */          virtual void run(); +        /** +         * getConfiguredWidth() returns the setting, if any, for the specified +         * ThreadPool name. Returns dft if the "ThreadPoolSizes" map does not +         * contain the specified name. +         */ +        static +        size_t getConfiguredWidth(const std::string& name, size_t dft=0); + +        /** +         * This getWidth() returns the width of the instantiated ThreadPool +         * with the specified name, if any. If no instance exists, returns its +         * getConfiguredWidth() if any. If there's no instance and no relevant +         * override, return dft. Presumably dft should match the threads +         * parameter passed to the ThreadPool constructor call that will +         * eventually instantiate the ThreadPool with that name. +         */ +        static +        size_t getWidth(const std::string& name, size_t dft); +      private:          void run(const std::string& name); diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 96574a18b9..784327f929 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -162,9 +162,15 @@ namespace LL                         CALLABLE&& callable);          template <typename CALLABLE> +        bool tryPost(const TimePoint& time, CALLABLE&& callable) +        { +            return mQueue.tryPush(TimedWork(time, std::move(callable))); +        } + +        template <typename CALLABLE>          bool tryPost(CALLABLE&& callable)          { -            return mQueue.tryPush(TimedWork(TimePoint::clock::now(), std::move(callable))); +            return mQueue.tryPush(TimePoint::clock::now(), std::move(callable));          }          /*------------------------- handshake API --------------------------*/ diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index 975ce8a4d5..bd0ac740db 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -113,6 +113,7 @@ void HttpLibcurl::shutdown()  void HttpLibcurl::start(int policy_count)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT);  	llassert_always(! mMultiHandles);					// One-time call only @@ -143,6 +144,7 @@ void HttpLibcurl::start(int policy_count)  // sleep otherwise ask for a normal polling interval.  HttpService::ELoopSpeed HttpLibcurl::processTransport()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpService::ELoopSpeed	ret(HttpService::REQUEST_SLEEP);  	// Give libcurl some cycles to do I/O & callbacks @@ -168,6 +170,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()  		CURLMcode status(CURLM_CALL_MULTI_PERFORM);  		do  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_perform");  			running = 0;  			status = curl_multi_perform(mMultiHandles[policy_class], &running);  		} @@ -176,31 +179,34 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()  		// Run completion on anything done  		CURLMsg * msg(NULL);  		int msgs_in_queue(0); -		while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue))) -		{ -			if (CURLMSG_DONE == msg->msg) -			{ -				CURL * handle(msg->easy_handle); -				CURLcode result(msg->data.result); +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_info_read"); +            while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue))) +            { +                if (CURLMSG_DONE == msg->msg) +                { +                    CURL* handle(msg->easy_handle); +                    CURLcode result(msg->data.result); -				completeRequest(mMultiHandles[policy_class], handle, result); -				handle = NULL;					// No longer valid on return -				ret = HttpService::NORMAL;		// If anything completes, we may have a free slot. -												// Turning around quickly reduces connection gap by 7-10mS. -			} -			else if (CURLMSG_NONE == msg->msg) -			{ -				// Ignore this... it shouldn't mean anything. -				; -			} -			else -			{ -				LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl.  Msg code:  " -										<< msg->msg -										<< LL_ENDL; -			} -			msgs_in_queue = 0; -		} +                    completeRequest(mMultiHandles[policy_class], handle, result); +                    handle = NULL;					// No longer valid on return +                    ret = HttpService::NORMAL;		// If anything completes, we may have a free slot. +                                                    // Turning around quickly reduces connection gap by 7-10mS. +                } +                else if (CURLMSG_NONE == msg->msg) +                { +                    // Ignore this... it shouldn't mean anything. +                    ; +                } +                else +                { +                    LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl.  Msg code:  " +                        << msg->msg +                        << LL_ENDL; +                } +                msgs_in_queue = 0; +            } +        }  	}  	if (! mActiveOps.empty()) @@ -214,6 +220,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()  // Caller has provided us with a ref count on op.  void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	llassert_always(op->mReqPolicy < mPolicyCount);  	llassert_always(mMultiHandles[op->mReqPolicy] != NULL); @@ -257,6 +264,7 @@ void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)  // method to kill the request.  bool HttpLibcurl::cancel(HttpHandle handle)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op = HttpOpRequest::fromHandle<HttpOpRequest>(handle);  	active_set_t::iterator it(mActiveOps.find(op));  	if (mActiveOps.end() == it) @@ -282,6 +290,7 @@ bool HttpLibcurl::cancel(HttpHandle handle)  // op to the reply queue with refcount intact.  void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	// Deactivate request  	op->mCurlActive = false; @@ -308,6 +317,7 @@ void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)  // Keep them synchronized as necessary.  bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpHandle ophandle(NULL);      CURLcode ccode(CURLE_OK); @@ -445,6 +455,7 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const  void HttpLibcurl::policyUpdated(int policy_class)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles)  	{  		return; diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp index 3fc4e28910..3b64018132 100644 --- a/indra/llcorehttp/_httpoperation.cpp +++ b/indra/llcorehttp/_httpoperation.cpp @@ -62,7 +62,6 @@ HttpOperation::HttpOperation():      mReplyQueue(),      mUserHandler(),      mReqPolicy(HttpRequest::DEFAULT_POLICY_ID), -    mReqPriority(0U),      mTracing(HTTP_TRACE_OFF),      mMyHandle(LLCORE_HTTP_HANDLE_INVALID)  { diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h index 1a75921c09..8c1364bab4 100644 --- a/indra/llcorehttp/_httpoperation.h +++ b/indra/llcorehttp/_httpoperation.h @@ -181,7 +181,6 @@ protected:  public:  	// Request Data  	HttpRequest::policy_t		mReqPolicy; -	HttpRequest::priority_t		mReqPriority;  	// Reply Data  	HttpStatus					mStatus; diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index ba31290c24..d60eb6c95f 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -200,6 +200,7 @@ HttpOpRequest::~HttpOpRequest()  void HttpOpRequest::stageFromRequest(HttpService * service)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));      service->getPolicy().addOp(self);			// transfers refcount  } @@ -207,6 +208,7 @@ void HttpOpRequest::stageFromRequest(HttpService * service)  void HttpOpRequest::stageFromReady(HttpService * service)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));      service->getTransport().addOp(self);		// transfers refcount  } @@ -214,6 +216,7 @@ void HttpOpRequest::stageFromReady(HttpService * service)  void HttpOpRequest::stageFromActive(HttpService * service)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	if (mReplyLength)  	{  		// If non-zero, we received and processed a Content-Range @@ -250,6 +253,7 @@ void HttpOpRequest::stageFromActive(HttpService * service)  void HttpOpRequest::visitNotifier(HttpRequest * request)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	if (mUserHandler)  	{  		HttpResponse * response = new HttpResponse(); @@ -292,6 +296,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)  HttpStatus HttpOpRequest::cancel()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	mStatus = HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED);  	addAsReply(); @@ -301,12 +306,12 @@ HttpStatus HttpOpRequest::cancel()  HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id, -								   HttpRequest::priority_t priority,  								   const std::string & url,                                     const HttpOptions::ptr_t & options,  								   const HttpHeaders::ptr_t & headers)  { -	setupCommon(policy_id, priority, url, NULL, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +	setupCommon(policy_id, url, NULL, options, headers);  	mReqMethod = HOR_GET;  	return HttpStatus(); @@ -314,14 +319,14 @@ HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id, -											HttpRequest::priority_t priority,  											const std::string & url,  											size_t offset,  											size_t len,                                              const HttpOptions::ptr_t & options,                                              const HttpHeaders::ptr_t & headers)  { -	setupCommon(policy_id, priority, url, NULL, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +	setupCommon(policy_id, url, NULL, options, headers);  	mReqMethod = HOR_GET;  	mReqOffset = offset;  	mReqLength = len; @@ -335,13 +340,13 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id, -									HttpRequest::priority_t priority,  									const std::string & url,  									BufferArray * body,                                      const HttpOptions::ptr_t & options,                                      const HttpHeaders::ptr_t & headers)  { -	setupCommon(policy_id, priority, url, body, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +	setupCommon(policy_id, url, body, options, headers);  	mReqMethod = HOR_POST;  	return HttpStatus(); @@ -349,13 +354,13 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id, -								   HttpRequest::priority_t priority,  								   const std::string & url,  								   BufferArray * body,                                     const HttpOptions::ptr_t & options,  								   const HttpHeaders::ptr_t & headers)  { -	setupCommon(policy_id, priority, url, body, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +	setupCommon(policy_id, url, body, options, headers);  	mReqMethod = HOR_PUT;  	return HttpStatus(); @@ -363,12 +368,12 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t & headers)  { -    setupCommon(policy_id, priority, url, NULL, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +    setupCommon(policy_id, url, NULL, options, headers);      mReqMethod = HOR_DELETE;      return HttpStatus(); @@ -376,13 +381,13 @@ HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      BufferArray * body,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t & headers)  { -    setupCommon(policy_id, priority, url, body, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +    setupCommon(policy_id, url, body, options, headers);      mReqMethod = HOR_PATCH;      return HttpStatus(); @@ -390,12 +395,12 @@ HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t &headers)  { -    setupCommon(policy_id, priority, url, NULL, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +    setupCommon(policy_id, url, NULL, options, headers);      mReqMethod = HOR_COPY;      return HttpStatus(); @@ -403,12 +408,12 @@ HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,  HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t &headers)  { -    setupCommon(policy_id, priority, url, NULL, options, headers); +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; +    setupCommon(policy_id, url, NULL, options, headers);      mReqMethod = HOR_MOVE;      return HttpStatus(); @@ -416,15 +421,14 @@ HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,  void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, -								HttpRequest::priority_t priority,  								const std::string & url,  								BufferArray * body,                                  const HttpOptions::ptr_t & options,  								const HttpHeaders::ptr_t & headers)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	mProcFlags = 0U;  	mReqPolicy = policy_id; -	mReqPriority = priority;  	mReqURL = url;  	if (body)  	{ @@ -465,6 +469,7 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,  // *TODO:  Move this to _httplibcurl where it belongs.  HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	// Scrub transport and result data for retried op case  	mCurlActive = false;  	mCurlHandle = NULL; @@ -773,6 +778,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void * userdata)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));  	if (! op->mReplyBody) @@ -788,6 +794,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void  size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void * userdata)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));  	if (! op->mReqBody) @@ -819,6 +826,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void  int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));      if (!op->mReqBody) @@ -850,6 +858,7 @@ int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)  size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	static const char status_line[] = "HTTP/";  	static const size_t status_line_len = sizeof(status_line) - 1;  	static const char con_ran_line[] = "content-range"; @@ -999,6 +1008,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi  CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));      if (op->mCallbackSSLVerify) @@ -1025,6 +1035,7 @@ CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userd  int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(param));  	if (op->mCallbackSSLVerify) @@ -1037,6 +1048,7 @@ int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)  int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;      HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));  	std::string safe_line; diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index cdbe350785..ec84822cf4 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -105,13 +105,11 @@ public:  	/// Threading:  called by application thread  	///  	HttpStatus setupGet(HttpRequest::policy_t policy_id, -						HttpRequest::priority_t priority,  						const std::string & url,  						const HttpOptions::ptr_t & options,  						const HttpHeaders::ptr_t & headers);  	HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id, -								 HttpRequest::priority_t priority,  								 const std::string & url,  								 size_t offset,  								 size_t len, @@ -119,40 +117,34 @@ public:  								 const HttpHeaders::ptr_t & headers);  	HttpStatus setupPost(HttpRequest::policy_t policy_id, -						 HttpRequest::priority_t priority,  						 const std::string & url,  						 BufferArray * body,                           const HttpOptions::ptr_t & options,  						 const HttpHeaders::ptr_t & headers);  	HttpStatus setupPut(HttpRequest::policy_t policy_id, -						HttpRequest::priority_t priority,  						const std::string & url,  						BufferArray * body,                          const HttpOptions::ptr_t & options,  						const HttpHeaders::ptr_t & headers);      HttpStatus setupDelete(HttpRequest::policy_t policy_id, -                        HttpRequest::priority_t priority,                          const std::string & url,                          const HttpOptions::ptr_t & options,                          const HttpHeaders::ptr_t & headers);      HttpStatus setupPatch(HttpRequest::policy_t policy_id, -                        HttpRequest::priority_t priority,                          const std::string & url,                          BufferArray * body,                          const HttpOptions::ptr_t & options,                          const HttpHeaders::ptr_t & headers);      HttpStatus setupCopy(HttpRequest::policy_t policy_id, -                        HttpRequest::priority_t priority,                          const std::string & url,                          const HttpOptions::ptr_t & options,                          const HttpHeaders::ptr_t & headers);      HttpStatus setupMove(HttpRequest::policy_t policy_id, -                        HttpRequest::priority_t priority,                          const std::string & url,                          const HttpOptions::ptr_t & options,                          const HttpHeaders::ptr_t & headers); @@ -172,7 +164,6 @@ protected:  	// Threading:  called by application thread  	//  	void setupCommon(HttpRequest::policy_t policy_id, -					 HttpRequest::priority_t priority,  					 const std::string & url,  					 BufferArray * body,                       const HttpOptions::ptr_t & options, @@ -239,19 +230,6 @@ public: -/// HttpOpRequestCompare isn't an operation but a uniform comparison -/// functor for STL containers that order by priority.  Mainly -/// used for the ready queue container but defined here. -class HttpOpRequestCompare -{ -public: -	bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs) -		{ -			return lhs->mReqPriority > rhs->mReqPriority; -		} -};  // end class HttpOpRequestCompare - -  // ---------------------------------------  // Free functions  // --------------------------------------- diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp index d48c7a0b7d..b99b4e9e4a 100644 --- a/indra/llcorehttp/_httpopsetpriority.cpp +++ b/indra/llcorehttp/_httpopsetpriority.cpp @@ -24,6 +24,7 @@   * $/LicenseInfo$   */ +#if 0 // DEPRECATED  #include "_httpopsetpriority.h"  #include "httpresponse.h" @@ -61,3 +62,5 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service)  }   // end namespace LLCore + +#endif diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h index 43e2aa081b..fd543f37cc 100644 --- a/indra/llcorehttp/_httpopsetpriority.h +++ b/indra/llcorehttp/_httpopsetpriority.h @@ -27,7 +27,7 @@  #ifndef	_LLCORE_HTTP_SETPRIORITY_H_  #define	_LLCORE_HTTP_SETPRIORITY_H_ - +#if 0 // DEPRECATED  #include "httpcommon.h"  #include "httprequest.h"  #include "_httpoperation.h" @@ -49,7 +49,7 @@ namespace LLCore  class HttpOpSetPriority : public HttpOperation  {  public: -	HttpOpSetPriority(HttpHandle handle, HttpRequest::priority_t priority); +	HttpOpSetPriority(HttpHandle handle);  	virtual ~HttpOpSetPriority(); @@ -63,10 +63,10 @@ public:  protected:  	// Request Data  	HttpHandle					mHandle; -	HttpRequest::priority_t		mPriority;  }; // end class HttpOpSetPriority  }  // end namespace LLCore +#endif  #endif	// _LLCORE_HTTP_SETPRIORITY_H_ diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index 885f0ed61d..29f50c1693 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -330,37 +330,6 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()  	return result;  } - -bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t priority) -{ -	for (int policy_class(0); policy_class < mClasses.size(); ++policy_class) -	{ -		ClassState & state(*mClasses[policy_class]); -		// We don't scan retry queue because a priority change there -		// is meaningless.  The request will be issued based on retry -		// intervals not priority value, which is now moot. -		 -		// Scan ready queue for requests that match policy -		HttpReadyQueue::container_type & c(state.mReadyQueue.get_container()); -		for (HttpReadyQueue::container_type::iterator iter(c.begin()); c.end() != iter;) -		{ -			HttpReadyQueue::container_type::iterator cur(iter++); - -			if ((*cur)->getHandle() == handle) -			{ -				HttpOpRequest::ptr_t op(*cur); -				c.erase(cur);									// All iterators are now invalidated -				op->mReqPriority = priority; -				state.mReadyQueue.push(op);						// Re-insert using adapter class -				return true; -			} -		} -	} -	 -	return false; -} - -  bool HttpPolicy::cancel(HttpHandle handle)  {  	for (int policy_class(0); policy_class < mClasses.size(); ++policy_class) diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h index 3c4126e14b..0b8806a3e2 100644 --- a/indra/llcorehttp/_httppolicy.h +++ b/indra/llcorehttp/_httppolicy.h @@ -110,12 +110,6 @@ public:  	/// Threading:  called by worker thread      void retryOp(const opReqPtr_t &); -	/// Attempt to change the priority of an earlier request. -	/// Request that Shadows HttpService's method -	/// -	/// Threading:  called by worker thread -	bool changePriority(HttpHandle handle, HttpRequest::priority_t priority); -  	/// Attempt to cancel a previous request.  	/// Shadows HttpService's method as well  	/// diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 56f52f1b09..294acd7f63 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -80,6 +80,7 @@ HttpService::HttpService()  HttpService::~HttpService()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	mExitRequested = 1U;  	if (RUNNING == sState)  	{ @@ -131,6 +132,7 @@ HttpService::~HttpService()  void HttpService::init(HttpRequestQueue * queue)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	llassert_always(! sInstance);  	llassert_always(NOT_INITIALIZED == sState);  	sInstance = new HttpService(); @@ -145,6 +147,7 @@ void HttpService::init(HttpRequestQueue * queue)  void HttpService::term()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	if (sInstance)  	{  		if (RUNNING == sState && sInstance->mThread) @@ -196,6 +199,7 @@ bool HttpService::isStopped()  /// Threading:  callable by consumer thread *once*.  void HttpService::startThread()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	llassert_always(! mThread || STOPPED == sState);  	llassert_always(INITIALIZED == sState || STOPPED == sState); @@ -220,22 +224,6 @@ void HttpService::stopRequested()  } -/// Threading:  callable by worker thread. -bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t priority) -{ -	bool found(false); - -	// Skip the request queue as we currently don't leave earlier -	// requests sitting there.  Start with the ready queue... -	found = mPolicy->changePriority(handle, priority); - -	// If not there, we could try the transport/active queue but priority -	// doesn't really have much effect there so we don't waste cycles. -	 -	return found; -} - -  /// Try to find the given request handle on any of the request  /// queues and cancel the operation.  /// @@ -244,6 +232,7 @@ bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t prio  /// Threading:  callable by worker thread.  bool HttpService::cancel(HttpHandle handle)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	bool canceled(false);  	// Request can't be on request queue so skip that. @@ -264,6 +253,7 @@ bool HttpService::cancel(HttpHandle handle)  /// Threading:  callable by worker thread.  void HttpService::shutdown()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	// Disallow future enqueue of requests  	mRequestQueue->stopQueue(); @@ -293,6 +283,8 @@ void HttpService::shutdown()  // requested to stop.  void HttpService::threadRun(LLCoreInt::HttpThread * thread)  { +    LL_PROFILER_SET_THREAD_NAME("HttpService"); +  	boost::this_thread::disable_interruption di;  	LLThread::registerThreadID(); @@ -300,6 +292,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)  	ELoopSpeed loop(REQUEST_SLEEP);  	while (! mExitRequested)  	{ +        LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;          try          {  		    loop = processRequestQueue(loop); @@ -344,6 +337,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)  HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpRequestQueue::OpContainer ops;  	const bool wait_for_req(REQUEST_SLEEP == loop); @@ -384,6 +378,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)  HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  										long * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range  		|| opt >= HttpRequest::PO_LAST													// ditto  		|| (! sOptionDesc[opt].mIsLong)													// datatype is long @@ -416,6 +411,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ  HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  										std::string * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range @@ -443,6 +439,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ  HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  	HttpRequest::policyCallback_t * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range @@ -472,6 +469,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ  HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  										long value, long * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range @@ -517,6 +515,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ  HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  										const std::string & value, std::string * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range @@ -548,6 +547,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ  HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,  	HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);  	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index d0c37ac195..551a718f20 100644 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -147,15 +147,6 @@ public:  	void shutdown();  	/// Try to find the given request handle on any of the request -	/// queues and reset the priority (and queue position) of the -	/// request if found. -	/// -	/// @return			True if the request was found somewhere. -	/// -	/// Threading:  callable by worker thread. -	bool changePriority(HttpHandle handle, HttpRequest::priority_t priority); -	 -	/// Try to find the given request handle on any of the request  	/// queues and cancel the operation.  	///  	/// @return			True if the request was found and canceled. diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp index c7376042b3..cc53b20add 100644 --- a/indra/llcorehttp/examples/http_texture_load.cpp +++ b/indra/llcorehttp/examples/http_texture_load.cpp @@ -469,11 +469,11 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & o  		LLCore::HttpHandle handle;  		if (offset || length)  		{ -			handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); +			handle = hr->requestGetByteRange(0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));  		}  		else  		{ -            handle = hr->requestGet(0, 0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); +            handle = hr->requestGet(0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));  		}  		if (! handle)  		{ diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 2687f77217..de3854a101 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -32,7 +32,6 @@  #include "_httppolicy.h"  #include "_httpoperation.h"  #include "_httpoprequest.h" -#include "_httpopsetpriority.h"  #include "_httpopcancel.h"  #include "_httpopsetget.h" @@ -183,16 +182,16 @@ HttpStatus HttpRequest::getStatus() const  HttpHandle HttpRequest::requestGet(policy_t policy_id, -								   priority_t priority,  								   const std::string & url,                                     const HttpOptions::ptr_t & options,  								   const HttpHeaders::ptr_t & headers,  								   HttpHandler::ptr_t user_handler)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status;  	HttpOpRequest::ptr_t op(new HttpOpRequest()); -	if (! (status = op->setupGet(policy_id, priority, url, options, headers))) +	if (! (status = op->setupGet(policy_id, url, options, headers)))  	{  		mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -210,7 +209,6 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id,  HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id, -											priority_t priority,  											const std::string & url,  											size_t offset,  											size_t len, @@ -218,10 +216,11 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,  											const HttpHeaders::ptr_t & headers,  											HttpHandler::ptr_t user_handler)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;  	HttpStatus status;  	HttpOpRequest::ptr_t op(new HttpOpRequest()); -	if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers))) +	if (! (status = op->setupGetByteRange(policy_id, url, offset, len, options, headers)))  	{  		mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -239,7 +238,6 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,  HttpHandle HttpRequest::requestPost(policy_t policy_id, -									priority_t priority,  									const std::string & url,  									BufferArray * body,                                      const HttpOptions::ptr_t & options, @@ -249,7 +247,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,  	HttpStatus status;  	HttpOpRequest::ptr_t op(new HttpOpRequest()); -	if (! (status = op->setupPost(policy_id, priority, url, body, options, headers))) +	if (! (status = op->setupPost(policy_id, url, body, options, headers)))  	{  		mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -267,7 +265,6 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,  HttpHandle HttpRequest::requestPut(policy_t policy_id, -								   priority_t priority,  								   const std::string & url,  								   BufferArray * body,                                     const HttpOptions::ptr_t & options, @@ -277,7 +274,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,  	HttpStatus status;  	HttpOpRequest::ptr_t op (new HttpOpRequest()); -	if (! (status = op->setupPut(policy_id, priority, url, body, options, headers))) +	if (! (status = op->setupPut(policy_id, url, body, options, headers)))  	{  		mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -294,7 +291,6 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,  }  HttpHandle HttpRequest::requestDelete(policy_t policy_id, -    priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t & headers, @@ -303,7 +299,7 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,      HttpStatus status;      HttpOpRequest::ptr_t op(new HttpOpRequest()); -    if (!(status = op->setupDelete(policy_id, priority, url, options, headers))) +    if (!(status = op->setupDelete(policy_id, url, options, headers)))      {          mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -320,7 +316,6 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id,  }  HttpHandle HttpRequest::requestPatch(policy_t policy_id, -    priority_t priority,      const std::string & url,      BufferArray * body,      const HttpOptions::ptr_t & options, @@ -330,7 +325,7 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,      HttpStatus status;      HttpOpRequest::ptr_t op (new HttpOpRequest()); -    if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers))) +    if (!(status = op->setupPatch(policy_id, url, body, options, headers)))      {          mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -347,7 +342,6 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id,  }  HttpHandle HttpRequest::requestCopy(policy_t policy_id, -    priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t & headers, @@ -356,7 +350,7 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,      HttpStatus status;      HttpOpRequest::ptr_t op(new HttpOpRequest()); -    if (!(status = op->setupCopy(policy_id, priority, url, options, headers))) +    if (!(status = op->setupCopy(policy_id, url, options, headers)))      {          mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -374,7 +368,6 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id,  }  HttpHandle HttpRequest::requestMove(policy_t policy_id, -    priority_t priority,      const std::string & url,      const HttpOptions::ptr_t & options,      const HttpHeaders::ptr_t & headers, @@ -383,7 +376,7 @@ HttpHandle HttpRequest::requestMove(policy_t policy_id,      HttpStatus status;      HttpOpRequest::ptr_t op (new HttpOpRequest()); -    if (!(status = op->setupMove(policy_id, priority, url, options, headers))) +    if (!(status = op->setupMove(policy_id, url, options, headers)))      {          mLastReqStatus = status;          return LLCORE_HTTP_HANDLE_INVALID; @@ -483,24 +476,6 @@ HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler::ptr_t use  } -HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority, -										   HttpHandler::ptr_t handler) -{ -	HttpStatus status; - -	HttpOperation::ptr_t op (new HttpOpSetPriority(request, priority)); -	op->setReplyPath(mReplyQueue, handler); -	if (! (status = mRequestQueue->addOp(op)))			// transfers refcount -	{ -		mLastReqStatus = status; -        return LLCORE_HTTP_HANDLE_INVALID; -	} - -	mLastReqStatus = status; -	return op->getHandle(); -} - -  // ====================================  // Utility Methods  // ==================================== diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index a418eb6a7a..ca4b9e92bc 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -95,7 +95,6 @@ private:  public:  	typedef unsigned int policy_t; -	typedef unsigned int priority_t;  	typedef boost::shared_ptr<HttpRequest> ptr_t;      typedef boost::weak_ptr<HttpRequest>   wptr_t; @@ -316,8 +315,6 @@ public:  	///  	/// @param	policy_id		Default or user-defined policy class under  	///							which this request is to be serviced. -	/// @param	priority		Standard priority scheme inherited from -	///							Indra code base (U32-type scheme).  	/// @param	url				URL with any encoded query parameters to  	///							be accessed.  	/// @param	options			Optional instance of an HttpOptions object @@ -346,7 +343,6 @@ public:  	///							case, @see getStatus() will return more info.  	///  	HttpHandle requestGet(policy_t policy_id, -						  priority_t priority,  						  const std::string & url,                            const HttpOptions::ptr_t & options,  						  const HttpHeaders::ptr_t & headers, @@ -377,7 +373,6 @@ public:  	/// - Referer:  	///  	/// @param	policy_id		@see requestGet() -	/// @param	priority		"  	/// @param	url				"  	/// @param	offset			Offset of first byte into resource to be returned.  	/// @param	len				Count of bytes to be returned @@ -387,7 +382,6 @@ public:  	/// @return					"  	///  	HttpHandle requestGetByteRange(policy_t policy_id, -								   priority_t priority,  								   const std::string & url,  								   size_t offset,  								   size_t len, @@ -418,7 +412,6 @@ public:  	/// - Expect:  	///  	/// @param	policy_id		@see requestGet() -	/// @param	priority		"  	/// @param	url				"  	/// @param	body			Byte stream to be sent as the body.  No  	///							further encoding or escaping will be done @@ -429,7 +422,6 @@ public:  	/// @return					"  	///  	HttpHandle requestPost(policy_t policy_id, -						   priority_t priority,  						   const std::string & url,  						   BufferArray * body,                             const HttpOptions::ptr_t & options, @@ -459,7 +451,6 @@ public:  	/// - Content-Type:  	///  	/// @param	policy_id		@see requestGet() -	/// @param	priority		"  	/// @param	url				"  	/// @param	body			Byte stream to be sent as the body.  No  	///							further encoding or escaping will be done @@ -470,7 +461,6 @@ public:  	/// @return					"  	///  	HttpHandle requestPut(policy_t policy_id, -						  priority_t priority,  						  const std::string & url,  						  BufferArray * body,                            const HttpOptions::ptr_t & options, @@ -483,7 +473,6 @@ public:      /// encoding and communicating the content types.      ///      /// @param	policy_id		@see requestGet() -    /// @param	priority		"      /// @param	url				"      /// @param	options			@see requestGet()K(optional)      /// @param	headers			" @@ -491,7 +480,6 @@ public:      /// @return					"      ///      HttpHandle requestDelete(policy_t policy_id, -            priority_t priority,              const std::string & url,              const HttpOptions::ptr_t & options,              const HttpHeaders::ptr_t & headers, @@ -502,7 +490,6 @@ public:      /// encoding and communicating the content types.      ///      /// @param	policy_id		@see requestGet() -    /// @param	priority		"      /// @param	url				"      /// @param	body			Byte stream to be sent as the body.  No      ///							further encoding or escaping will be done @@ -513,7 +500,6 @@ public:      /// @return					"      ///      HttpHandle requestPatch(policy_t policy_id, -            priority_t priority,              const std::string & url,              BufferArray * body,              const HttpOptions::ptr_t & options, @@ -525,7 +511,6 @@ public:      /// encoding and communicating the content types.      ///      /// @param	policy_id		@see requestGet() -    /// @param	priority		"      /// @param	url				"      /// @param	options			@see requestGet()K(optional)      /// @param	headers			" @@ -533,7 +518,6 @@ public:      /// @return					"      ///      HttpHandle requestCopy(policy_t policy_id, -            priority_t priority,              const std::string & url,              const HttpOptions::ptr_t & options,              const HttpHeaders::ptr_t & headers, @@ -544,7 +528,6 @@ public:      /// encoding and communicating the content types.      ///      /// @param	policy_id		@see requestGet() -    /// @param	priority		"      /// @param	url				"      /// @param	options			@see requestGet()K(optional)      /// @param	headers			" @@ -552,7 +535,6 @@ public:      /// @return					"      ///      HttpHandle requestMove(policy_t policy_id, -            priority_t priority,              const std::string & url,              const HttpOptions::ptr_t & options,              const HttpHeaders::ptr_t & headers, @@ -593,18 +575,6 @@ public:  	HttpHandle requestCancel(HttpHandle request, HttpHandler::ptr_t); -	/// Request that a previously-issued request be reprioritized. -	/// The status of whether the change itself succeeded arrives -	/// via notification.   -	/// -	/// @param	request			Handle of previously-issued request to -	///							be changed. -	/// @param	priority		New priority value. -	/// @param	handler			@see requestGet() -	/// @return					" -	/// -	HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler::ptr_t handler); -  	/// @}  	/// @name UtilityMethods diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 154f6b12e9..3eaac10aeb 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -614,7 +614,6 @@ void HttpRequestTestObjectType::test<7>()  		// Issue a GET that can't connect  		mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -													 0U,  													 "http://127.0.0.1:2/nothing/here",  													 0,  													 0, @@ -716,7 +715,6 @@ void HttpRequestTestObjectType::test<8>()  		// Issue a GET that *can* connect  		mStatus = HttpStatus(200);  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base,  											HttpOptions::ptr_t(),                                              HttpHeaders::ptr_t(), @@ -812,7 +810,6 @@ void HttpRequestTestObjectType::test<9>()  		// Issue a GET that *can* connect  		mStatus = HttpStatus(200);  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -													 0U,  													 url_base,  													 0,  													 0, @@ -913,7 +910,6 @@ void HttpRequestTestObjectType::test<10>()  		body->append(body_text, strlen(body_text));  		mStatus = HttpStatus(200);  		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base,  											body,                                              HttpOptions::ptr_t(), @@ -1020,7 +1016,6 @@ void HttpRequestTestObjectType::test<11>()  		body->append(body_text, strlen(body_text));  		mStatus = HttpStatus(200);  		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, -											 0U,  											 url_base,  											 body,                                               HttpOptions::ptr_t(), @@ -1127,7 +1122,6 @@ void HttpRequestTestObjectType::test<12>()  		// Issue a GET that *can* connect  		mStatus = HttpStatus(200);  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -													 0U,  													 url_base,  													 0,  													 0, @@ -1240,7 +1234,6 @@ void HttpRequestTestObjectType::test<13>()  			regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),  										  boost::regex(".*", boost::regex::icase)));  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -													 0U,  													 url_base,  													 0,	  												 0, @@ -1346,7 +1339,6 @@ void HttpRequestTestObjectType::test<14>()  		// Issue a GET that sleeps  		mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -													 0U,  													 url_base,  													 0,  													 0, @@ -1454,7 +1446,6 @@ void HttpRequestTestObjectType::test<15>()  		mStatus = HttpStatus(200);  		handler.mCheckContentType = "application/llsd+xml";  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base,                                              HttpOptions::ptr_t(),                                              HttpHeaders::ptr_t(), @@ -1609,7 +1600,6 @@ void HttpRequestTestObjectType::test<16>()  				boost::regex("X-Reflect-content-encoding", boost::regex::icase),  				boost::regex(".*", boost::regex::icase)));  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base + "reflect/",  											options,  											HttpHeaders::ptr_t(), @@ -1684,7 +1674,6 @@ void HttpRequestTestObjectType::test<16>()  				boost::regex("X-Reflect-content-encoding", boost::regex::icase),  				boost::regex(".*", boost::regex::icase)));  		handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -										  0U,  										  url_base + "reflect/",  										  0,  										  47, @@ -1863,7 +1852,6 @@ void HttpRequestTestObjectType::test<17>()  				boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),  				boost::regex(".*chunked.*", boost::regex::icase)));  		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, -											 0U,  											 url_base + "reflect/",  											 ba,  											 options, @@ -2049,7 +2037,6 @@ void HttpRequestTestObjectType::test<18>()  				boost::regex(".*", boost::regex::icase)));  		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base + "reflect/",  											ba,  											options, @@ -2249,7 +2236,6 @@ void HttpRequestTestObjectType::test<19>()  				boost::regex("X-Reflect-content-encoding", boost::regex::icase),  				boost::regex(".*", boost::regex::icase)));  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base + "reflect/",  											options,  											headers, @@ -2457,7 +2443,6 @@ void HttpRequestTestObjectType::test<20>()  				boost::regex(".*", boost::regex::icase)));  		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, -											 0U,  											 url_base + "reflect/",  											 ba,  											 options, @@ -2666,7 +2651,6 @@ void HttpRequestTestObjectType::test<21>()  				boost::regex("X-Reflect-content-type", boost::regex::icase),  				boost::regex("text/html", boost::regex::icase)));  		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, -											0U,  											url_base + "reflect/",  											ba,  											options, @@ -2797,7 +2781,6 @@ void HttpRequestTestObjectType::test<22>()  			char buffer[128];  			sprintf(buffer, "/bug2295/%d/", i);  			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -														 0U,  														 url_base + buffer,  														 0,  														 25, @@ -2829,7 +2812,6 @@ void HttpRequestTestObjectType::test<22>()  			char buffer[128];  			sprintf(buffer, "/bug2295/00000012/%d/", i);  			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -														 0U,  														 url_base + buffer,  														 0,  														 25, @@ -2861,7 +2843,6 @@ void HttpRequestTestObjectType::test<22>()  			char buffer[128];  			sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);  			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -														 0U,  														 url_base + buffer,  														 0,  														 25, @@ -2984,7 +2965,6 @@ void HttpRequestTestObjectType::test<23>()  			std::ostringstream url;  			url << url_base << i << "/";  			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, -														 0U,  														 url.str(),  														 0,  														 0, diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 0d8fb4863b..bb603d3d7f 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -418,7 +418,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg  		updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));          LL_INFOS("CRASHREPORT") << "POST crash data to " << host << LL_ENDL; -        LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0, +        LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID,              host, data, httpOpts, LLCore::HttpHeaders::ptr_t(), LLCore::HttpHandler::ptr_t(new LLCrashLoggerHandler));          if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp index be8e83a56f..dbb69cd605 100644 --- a/indra/llfilesystem/lllfsthread.cpp +++ b/indra/llfilesystem/lllfsthread.cpp @@ -45,8 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded)  //static  S32 LLLFSThread::updateClass(U32 ms_elapsed)  { -	sLocal->update((F32)ms_elapsed); -	return sLocal->getPending(); +	return sLocal->update((F32)ms_elapsed);  }  //static @@ -58,6 +57,7 @@ void LLLFSThread::cleanupClass()  	{  		sLocal->update(0);  	} +    sLocal->shutdown();  	delete sLocal;  	sLocal = NULL;  } @@ -65,8 +65,7 @@ void LLLFSThread::cleanupClass()  //----------------------------------------------------------------------------  LLLFSThread::LLLFSThread(bool threaded) : -	LLQueuedThread("LFS", threaded), -	mPriorityCounter(PRIORITY_LOWBITS) +	LLQueuedThread("LFS", threaded)  {  	if(!mLocalAPRFilePoolp)  	{ @@ -84,14 +83,12 @@ LLLFSThread::~LLLFSThread()  LLLFSThread::handle_t LLLFSThread::read(const std::string& filename,	/* Flawfinder: ignore */   										U8* buffer, S32 offset, S32 numbytes, -										Responder* responder, U32 priority) +										Responder* responder)  { +    LL_PROFILE_ZONE_SCOPED;  	handle_t handle = generateHandle(); -	if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter(); -	else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW - -	Request* req = new Request(this, handle, priority, +	Request* req = new Request(this, handle,  							   FILE_READ, filename,  							   buffer, offset, numbytes,  							   responder); @@ -107,13 +104,12 @@ LLLFSThread::handle_t LLLFSThread::read(const std::string& filename,	/* Flawfind  LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,  										 U8* buffer, S32 offset, S32 numbytes, -										 Responder* responder, U32 priority) +										 Responder* responder)  { +    LL_PROFILE_ZONE_SCOPED;  	handle_t handle = generateHandle(); -	if (priority == 0) priority = PRIORITY_LOW | priorityCounter(); -	 -	Request* req = new Request(this, handle, priority, +	Request* req = new Request(this, handle,  							   FILE_WRITE, filename,  							   buffer, offset, numbytes,  							   responder); @@ -130,11 +126,11 @@ LLLFSThread::handle_t LLLFSThread::write(const std::string& filename,  //============================================================================  LLLFSThread::Request::Request(LLLFSThread* thread, -							  handle_t handle, U32 priority, +							  handle_t handle,  							  operation_t op, const std::string& filename,  							  U8* buffer, S32 offset, S32 numbytes,  							  Responder* responder) : -	QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), +	QueuedRequest(handle, FLAG_AUTO_COMPLETE),  	mThread(thread),  	mOperation(op),  	mFileName(filename), @@ -157,6 +153,7 @@ LLLFSThread::Request::~Request()  // virtual, called from own thread  void LLLFSThread::Request::finishRequest(bool completed)  { +    LL_PROFILE_ZONE_SCOPED;  	if (mResponder.notNull())  	{  		mResponder->completed(completed ? mBytesRead : 0); @@ -166,6 +163,7 @@ void LLLFSThread::Request::finishRequest(bool completed)  void LLLFSThread::Request::deleteRequest()  { +    LL_PROFILE_ZONE_SCOPED;  	if (getStatus() == STATUS_QUEUED)  	{  		LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; @@ -180,6 +178,7 @@ void LLLFSThread::Request::deleteRequest()  bool LLLFSThread::Request::processRequest()  { +    LL_PROFILE_ZONE_SCOPED;  	bool complete = false;  	if (mOperation ==  FILE_READ)  	{ diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h index 58f658f7ba..f2693a1172 100644 --- a/indra/llfilesystem/lllfsthread.h +++ b/indra/llfilesystem/lllfsthread.h @@ -68,7 +68,7 @@ public:  	public:  		Request(LLLFSThread* thread, -				handle_t handle, U32 priority,  +				handle_t handle,  				operation_t op, const std::string& filename,  				U8* buffer, S32 offset, S32 numbytes,  				Responder* responder); @@ -120,22 +120,15 @@ public:  	// Return a Request handle  	handle_t read(const std::string& filename,	/* Flawfinder: ignore */   				  U8* buffer, S32 offset, S32 numbytes, -				  Responder* responder, U32 pri=0); +				  Responder* responder);  	handle_t write(const std::string& filename,  				   U8* buffer, S32 offset, S32 numbytes, -				   Responder* responder, U32 pri=0); -	 -	// Misc -	U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations +				   Responder* responder);  	// static initializers  	static void initClass(bool local_is_threaded = TRUE); // Setup sLocal  	static S32 updateClass(U32 ms_elapsed);  	static void cleanupClass();		// Delete sLocal - -	 -private: -	U32 mPriorityCounter;  public:  	static LLLFSThread* sLocal;		// Default local file thread diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ad7124b5aa..186b01d60c 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -798,7 +798,6 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si  // LLImageRaw  //--------------------------------------------------------------------------- -S32 LLImageRaw::sGlobalRawMemory = 0;  S32 LLImageRaw::sRawImageCount = 0;  LLImageRaw::LLImageRaw() @@ -856,16 +855,13 @@ LLImageRaw::~LLImageRaw()  U8* LLImageRaw::allocateData(S32 size)  {  	U8* res = LLImageBase::allocateData(size); -	sGlobalRawMemory += getDataSize();  	return res;  }  // virtual  U8* LLImageRaw::reallocateData(S32 size)  { -	sGlobalRawMemory -= getDataSize();  	U8* res = LLImageBase::reallocateData(size); -	sGlobalRawMemory += getDataSize();  	return res;  } @@ -878,7 +874,6 @@ void LLImageRaw::releaseData()  // virtual  void LLImageRaw::deleteData()  { -	sGlobalRawMemory -= getDataSize();  	LLImageBase::deleteData();  } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 59c192d9f8..9e50fd502b 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -276,7 +276,6 @@ protected:  	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;  public: -	static S32 sGlobalRawMemory;  	static S32 sRawImageCount;  private: diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index e1809dbe59..8dba1641a6 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -146,6 +146,7 @@ bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precinct  bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	return decodeChannels(raw_imagep, decode_time, 0, 4);  } @@ -153,6 +154,7 @@ bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)  // Returns true to mean done, whether successful or not.  bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	LLTimer elapsed;  	bool res = true; diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 0dbb744bcf..0093958e6d 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -28,64 +28,88 @@  #include "llimageworker.h"  #include "llimagedxt.h" +#include "threadpool.h" + +/*--------------------------------------------------------------------------*/ +class ImageRequest +{ +public: +	ImageRequest(const LLPointer<LLImageFormatted>& image, +				 S32 discard, BOOL needs_aux, +				 const LLPointer<LLImageDecodeThread::Responder>& responder); +	virtual ~ImageRequest(); + +	/*virtual*/ bool processRequest(); +	/*virtual*/ void finishRequest(bool completed); + +private: +	// LLPointers stored in ImageRequest MUST be LLPointer instances rather +	// than references: we need to increment the refcount when storing these. +	// input +	LLPointer<LLImageFormatted> mFormattedImage; +	S32 mDiscardLevel; +	BOOL mNeedsAux; +	// output +	LLPointer<LLImageRaw> mDecodedImageRaw; +	LLPointer<LLImageRaw> mDecodedImageAux; +	BOOL mDecodedRaw; +	BOOL mDecodedAux; +	LLPointer<LLImageDecodeThread::Responder> mResponder; +}; +  //----------------------------------------------------------------------------  // MAIN THREAD -LLImageDecodeThread::LLImageDecodeThread(bool threaded) -	: LLQueuedThread("imagedecode", threaded) +LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/)  { -	mCreationMutex = new LLMutex(); +    mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8)); +    mThreadPool->start();  }  //virtual   LLImageDecodeThread::~LLImageDecodeThread() -{ -	delete mCreationMutex ; -} +{}  // MAIN THREAD  // virtual  S32 LLImageDecodeThread::update(F32 max_time_ms)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	LLMutexLock lock(mCreationMutex); -	for (creation_list_t::iterator iter = mCreationList.begin(); -		 iter != mCreationList.end(); ++iter) -	{ -		creation_info& info = *iter; -		ImageRequest* req = new ImageRequest(info.handle, info.image, -						     info.priority, info.discard, info.needs_aux, -						     info.responder); +    return getPending(); +} -		bool res = addRequest(req); -		if (!res) -		{ -			LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL; -		} -	} -	mCreationList.clear(); -	S32 res = LLQueuedThread::update(max_time_ms); -	return res; +S32 LLImageDecodeThread::getPending() +{ +    return mThreadPool->getQueue().size();  } -LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,  -	U32 priority, S32 discard, BOOL needs_aux, Responder* responder) +LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( +    const LLPointer<LLImageFormatted>& image,  +    S32 discard, +    BOOL needs_aux, +    const LLPointer<LLImageDecodeThread::Responder>& responder)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	LLMutexLock lock(mCreationMutex); -	handle_t handle = generateHandle(); -	mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); -	return handle; + +    // Instantiate the ImageRequest right in the lambda, why not? +    mThreadPool->getQueue().post( +        [req = ImageRequest(image, discard, needs_aux, responder)] +        () mutable +        { +            auto done = req.processRequest(); +            req.finishRequest(done); +        }); + +    // It's important to our consumer (LLTextureFetchWorker) that we return a +    // nonzero handle. It is NOT important that the nonzero handle be unique: +    // nothing is ever done with it except to compare it to zero, or zero it. +    return 17;  } -// Used by unit test only -// Returns the size of the mutex guarded list as an indication of sanity -S32 LLImageDecodeThread::tut_size() +void LLImageDecodeThread::shutdown()  { -	LLMutexLock lock(mCreationMutex); -	S32 res = mCreationList.size(); -	return res; +    mThreadPool->close();  }  LLImageDecodeThread::Responder::~Responder() @@ -94,11 +118,10 @@ LLImageDecodeThread::Responder::~Responder()  //---------------------------------------------------------------------------- -LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,  -												U32 priority, S32 discard, BOOL needs_aux, -												LLImageDecodeThread::Responder* responder) -	: LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), -	  mFormattedImage(image), +ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image,  +							S32 discard, BOOL needs_aux, +							const LLPointer<LLImageDecodeThread::Responder>& responder) +	: mFormattedImage(image),  	  mDiscardLevel(discard),  	  mNeedsAux(needs_aux),  	  mDecodedRaw(FALSE), @@ -107,7 +130,7 @@ LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatte  {  } -LLImageDecodeThread::ImageRequest::~ImageRequest() +ImageRequest::~ImageRequest()  {  	mDecodedImageRaw = NULL;  	mDecodedImageAux = NULL; @@ -118,10 +141,10 @@ LLImageDecodeThread::ImageRequest::~ImageRequest()  // Returns true when done, whether or not decode was successful. -bool LLImageDecodeThread::ImageRequest::processRequest() +bool ImageRequest::processRequest()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	const F32 decode_time_slice = .1f; +	const F32 decode_time_slice = 0.f; //disable time slicing  	bool done = true;  	if (!mDecodedRaw && mFormattedImage.notNull())  	{ @@ -145,7 +168,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest()  											  mFormattedImage->getHeight(),  											  mFormattedImage->getComponents());  		} -		done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms +		done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice);  		// some decoders are removing data when task is complete and there were errors  		mDecodedRaw = done && mDecodedImageRaw->getData();  	} @@ -158,14 +181,14 @@ bool LLImageDecodeThread::ImageRequest::processRequest()  											  mFormattedImage->getHeight(),  											  1);  		} -		done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms +		done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4);  		mDecodedAux = done && mDecodedImageAux->getData();  	}  	return done;  } -void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) +void ImageRequest::finishRequest(bool completed)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if (mResponder.notNull()) @@ -175,10 +198,3 @@ void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)  	}  	// Will automatically be deleted  } - -// Used by unit test only -// Checks that a responder exists for this instance so that something can happen when completion is reached -bool LLImageDecodeThread::ImageRequest::tut_isOK() -{ -	return mResponder.notNull(); -} diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 1bfb0ddfd3..18398d9ae2 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -29,9 +29,13 @@  #include "llimage.h"  #include "llpointer.h" -#include "llworkerthread.h" -class LLImageDecodeThread : public LLQueuedThread +namespace LL +{ +    class ThreadPool; +} // namespace LL + +class LLImageDecodeThread  {  public:  	class Responder : public LLThreadSafeRefCount @@ -42,63 +46,24 @@ public:  		virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0;  	}; -	class ImageRequest : public LLQueuedThread::QueuedRequest -	{ -	protected: -		virtual ~ImageRequest(); // use deleteRequest() -		 -	public: -		ImageRequest(handle_t handle, LLImageFormatted* image, -					 U32 priority, S32 discard, BOOL needs_aux, -					 LLImageDecodeThread::Responder* responder); - -		/*virtual*/ bool processRequest(); -		/*virtual*/ void finishRequest(bool completed); - -		// Used by unit tests to check the consitency of the request instance -		bool tut_isOK(); -		 -	private: -		// input -		LLPointer<LLImageFormatted> mFormattedImage; -		S32 mDiscardLevel; -		BOOL mNeedsAux; -		// output -		LLPointer<LLImageRaw> mDecodedImageRaw; -		LLPointer<LLImageRaw> mDecodedImageAux; -		BOOL mDecodedRaw; -		BOOL mDecodedAux; -		LLPointer<LLImageDecodeThread::Responder> mResponder; -	}; -	  public:  	LLImageDecodeThread(bool threaded = true);  	virtual ~LLImageDecodeThread(); -	handle_t decodeImage(LLImageFormatted* image, -						 U32 priority, S32 discard, BOOL needs_aux, -						 Responder* responder); +	// meant to resemble LLQueuedThread::handle_t +	typedef U32 handle_t; +	handle_t decodeImage(const LLPointer<LLImageFormatted>& image, +						 S32 discard, BOOL needs_aux, +						 const LLPointer<Responder>& responder); +	S32 getPending();  	S32 update(F32 max_time_ms); +	void shutdown(); -	// Used by unit tests to check the consistency of the thread instance -	S32 tut_size(); -	  private: -	struct creation_info -	{ -		handle_t handle; -		LLPointer<LLImageFormatted> image; -		U32 priority; -		S32 discard; -		BOOL needs_aux; -		LLPointer<Responder> responder; -		creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r) -			: handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r) -		{} -	}; -	typedef std::list<creation_info> creation_list_t; -	creation_list_t mCreationList; -	LLMutex* mCreationMutex; +	// As of SL-17483, LLImageDecodeThread is no longer itself an +	// LLQueuedThread - instead this is the API by which we submit work to the +	// "ImageDecode" ThreadPool. +	std::unique_ptr<LL::ThreadPool> mThreadPool;  };  #endif diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 9011ac615c..0a97b739b0 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -125,42 +125,11 @@ namespace tut  		}  	}; -	// Test wrapper declaration : image worker -	// Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance -	// but it's not a bad idea to get its public API a good shake as part of a thorough unit test set. -	// Some gotcha with the destructor though (see below). -	struct imagerequest_test -	{ -		// Instance to be tested -		LLImageDecodeThread::ImageRequest* mRequest; -		bool done; - -		// Constructor and destructor of the test wrapper -		imagerequest_test() -		{ -			done = false; - -			mRequest = new LLImageDecodeThread::ImageRequest(0, 0, -											 LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, -											 new responder_test(&done)); -		} -		~imagerequest_test() -		{ -			// We should delete the object *but*, because its destructor is protected, that cannot be -			// done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine... -			//delete mRequest; -		} -	}; -  	// Tut templating thingamagic: test group, object and test instance  	typedef test_group<imagedecodethread_test> imagedecodethread_t;  	typedef imagedecodethread_t::object imagedecodethread_object_t;  	tut::imagedecodethread_t tut_imagedecodethread("LLImageDecodeThread"); -	typedef test_group<imagerequest_test> imagerequest_t; -	typedef imagerequest_t::object imagerequest_object_t; -	tut::imagerequest_t tut_imagerequest("LLImageRequest"); -  	// ---------------------------------------------------------------------------------------  	// Test functions  	// Notes: @@ -172,64 +141,18 @@ namespace tut  	// ---------------------------------------------------------------------------------------  	// Test the LLImageDecodeThread interface  	// --------------------------------------------------------------------------------------- -	// -	// Note on Unit Testing Queued Thread Classes -	// -	// Since methods on such a class are called on a separate loop and that we can't insert tut -	// ensure() calls in there, we exercise the class with 2 sets of tests: -	// - 1: Test as a single threaded instance: We declare the class but ask for no thread -	//   to be spawned (easy with LLThreads since there's a boolean argument on the constructor -	//   just for that). We can then unit test each public method like we do on a normal class. -	// - 2: Test as a threaded instance: We let the thread launch and check that its external  -	//   behavior is as expected (i.e. it runs, can accept a work order and processes -	//   it). Typically though there's no guarantee that this exercises all the methods of the -	//   class which is why we also need the previous "non threaded" set of unit tests for -	//   complete coverage. -	// -	// ---------------------------------------------------------------------------------------  	template<> template<>  	void imagedecodethread_object_t::test<1>()  	{ -		// Test a *non threaded* instance of the class -		mThread = new LLImageDecodeThread(false); -		ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL); -		// Test that we start with an empty list right at creation -		ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0); -		// Insert something in the queue -		bool done = false; -		LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); -		// Verifies we got a valid handle -		ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0); -		// Verifies that we do now have something in the queued list -		ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1); -		// Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop) -		S32 res = mThread->update(0); -		// Verifies that we successfully handled the list -		ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0); -		// Verifies that the list is now empty -		ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0); -	} - -	template<> template<> -	void imagedecodethread_object_t::test<2>() -	{  		// Test a *threaded* instance of the class  		mThread = new LLImageDecodeThread(true);  		ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL); -		// Test that we start with an empty list right at creation -		ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0);  		// Insert something in the queue  		bool done = false; -		LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); +		LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done));  		// Verifies we get back a valid handle  		ensure("LLImageDecodeThread:  threaded decodeImage(), returned handle is null", decodeHandle != 0); -		// Wait a little so to simulate the main thread doing something on its main loop... -		ms_sleep(500);		// 500 milliseconds -		// Verifies that the responder has *not* been called yet in the meantime -		ensure("LLImageDecodeThread: responder creation failed", done == false); -		// Ask the thread to update: that means tells the queue to check itself and creates work requests -		mThread->update(1);  		// Wait till the thread has time to handle the work order (though it doesn't do much per work order...)  		const U32 INCREMENT_TIME = 500;				// 500 milliseconds  		const U32 MAX_TIME = 20 * INCREMENT_TIME;	// Do the loop 20 times max, i.e. wait 10 seconds but no more @@ -242,24 +165,4 @@ namespace tut  		// Verifies that the responder has now been called  		ensure("LLImageDecodeThread: threaded work unit not processed", done == true);  	} - -	// --------------------------------------------------------------------------------------- -	// Test the LLImageDecodeThread::ImageRequest interface -	// --------------------------------------------------------------------------------------- -	 -	template<> template<> -	void imagerequest_object_t::test<1>() -	{ -		// Test that we start with a correct request at creation -		ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK()); -		bool res = mRequest->processRequest(); -		// Verifies that we processed the request successfully -		ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true); -		// Check that we can call the finishing call safely -		try { -			mRequest->finishRequest(false); -		} catch (...) { -			fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed"); -		} -	}  } diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 925da5674b..8a641617fa 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -118,6 +118,7 @@ bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int block  bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	//  	// FIXME: Get the comment field out of the texture  	// diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index dac5349f57..2ad42d6b87 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -379,6 +379,7 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod  void LLImageJ2CKDU::cleanupCodeStream()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	mInputp.reset();  	mDecodeState.reset();  	mCodeStreamp.reset(); @@ -426,6 +427,7 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc  // decodeImpl() usage matters for production.  bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	base.resetLastError();  	// *FIX: kdu calls our callback function if there's an error, and then bombs. @@ -509,6 +511,7 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  // Returns true to mean done, whether successful or not.  bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	ECodeStreamMode mode = MODE_FAST;  	LLTimer decode_timer; @@ -1332,6 +1335,7 @@ the `buf' pointer may actually point into a larger buffer representing  multiple tiles.  For this reason, `row_gap' is needed to identify the  separation between consecutive rows in the real buffer. */  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	S32 c;  	// Now walk through the lines of the buffer, recovering them from the  	// relevant tile-component processing engines. @@ -1339,18 +1343,27 @@ separation between consecutive rows in the real buffer. */  	LLTimer decode_timer;  	while (mDims.size.y--)  	{ -		for (c = 0; c < mNumComponents; c++) -		{ -			mEngines[c].pull(mLines[c]); -		} +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - pull"); +            for (c = 0; c < mNumComponents; c++) +            { +                mEngines[c].pull(mLines[c]); +            } +        } +  		if ((mNumComponents >= 3) && mUseYCC)  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - convert");  			kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]);  		} -		for (c = 0; c < mNumComponents; c++) -		{ -			transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]); -		} + +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - transfer"); +            for (c = 0; c < mNumComponents; c++) +            { +                transfer_bytes(mBuf + c, mLines[c], mNumComponents, mBitDepths[c]); +            } +        }  		mBuf += mRowGap;  		if (mDims.size.y % 10)  		{ diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 552e820127..4617309606 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -4,12 +4,14 @@ project(llmath)  include(00-Common)  include(LLCommon) +include(LLMeshOptimizer)  include(bugsplat)  include(Boost)  include_directories(      ${LLCOMMON_INCLUDE_DIRS}      ${LLCOMMON_SYSTEM_INCLUDE_DIRS} +    ${LLMESHOPTIMIZER_INCLUDE_DIRS}      )  set(llmath_SOURCE_FILES @@ -109,6 +111,7 @@ add_library (llmath ${llmath_SOURCE_FILES})  target_link_libraries(llmath      ${LLCOMMON_LIBRARIES} +    ${LLMESHOPTIMIZER_LIBRARIES}      )  # Add tests diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 5099920f32..4a069b0f63 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -49,6 +49,7 @@  #include "llsdserialize.h"  #include "llvector4a.h"  #include "llmatrix4a.h" +#include "llmeshoptimizer.h"  #include "lltimer.h"  #define DEBUG_SILHOUETTE_BINORMALS 0 @@ -4952,6 +4953,50 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a  	return a.mV[2] < b.mV[2];  } +void LLVolumeFace::remap() +{ +    // Generate a remap buffer +    std::vector<unsigned int> remap(mNumVertices); +    S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], +        mIndices, +        mNumIndices, +        mPositions, +        mNormals, +        mTexCoords, +        mNumVertices); + +    // Allocate new buffers +    S32 size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF; +    U16* remap_indices = (U16*)ll_aligned_malloc_16(size); + +    S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF; +    LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size); +    LLVector4a* remap_normals = remap_positions + remap_vertices_count; +    LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count); + +    // Fill the buffers +    LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]); +    LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]); +    LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]); +    LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]); + +    // Free unused buffers +    ll_aligned_free_16(mIndices); +    ll_aligned_free<64>(mPositions); + +    // Tangets are now invalid +    ll_aligned_free_16(mTangents); +    mTangents = NULL; + +    // Assign new values +    mIndices = remap_indices; +    mPositions = remap_positions; +    mNormals = remap_normals; +    mTexCoords = remap_tex_coords; +    mNumVertices = remap_vertices_count; +    mNumAllocatedVertices = remap_vertices_count; +} +  void LLVolumeFace::optimize(F32 angle_cutoff)  {  	LLVolumeFace new_face; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c0b224b1ff..9697952f5b 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -902,6 +902,10 @@ public:  		typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;  	}; +    // Eliminates non unique triangles, takes positions, +    // normals and texture coordinates into account. +    void remap(); +  	void optimize(F32 angle_cutoff = 2.f);  	bool cacheOptimize(); diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index a879389c5a..c178348968 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -28,6 +28,9 @@  #include "meshoptimizer.h" +#include "llmath.h" +#include "v2math.h" +  LLMeshOptimizer::LLMeshOptimizer()  {      // Todo: Looks like for memory management, we can add allocator and deallocator callbacks @@ -40,25 +43,219 @@ LLMeshOptimizer::~LLMeshOptimizer()  }  //static -void LLMeshOptimizer::generateShadowIndexBuffer(U16 *destination, -    const U16 *indices, +void LLMeshOptimizer::generateShadowIndexBufferU32(U32 *destination, +    const U32 *indices,      U64 index_count, -    const LLVector4a *vertex_positions, -    U64 vertex_count, -    U64 vertex_positions_stride +    const LLVector4a * vertex_positions, +    const LLVector4a * normals, +    const LLVector2 * text_coords, +    U64 vertex_count  )  { -    meshopt_generateShadowIndexBuffer<unsigned short>(destination, +    meshopt_Stream streams[3]; + +    S32 index = 0; +    if (vertex_positions) +    { +        streams[index].data = (const float*)vertex_positions; +        // Despite being LLVector4a, only x, y and z are in use +        streams[index].size = sizeof(F32) * 3; +        streams[index].stride = sizeof(F32) * 4; +        index++; +    } +    if (normals) +    { +        streams[index].data = (const float*)normals; +        streams[index].size = sizeof(F32) * 3; +        streams[index].stride = sizeof(F32) * 4; +        index++; +    } +    if (text_coords) +    { +        streams[index].data = (const float*)text_coords; +        streams[index].size = sizeof(F32) * 2; +        streams[index].stride = sizeof(F32) * 2; +        index++; +    } + +    if (index == 0) +    { +        // invalid +        return; +    } + +    meshopt_generateShadowIndexBufferMulti<unsigned int>(destination,          indices,          index_count, -        (const float*)vertex_positions, // verify that it is correct to convert to float          vertex_count, -        sizeof(LLVector4a), -        vertex_positions_stride +        streams, +        index          );  }  //static +void LLMeshOptimizer::generateShadowIndexBufferU16(U16 *destination, +    const U16 *indices, +    U64 index_count, +    const LLVector4a * vertex_positions, +    const LLVector4a * normals, +    const LLVector2 * text_coords, +    U64 vertex_count +) +{ +    meshopt_Stream streams[3]; + +    S32 index = 0; +    if (vertex_positions) +    { +        streams[index].data = (const float*)vertex_positions; +        streams[index].size = sizeof(F32) * 3; +        streams[index].stride = sizeof(F32) * 4; +        index++; +    } +    if (normals) +    { +        streams[index].data = (const float*)normals; +        streams[index].size = sizeof(F32) * 3; +        streams[index].stride = sizeof(F32) * 4; +        index++; +    } +    if (text_coords) +    { +        streams[index].data = (const float*)text_coords; +        streams[index].size = sizeof(F32) * 2; +        streams[index].stride = sizeof(F32) * 2; +        index++; +    } + +    if (index == 0) +    { +        // invalid +        return; +    } + +    meshopt_generateShadowIndexBufferMulti<unsigned short>(destination, +        indices, +        index_count, +        vertex_count, +        streams, +        index); +} + +void LLMeshOptimizer::optimizeVertexCacheU32(U32 * destination, const U32 * indices, U64 index_count, U64 vertex_count) +{ +    meshopt_optimizeVertexCache<unsigned int>(destination, indices, index_count, vertex_count); +} + +void LLMeshOptimizer::optimizeVertexCacheU16(U16 * destination, const U16 * indices, U64 index_count, U64 vertex_count) +{ +    meshopt_optimizeVertexCache<unsigned short>(destination, indices, index_count, vertex_count); +} + +size_t LLMeshOptimizer::generateRemapMultiU32( +    unsigned int* remap, +    const U32 * indices, +    U64 index_count, +    const LLVector4a * vertex_positions, +    const LLVector4a * normals, +    const LLVector2 * text_coords, +    U64 vertex_count) +{ +    meshopt_Stream streams[] = { +       {(const float*)vertex_positions, sizeof(F32) * 3, sizeof(F32) * 4}, +       {(const float*)normals, sizeof(F32) * 3, sizeof(F32) * 4}, +       {(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2}, +    }; + +    // Remap can function without indices, +    // but providing indices helps with removing unused vertices +    U64 indeces_cmp = indices ? index_count : vertex_count; + +    // meshopt_generateVertexRemapMulti will throw an assert if (indices[i] >= vertex_count) +    return meshopt_generateVertexRemapMulti(&remap[0], indices, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); +} + +size_t LLMeshOptimizer::generateRemapMultiU16( +    unsigned int* remap, +    const U16 * indices, +    U64 index_count, +    const LLVector4a * vertex_positions, +    const LLVector4a * normals, +    const LLVector2 * text_coords, +    U64 vertex_count) +{ +    S32 out_of_range_count = 0; +    U32* indices_u32 = NULL; +    if (indices) +    { +        indices_u32 = (U32*)ll_aligned_malloc_32(index_count * sizeof(U32)); +        for (U64 i = 0; i < index_count; i++) +        { +            if (indices[i] < vertex_count) +            { +                indices_u32[i] = (U32)indices[i]; +            } +            else +            { +                out_of_range_count++; +                indices_u32[i] = 0; +            } +        } +    } + +    if (out_of_range_count) +    { +        LL_WARNS() << out_of_range_count << " indices are out of range." << LL_ENDL; +    } + +    size_t unique = generateRemapMultiU32(remap, indices_u32, index_count, vertex_positions, normals, text_coords, vertex_count); + +    ll_aligned_free_32(indices_u32); + +    return unique; +} + +void LLMeshOptimizer::remapIndexBufferU32(U32 * destination_indices, +    const U32 * indices, +    U64 index_count, +    const unsigned int* remap) +{ +    meshopt_remapIndexBuffer<unsigned int>(destination_indices, indices, index_count, remap); +} + +void LLMeshOptimizer::remapIndexBufferU16(U16 * destination_indices, +    const U16 * indices, +    U64 index_count, +    const unsigned int* remap) +{ +    meshopt_remapIndexBuffer<unsigned short>(destination_indices, indices, index_count, remap); +} + +void LLMeshOptimizer::remapPositionsBuffer(LLVector4a * destination_vertices, +    const LLVector4a * vertex_positions, +    U64 vertex_count, +    const unsigned int* remap) +{ +    meshopt_remapVertexBuffer((float*)destination_vertices, (const float*)vertex_positions, vertex_count, sizeof(LLVector4a), remap); +} + +void LLMeshOptimizer::remapNormalsBuffer(LLVector4a * destination_normalss, +    const LLVector4a * normals, +    U64 mormals_count, +    const unsigned int* remap) +{ +    meshopt_remapVertexBuffer((float*)destination_normalss, (const float*)normals, mormals_count, sizeof(LLVector4a), remap); +} + +void LLMeshOptimizer::remapUVBuffer(LLVector2 * destination_uvs, +    const LLVector2 * uv_positions, +    U64 uv_count, +    const unsigned int* remap) +{ +    meshopt_remapVertexBuffer((float*)destination_uvs, (const float*)uv_positions, uv_count, sizeof(LLVector2), remap); +} + +//static  U64 LLMeshOptimizer::simplifyU32(U32 *destination,      const U32 *indices,      U64 index_count, diff --git a/indra/llmeshoptimizer/llmeshoptimizer.h b/indra/llmeshoptimizer/llmeshoptimizer.h index e8dd16dae9..ea965d6b47 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.h +++ b/indra/llmeshoptimizer/llmeshoptimizer.h @@ -28,7 +28,8 @@  #include "linden_common.h" -#include "llmath.h" +class LLVector4a; +class LLVector2;  class LLMeshOptimizer  { @@ -36,13 +37,85 @@ public:      LLMeshOptimizer();      ~LLMeshOptimizer(); -    static void generateShadowIndexBuffer( +    static void generateShadowIndexBufferU32( +        U32 *destination, +        const U32 *indices, +        U64 index_count, +        const LLVector4a * vertex_positions, +        const LLVector4a * normals, +        const LLVector2 * text_coords, +        U64 vertex_count); + +    static void generateShadowIndexBufferU16(          U16 *destination,          const U16 *indices,          U64 index_count, -        const LLVector4a *vertex_positions, +        const LLVector4a * vertex_positions, +        const LLVector4a * normals, +        const LLVector2 * text_coords, +        U64 vertex_count); + +    static void optimizeVertexCacheU32( +        U32 *destination, +        const U32 *indices, +        U64 index_count, +        U64 vertex_count); + +    static void optimizeVertexCacheU16( +        U16 *destination, +        const U16 *indices, +        U64 index_count, +        U64 vertex_count); + +    // Remap functions +    // Welds indentical vertexes together. +    // Removes unused vertices if indices were provided. + +    static size_t generateRemapMultiU32( +        unsigned int* remap, +        const U32 * indices, +        U64 index_count, +        const LLVector4a * vertex_positions, +        const LLVector4a * normals, +        const LLVector2 * text_coords, +        U64 vertex_count); + +    static size_t generateRemapMultiU16( +        unsigned int* remap, +        const U16 * indices, +        U64 index_count, +        const LLVector4a * vertex_positions, +        const LLVector4a * normals, +        const LLVector2 * text_coords, +        U64 vertex_count); + +    static void remapIndexBufferU32(U32 * destination_indices, +        const U32 * indices, +        U64 index_count, +        const unsigned int* remap); + +    static void remapIndexBufferU16(U16 * destination_indices, +        const U16 * indices, +        U64 index_count, +        const unsigned int* remap); + + +    static void remapPositionsBuffer(LLVector4a * destination_vertices, +        const LLVector4a * vertex_positions,          U64 vertex_count, -        U64 vertex_positions_stride); +        const unsigned int* remap); + +    static void remapNormalsBuffer(LLVector4a * destination_normalss, +        const LLVector4a * normals, +        U64 mormals_count, +        const unsigned int* remap); + +    static void remapUVBuffer(LLVector2 * destination_uvs, +        const LLVector2 * uv_positions, +        U64 uv_count, +        const unsigned int* remap); + +    // Simplification      // returns amount of indices in destiantion      // sloppy engages a variant of a mechanizm that does not respect topology as much diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index c67f59bc0c..ae066112c1 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -64,7 +64,6 @@ LLCore::HttpRequest::ptr_t		sHttpRequest;  LLCore::HttpHeaders::ptr_t		sHttpHeaders;  LLCore::HttpOptions::ptr_t		sHttpOptions;  LLCore::HttpRequest::policy_t	sHttpPolicy; -LLCore::HttpRequest::priority_t	sHttpPriority;  /* Sample response:  <?xml version="1.0"?> @@ -121,7 +120,6 @@ LLAvatarNameCache::LLAvatarNameCache()      sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());      sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());      sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; -    sHttpPriority = 0;  }  LLAvatarNameCache::~LLAvatarNameCache() diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 7031f1aa8c..96af8bacee 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -131,7 +131,6 @@ bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd)  HttpHandle requestPostWithLLSD(HttpRequest * request,      HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const HttpOptions::ptr_t &options, @@ -145,7 +144,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request,      LLSDSerialize::toXML(body, bas);      handle = request->requestPost(policy_id, -        priority,          url,          ba,          options, @@ -158,7 +156,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request,  HttpHandle requestPutWithLLSD(HttpRequest * request,      HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const HttpOptions::ptr_t &options, @@ -172,7 +169,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request,      LLSDSerialize::toXML(body, bas);      handle = request->requestPut(policy_id, -        priority,          url,          ba,          options, @@ -184,7 +180,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request,  HttpHandle requestPatchWithLLSD(HttpRequest * request,      HttpRequest::policy_t policy_id, -    HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const HttpOptions::ptr_t &options, @@ -198,7 +193,6 @@ HttpHandle requestPatchWithLLSD(HttpRequest * request,      LLSDSerialize::toXML(body, bas);      handle = request->requestPatch(policy_id, -        priority,          url,          ba,          options, @@ -672,10 +666,9 @@ const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content");  const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw");  HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name, -    LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) : +    LLCore::HttpRequest::policy_t policyId) :      mAdapterName(name),      mPolicyId(policyId), -    mPriority(priority),      mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),      mWeakRequest(),      mWeakHandler() @@ -709,7 +702,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case.      LLCore::HttpHandle hhandle = requestPostWithLLSD(request, -        mPolicyId, mPriority, url, body, options, headers, +        mPolicyId, url, body, options, headers,          handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -832,7 +825,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case. -    LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(), +    LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, url, rawbody.get(),          options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -890,7 +883,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case.      LLCore::HttpHandle hhandle = requestPutWithLLSD(request, -        mPolicyId, mPriority, url, body, options, headers, +        mPolicyId, url, body, options, headers,          handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -916,7 +909,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case. -    LLCore::HttpHandle hhandle = request->requestPut(mPolicyId, mPriority,  +    LLCore::HttpHandle hhandle = request->requestPut(mPolicyId,          url, rawbody.get(), options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -972,7 +965,7 @@ LLSD HttpCoroutineAdapter::getAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case. -    LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, mPriority, +    LLCore::HttpHandle hhandle = request->requestGet(mPolicyId,          url, options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1018,7 +1011,7 @@ LLSD HttpCoroutineAdapter::deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request      checkDefaultHeaders(headers);      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case. -    LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority, +    LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId,          url, options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1056,7 +1049,7 @@ LLSD HttpCoroutineAdapter::patchAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case.      LLCore::HttpHandle hhandle = requestPatchWithLLSD(request, -        mPolicyId, mPriority, url, body, options, headers, +        mPolicyId, url, body, options, headers,          handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1098,7 +1091,7 @@ LLSD HttpCoroutineAdapter::copyAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case.      //  -    LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, mPriority, url, +    LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, url,          options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1140,7 +1133,7 @@ LLSD HttpCoroutineAdapter::moveAndSuspend_(LLCore::HttpRequest::ptr_t &request,      // The HTTPCoroHandler does not self delete, so retrieval of a the contained       // pointer from the smart pointer is safe in this case.      //  -    LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, mPriority, url, +    LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, url,          options, headers, handler);      if (hhandle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 6f0b865f83..430dc417ac 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -116,7 +116,6 @@ std::string responseToString(LLCore::HttpResponse * response);  ///  LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const LLCore::HttpOptions::ptr_t &options, @@ -125,20 +124,18 @@ LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,  inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,  	LLCore::HttpRequest::policy_t policy_id, -	LLCore::HttpRequest::priority_t priority,  	const std::string & url,  	const LLSD & body,  	const LLCore::HttpOptions::ptr_t & options,  	const LLCore::HttpHeaders::ptr_t & headers,      const LLCore::HttpHandler::ptr_t & handler)  { -    return requestPostWithLLSD(request.get(), policy_id, priority, +    return requestPostWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  }  inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const LLCore::HttpHandler::ptr_t &handler) @@ -146,7 +143,7 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque      LLCore::HttpOptions::ptr_t options;      LLCore::HttpHeaders::ptr_t headers; -    return requestPostWithLLSD(request.get(), policy_id, priority, +    return requestPostWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  } @@ -169,7 +166,6 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque  ///  LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,  	LLCore::HttpRequest::policy_t policy_id, -	LLCore::HttpRequest::priority_t priority,  	const std::string & url,  	const LLSD & body,  	const LLCore::HttpOptions::ptr_t &options, @@ -178,20 +174,18 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,  inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,  	LLCore::HttpRequest::policy_t policy_id, -	LLCore::HttpRequest::priority_t priority,  	const std::string & url,  	const LLSD & body,  	const LLCore::HttpOptions::ptr_t & options,  	const LLCore::HttpHeaders::ptr_t & headers,      LLCore::HttpHandler::ptr_t handler)  { -    return requestPutWithLLSD(request.get(), policy_id, priority, +    return requestPutWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  }  inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      LLCore::HttpHandler::ptr_t handler) @@ -199,7 +193,7 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques      LLCore::HttpOptions::ptr_t options;      LLCore::HttpHeaders::ptr_t headers; -    return requestPutWithLLSD(request.get(), policy_id, priority, +    return requestPutWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  } @@ -221,7 +215,6 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques  ///  LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const LLCore::HttpOptions::ptr_t &options, @@ -230,20 +223,18 @@ LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,  inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const LLCore::HttpOptions::ptr_t & options,      const LLCore::HttpHeaders::ptr_t & headers,      const LLCore::HttpHandler::ptr_t & handler)  { -    return requestPatchWithLLSD(request.get(), policy_id, priority, +    return requestPatchWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  }  inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,      LLCore::HttpRequest::policy_t policy_id, -    LLCore::HttpRequest::priority_t priority,      const std::string & url,      const LLSD & body,      const LLCore::HttpHandler::ptr_t &handler) @@ -251,7 +242,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ      LLCore::HttpOptions::ptr_t options;      LLCore::HttpHeaders::ptr_t headers; -    return requestPatchWithLLSD(request.get(), policy_id, priority, +    return requestPatchWithLLSD(request.get(), policy_id,          url, body, options, headers, handler);  } @@ -329,8 +320,7 @@ public:      typedef boost::shared_ptr<HttpCoroutineAdapter> ptr_t;      typedef boost::weak_ptr<HttpCoroutineAdapter>   wptr_t; -    HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId, -        LLCore::HttpRequest::priority_t priority = 0L); +    HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId);      ~HttpCoroutineAdapter();      /// Execute a Post transaction on the supplied URL and yield execution of  @@ -673,7 +663,6 @@ private:      void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);      std::string                     mAdapterName; -    LLCore::HttpRequest::priority_t mPriority;      LLCore::HttpRequest::policy_t   mPolicyId;      LLCore::HttpHandle              mYieldingHandle; diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp index 6424117ef3..78424a28c8 100644 --- a/indra/llmessage/tests/llcoproceduremanager_test.cpp +++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp @@ -48,7 +48,7 @@  #pragma warning(disable: 4702)  #endif -LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int, unsigned int) +LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int)  {  } diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 68b29f01da..50f4a4306e 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -2563,7 +2563,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo  		if (!mNoOptimize)  		{ -			ret->optimizeVolumeFaces(); +			ret->remapVolumeFaces();  		}  		volume_faces = remainder.size(); diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index a8d5fb8e85..ab381ca55e 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -61,8 +61,10 @@ public:      // get a UUID based on a hash of this LLGLTFMaterial      LLUUID getHash() const      { +        LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;          LLMD5 md5;          md5.update((unsigned char*) this, sizeof(this)); +        md5.finalize();          LLUUID id;          md5.raw_digest(id.mData);          return id; diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index b1d371a399..285c5f656b 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -107,6 +107,14 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )  	}  } +void LLModel::remapVolumeFaces() +{ +    for (U32 i = 0; i < getNumVolumeFaces(); ++i) +    { +        mVolumeFaces[i].remap(); +    } +} +  void LLModel::optimizeVolumeFaces()  {  	for (U32 i = 0; i < getNumVolumeFaces(); ++i) diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 3881b1338c..354ceb26b7 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -184,6 +184,7 @@ public:  	void sortVolumeFacesByMaterialName();  	void normalizeVolumeFaces();  	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); +    void remapVolumeFaces();  	void optimizeVolumeFaces();  	void offsetMesh( const LLVector3& pivotPoint );  	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 3f0059b759..8b470d235c 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1701,6 +1701,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)          return (size == 4);      case PARAMS_RENDER_MATERIAL:          return (size > 1); +    case PARAMS_REFLECTION_PROBE: +        return (size == 9);  	}  	return FALSE; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 89dd68da76..6215727de0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -53,13 +53,75 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;  //assumes i is a power of 2 > 0  U32 wpo2(U32 i); + +// texture memory accounting (for OS X) +static LLMutex sTexMemMutex; +static std::unordered_map<U32, U32> sTextureAllocs; +static U64 sTextureBytes = 0; + +// track a texture alloc on the currently bound texture. +// asserts that no currently tracked alloc exists +static void alloc_tex_image(U32 width, U32 height, U32 pixformat) +{ +    U32 texUnit = gGL.getCurrentTexUnitIndex(); +    U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); +    S32 size = LLImageGL::dataFormatBytes(pixformat, width, height); + +    llassert(size >= 0); + +    sTexMemMutex.lock(); +    llassert(sTextureAllocs.find(texName) == sTextureAllocs.end()); + +    sTextureAllocs[texName] = size; +    sTextureBytes += size; + +    sTexMemMutex.unlock(); +} + +// track texture free on given texName +static void free_tex_image(U32 texName) +{ +    sTexMemMutex.lock(); +    auto iter = sTextureAllocs.find(texName); +    if (iter != sTextureAllocs.end()) +    { +        llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero + +        sTextureBytes -= iter->second; + +        sTextureAllocs.erase(iter); +    } + +    sTexMemMutex.unlock(); +} + +// track texture free on given texNames +static void free_tex_images(U32 count, const U32* texNames) +{ +    for (int i = 0; i < count; ++i) +    { +        free_tex_image(texNames[i]); +    } +} + +// track texture free on currently bound texture +static void free_cur_tex_image() +{ +    U32 texUnit = gGL.getCurrentTexUnitIndex(); +    U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); +    free_tex_image(texName); +} + +// static  +U64 LLImageGL::getTextureBytesAllocated() +{ +    return sTextureBytes; +} +  //statics  U32 LLImageGL::sUniqueCount				= 0;  U32 LLImageGL::sBindCount				= 0; -S32Bytes LLImageGL::sGlobalTextureMemory(0); -S32Bytes LLImageGL::sBoundTextureMemory(0); -S32Bytes LLImageGL::sCurBoundTextureMemory(0);  S32 LLImageGL::sCount					= 0;  BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE; @@ -220,6 +282,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)      case GL_RGBA:								    return 32;      case GL_SRGB_ALPHA:						        return 32;      case GL_BGRA:								    return 32;		// Used for QuickTime media textures on the Mac +    case GL_DEPTH_COMPONENT:                        return 24;      default:          LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;          return 0; @@ -282,15 +345,6 @@ void LLImageGL::updateStats(F32 current_time)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	sLastFrameTime = current_time; -	sBoundTextureMemory = sCurBoundTextureMemory; -	sCurBoundTextureMemory = S32Bytes(0); -} - -//static -S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) -{ -	LLImageGL::sCurBoundTextureMemory += mem ; -	return LLImageGL::sCurBoundTextureMemory.value();  }  //---------------------------------------------------------------------------- @@ -623,7 +677,7 @@ void LLImageGL::forceUpdateBindStats(void) const  	mLastBindTime = sLastFrameTime;  } -BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const +BOOL LLImageGL::updateBindStats() const  {	  	if (mTexName != 0)  	{ @@ -635,7 +689,6 @@ BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const  		{  			// we haven't accounted for this texture yet this frame  			sUniqueCount++; -			updateBoundTexMem(tex_mem, mComponents, mCategory);  			mLastBindTime = sLastFrameTime;  			return TRUE ; @@ -1232,6 +1285,7 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)  {  	if (gGLManager.mInited)  	{ +        free_tex_images(numTextures, textures);  		glDeleteTextures(numTextures, textures);  	}  } @@ -1354,7 +1408,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt      stop_glerror();      {          LL_PROFILE_ZONE_NAMED("glTexImage2D"); + +        free_cur_tex_image();          glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); +        alloc_tex_image(width, height, pixformat);      }      stop_glerror(); @@ -1601,11 +1658,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_      // things will break if we don't unbind after creation      gGL.getTexUnit(0)->unbind(mBindTarget); -    if (old_texname != 0) -    { -        sGlobalTextureMemory -= mTextureMemory; -    } -      //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread      if (!defer_copy)      { @@ -1626,7 +1678,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_      mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); -    sGlobalTextureMemory += mTextureMemory;      mTexelsInGLTexture = getWidth() * getHeight();      // mark this as bound at this point, so we don't throw it out immediately @@ -1636,51 +1687,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_      return TRUE;  } -void LLImageGLThread::updateClass() -{ -    LL_PROFILE_ZONE_SCOPED; - -    // update available vram one per second -    static LLFrameTimer sTimer; - -    if (sTimer.getElapsedSeconds() < 1.f) -    { -        return; -    } -     -    sTimer.reset(); - -    auto func = []() -    { -        if (gGLManager.mHasATIMemInfo) -        { -            S32 meminfo[4]; -            glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); -            LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; - -        } -        else if (gGLManager.mHasNVXMemInfo) -        { -            S32 free_memory; -            glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); -            LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; -        } -    }; - -     -    // post update to background thread if available, otherwise execute immediately -    auto queue = LL::WorkQueue::getInstance("LLImageGL"); -    if (sEnabled) -    { -        queue->post(func); -    } -    else -    { -        llassert(queue == nullptr); -        func(); -    } -} -  void LLImageGL::syncToMainThread(LLGLuint new_tex_name)  {      LL_PROFILE_ZONE_SCOPED; @@ -1874,7 +1880,6 @@ void LLImageGL::destroyGLTexture()  	{  		if(mTextureMemory != S32Bytes(0))  		{ -			sGlobalTextureMemory -= mTextureMemory;  			mTextureMemory = (S32Bytes)0;  		} @@ -2426,13 +2431,9 @@ void LLImageGL::checkActiveThread()  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  nummips);  */   -std::atomic<S32> LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB -  LLImageGLThread::LLImageGLThread(LLWindow* window) -    // We want exactly one thread, but a very large capacity: we never want -    // anyone, especially inner-loop render code, to have to block on post() -    // because we're full. -    : ThreadPool("LLImageGL", 1, 1024*1024) +    // We want exactly one thread. +    : ThreadPool("LLImageGL", 1)      , mWindow(window)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -2455,8 +2456,3 @@ void LLImageGLThread::run()      mWindow->destroySharedContext(mContext);  } -S32 LLImageGLThread::getFreeVRAMMegabytes() -{ -    return sFreeVRAMMegabytes; -} - diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index b419c9fab5..b4618fd35c 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -52,6 +52,13 @@ class LLImageGL : public LLRefCount  {  	friend class LLTexUnit;  public: + +    // Get an estimate of how many bytes have been allocated in vram for textures. +    // Does not include mipmaps. +    // NOTE: multiplying this number by two gives a good estimate for total +    // video memory usage based on testing in lagland against an NVIDIA GPU. +    static U64 getTextureBytesAllocated(); +  	// These 2 functions replace glGenTextures() and glDeleteTextures()  	static void generateTextures(S32 numTextures, U32 *textures);  	static void deleteTextures(S32 numTextures, const U32 *textures); @@ -61,7 +68,7 @@ public:  	static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);  	static S32 dataFormatComponents(S32 dataformat); -	BOOL updateBindStats(S32Bytes tex_mem) const ; +	BOOL updateBindStats() const ;  	F32 getTimePassedSinceLastBound();  	void forceUpdateBindStats(void) const; @@ -73,9 +80,6 @@ public:  	static void restoreGL();  	static void dirtyTexOptions(); -	// Sometimes called externally for textures not using LLImageGL (should go away...)	 -	static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ; -	  	static bool checkSize(S32 width, S32 height);  	//for server side use only. @@ -165,7 +169,7 @@ public:  	void updatePickMask(S32 width, S32 height, const U8* data_in);  	BOOL getMask(const LLVector2 &tc); -	void checkTexSize(bool forced = false) const ; +    void checkTexSize(bool forced = false) const ;  	// Sets the addressing mode used to sample the texture   	//  (such as wrapping, mirrored wrapping, and clamp) @@ -265,9 +269,6 @@ public:  	static F32 sLastFrameTime;  	// Global memory statistics -	static S32Bytes sGlobalTextureMemory;	// Tracks main memory texmem -	static S32Bytes sBoundTextureMemory;	// Tracks bound texmem for last completed frame -	static S32Bytes sCurBoundTextureMemory;		// Tracks bound texmem for current frame  	static U32 sBindCount;					// Tracks number of texture binds for current frame  	static U32 sUniqueCount;				// Tracks number of unique texture binds for current frame  	static BOOL sGlobalUseAnisotropic; @@ -327,12 +328,6 @@ public:      // follows gSavedSettings "RenderGLMultiThreaded"      static bool sEnabled; -    // app should call this function periodically -    static void updateClass(); - -    // free video memory in megabytes -    static std::atomic<S32> sFreeVRAMMegabytes; -      LLImageGLThread(LLWindow* window);      // post a function to be executed on the LLImageGL background thread @@ -344,8 +339,6 @@ public:      void run() override; -    static S32 getFreeVRAMMegabytes(); -  private:      LLWindow* mWindow;      void* mContext = nullptr; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 3adb47f493..e5bd19e91c 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -224,7 +224,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  					enable(gl_tex->getTarget());  					mCurrTexture = gl_tex->getTexName();  					glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); -					if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) +					if(gl_tex->updateBindStats())  					{  						texture->setActive() ;  						texture->updateBindStatsForTester() ; @@ -303,7 +303,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32  		mCurrTexture = texname;  		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);  		stop_glerror(); -		texture->updateBindStats(texture->mTextureMemory);		 +        texture->updateBindStats();  		mHasMipMaps = texture->mHasMipMaps;  		if (texture->mTexOptionsDirty)  		{ @@ -342,7 +342,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)              mCurrTexture = cubeMap->mImages[0]->getTexName();  			glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);  			mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; -			cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory); +			cubeMap->mImages[0]->updateBindStats();  			if (cubeMap->mImages[0]->mTexOptionsDirty)  			{  				cubeMap->mImages[0]->mTexOptionsDirty = false; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 686eaddc24..96fb764f75 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -673,7 +673,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  	if (file == NULL)  	{ -		LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL; +		LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL;  		return 0;  	} diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 0e59fdf519..8028f397f3 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -102,6 +102,7 @@ LLButton::Params::Params()  	scale_image("scale_image", true),  	hover_glow_amount("hover_glow_amount"),  	commit_on_return("commit_on_return", true), +    commit_on_capture_lost("commit_on_capture_lost", false),  	display_pressed_state("display_pressed_state", true),  	use_draw_context_alpha("use_draw_context_alpha", true),  	badge("badge"), @@ -165,6 +166,7 @@ LLButton::LLButton(const LLButton::Params& p)  	mBottomVPad(p.pad_bottom),  	mHoverGlowStrength(p.hover_glow_amount),  	mCommitOnReturn(p.commit_on_return), +    mCommitOnCaptureLost(p.commit_on_capture_lost),  	mFadeWhenDisabled(FALSE),  	mForcePressedState(false),  	mDisplayPressedState(p.display_pressed_state), @@ -475,6 +477,10 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)  	// We only handle the click if the click both started and ended within us  	if( hasMouseCapture() )  	{ +        // reset timers before focus change, to not cause +        // additional commits if mCommitOnCaptureLost. +        resetMouseDownTimer(); +  		// Always release the mouse  		gFocusMgr.setMouseCapture( NULL ); @@ -489,8 +495,6 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)  		// Regardless of where mouseup occurs, handle callback  		if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); -		resetMouseDownTimer(); -  		// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.  		// If mouseup in the widget, it's been clicked  		if (pointInView(x, y)) @@ -1195,6 +1199,18 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen  void LLButton::onMouseCaptureLost()  { +    if (mCommitOnCaptureLost +        && mMouseDownTimer.getStarted()) +    { +        if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); + +        if (mIsToggle) +        { +            toggleState(); +        } + +        LLUICtrl::onCommit(); +    }  	resetMouseDownTimer();  } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 572d36996c..ccd31e90c0 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -124,6 +124,7 @@ public:  		Optional<bool>			is_toggle,  								scale_image,  								commit_on_return, +								commit_on_capture_lost,  								display_pressed_state;  		Optional<F32>				hover_glow_amount; @@ -374,6 +375,7 @@ protected:  	F32							mCurGlowStrength;  	bool						mCommitOnReturn; +    bool						mCommitOnCaptureLost;  	bool						mFadeWhenDisabled;  	bool						mForcePressedState;  	bool						mDisplayPressedState; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 03efd09689..c6a3ada777 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -259,6 +259,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)  	mMinHeight(p.min_height),  	mHeaderHeight(p.header_height),  	mLegacyHeaderHeight(p.legacy_header_height), +	mDefaultRectForGroup(true),  	mMinimized(FALSE),  	mForeground(FALSE),  	mFirstLook(TRUE), @@ -906,7 +907,10 @@ bool LLFloater::applyRectControl()  	if (last_in_group && last_in_group != this)  	{  		// other floaters in our group, position ourselves relative to them and don't save the rect -		mRectControl.clear(); +		if (mDefaultRectForGroup) +		{ +			mRectControl.clear(); +		}  		mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP;  	}  	else @@ -3481,8 +3485,15 @@ void LLFloater::stackWith(LLFloater& other)  	}  	next_rect.translate(floater_offset, -floater_offset); -	next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); -	 +	const LLRect& rect = getControlGroup()->getRect(mRectControl); +	if (rect.notEmpty() && !mDefaultRectForGroup && mResizable) +	{ +		next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); +	} +	else +	{ +		next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); +	}  	setShape(next_rect);  	if (!other.getHost()) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 306760b7fb..668cd208a9 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -454,6 +454,7 @@ public:  protected:  	bool			mSaveRect; +	bool			mDefaultRectForGroup;  	std::string		mRectControl;  	std::string		mPosXControl;  	std::string		mPosYControl; diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 82b01e705d..e01aba402e 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -35,6 +35,7 @@  #include "llui.h"  #include "lluictrlfactory.h"  #include "lluiimage.h" +#include "llwindow.h"  static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon"); @@ -42,6 +43,7 @@ LLIconCtrl::Params::Params()  :	image("image_name"),  	color("color"),  	use_draw_context_alpha("use_draw_context_alpha", true), +    interactable("interactable", false),  	scale_image("scale_image"),  	min_width("min_width", 0),  	min_height("min_height", 0) @@ -52,6 +54,7 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)  	mColor(p.color()),  	mImagep(p.image),  	mUseDrawContextAlpha(p.use_draw_context_alpha), +    mInteractable(p.interactable),  	mPriority(0),  	mMinWidth(p.min_width),  	mMinHeight(p.min_height), @@ -81,6 +84,16 @@ void LLIconCtrl::draw()  	LLUICtrl::draw();  } +BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask) +{ +    if (mInteractable && getEnabled()) +    { +        getWindow()->setCursor(UI_CURSOR_HAND); +        return TRUE; +    } +    return LLUICtrl::handleHover(x, y, mask); +} +  // virtual  // value might be a string or a UUID  void LLIconCtrl::setValue(const LLSD& value) diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index dd83e78fd3..9c3b517bca 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -48,7 +48,8 @@ public:  	{  		Optional<LLUIImage*>	image;  		Optional<LLUIColor>		color; -		Optional<bool>			use_draw_context_alpha; +		Optional<bool>			use_draw_context_alpha, +                                interactable;  		Optional<S32>			min_width,  								min_height;  		Ignored					scale_image; @@ -67,6 +68,9 @@ public:  	// llview overrides  	virtual void	draw(); +    // llview overrides +    virtual BOOL handleHover(S32 x, S32 y, MASK mask); +  	// lluictrl overrides  	virtual void	setValue(const LLSD& value ); @@ -88,6 +92,7 @@ protected:  	// If set to true (default), use the draw context transparency.  	// If false, will use transparency returned by getCurrentTransparency(). See STORM-698.  	bool mUseDrawContextAlpha; +    bool mInteractable;  private:  	LLUIColor mColor; diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 303afcda15..583704418b 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -40,6 +40,7 @@ void LLMenuButton::MenuPositions::declareValues()  	declare("topleft", MP_TOP_LEFT);  	declare("topright", MP_TOP_RIGHT);  	declare("bottomleft", MP_BOTTOM_LEFT); +	declare("bottomright", MP_BOTTOM_RIGHT);  }  LLMenuButton::Params::Params() @@ -212,6 +213,13 @@ void LLMenuButton::updateMenuOrigin()  			mY = rect.mBottom;  			break;  		} +		case MP_BOTTOM_RIGHT: +		{ +			const LLRect& menu_rect = menu->getRect(); +			mX = rect.mRight - menu_rect.getWidth(); +			mY = rect.mBottom; +			break; +		}  	}  } diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 67ec1983b3..e42f8f53bd 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -41,7 +41,8 @@ public:  	{  		MP_TOP_LEFT,  		MP_TOP_RIGHT, -		MP_BOTTOM_LEFT +		MP_BOTTOM_LEFT, +		MP_BOTTOM_RIGHT  	} EMenuPosition;  	struct MenuPositions diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index 209796565c..cf57b1fe76 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -69,16 +69,22 @@ void LLProgressBar::draw()  	static LLTimer timer;  	F32 alpha = getDrawContext().mAlpha; -	LLColor4 image_bar_color = mColorBackground.get(); -	image_bar_color.setAlpha(alpha); -	mImageBar->draw(getLocalRect(), image_bar_color); +    if (mImageBar) // optional according to parameters +    { +        LLColor4 image_bar_color = mColorBackground.get(); +        image_bar_color.setAlpha(alpha); +        mImageBar->draw(getLocalRect(), image_bar_color); +    } -	alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); -	LLColor4 bar_color = mColorBar.get(); -	bar_color.mV[VALPHA] *= alpha; // modulate alpha -	LLRect progress_rect = getLocalRect(); -	progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f)); -	mImageFill->draw(progress_rect, bar_color); +    if (mImageFill) +    { +        alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32())); +        LLColor4 bar_color = mColorBar.get(); +        bar_color.mV[VALPHA] *= alpha; // modulate alpha +        LLRect progress_rect = getLocalRect(); +        progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f)); +        mImageFill->draw(progress_rect, bar_color); +    }  }  void LLProgressBar::setValue(const LLSD& value) diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ee78b82429..ef7c8ec012 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -103,6 +103,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);  	up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));  	up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); +    up_button_params.commit_on_capture_lost = true;  	mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);  	addChild(mUpBtn); @@ -111,6 +112,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)  	down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);  	down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));  	down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); +    down_button_params.commit_on_capture_lost = true;  	mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);  	addChild(mDownBtn); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 459fdcf2ae..0aa7a2d217 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -402,9 +402,13 @@ void LLTabContainer::draw()  	S32 cur_scroll_pos = getScrollPos();  	if (cur_scroll_pos > 0)  	{ -		S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size  + tabcntr_arrow_btn_size + 1); -		if (!mIsVertical) +		if (mIsVertical)  		{ +			target_pixel_scroll = cur_scroll_pos * (BTN_HEIGHT + tabcntrv_pad); +		} +		else +		{ +			S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size  + tabcntr_arrow_btn_size + 1);  			for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)  			{  				if (cur_scroll_pos == 0) @@ -1189,13 +1193,15 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)  	sendChildToFront(mNextArrowBtn);  	sendChildToFront(mJumpPrevArrowBtn);  	sendChildToFront(mJumpNextArrowBtn); -	 + +	updateMaxScrollPos(); +  	if( select )  	{  		selectLastTab(); +		mScrollPos = mMaxScrollPos;  	} -	updateMaxScrollPos();  }  void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label) @@ -2079,9 +2085,9 @@ void LLTabContainer::updateMaxScrollPos()  		if( tab_total_height > available_height )  		{  			static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); -			S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad); +			S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom;  			S32 additional_needed = tab_total_height - available_height_with_arrows; -			setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) ); +			setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) );  			no_scroll = FALSE;  		}  	} diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0dc99fdde6..c4a529e4ad 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -163,6 +163,7 @@ LLTextBase::Params::Params()  	font_shadow("font_shadow"),  	wrap("wrap"),  	trusted_content("trusted_content", true), +	always_show_icons("always_show_icons", false),  	use_ellipses("use_ellipses", false),  	parse_urls("parse_urls", false),  	force_urls_external("force_urls_external", false), @@ -212,6 +213,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mClip(p.clip),  	mClipPartial(p.clip_partial && !p.allow_scroll),  	mTrustedContent(p.trusted_content), +	mAlwaysShowIcons(p.always_show_icons),  	mTrackEnd( p.track_end ),  	mScrollIndex(-1),  	mSelectionStart( 0 ), @@ -448,8 +450,48 @@ void LLTextBase::drawSelectionBackground()  			++rect_it)  		{  			LLRect selection_rect = *rect_it; -			selection_rect = *rect_it; -			selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); +            if (mScroller) +            { +                // If scroller is On content_display_rect has correct rect and safe to use as is +                // Note: we might need to account for border +                selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom); +            } +            else +            { +                // If scroller is Off content_display_rect will have rect from document, adjusted to text width, heigh and position +                // and we have to acount for offset depending on position +                S32 v_delta = 0; +                S32 h_delta = 0; +                switch (mVAlign) +                { +                case LLFontGL::TOP: +                    v_delta = mVisibleTextRect.mTop - content_display_rect.mTop - mVPad; +                    break; +                case LLFontGL::VCENTER: +                    v_delta = (llmax(mVisibleTextRect.getHeight() - content_display_rect.mTop, -content_display_rect.mBottom) + (mVisibleTextRect.mBottom - content_display_rect.mBottom)) / 2; +                    break; +                case LLFontGL::BOTTOM: +                    v_delta = mVisibleTextRect.mBottom - content_display_rect.mBottom; +                    break; +                default: +                    break; +                } +                switch (mHAlign) +                { +                case LLFontGL::LEFT: +                    h_delta = mVisibleTextRect.mLeft - content_display_rect.mLeft + mHPad; +                    break; +                case LLFontGL::HCENTER: +                    h_delta = (llmax(mVisibleTextRect.getWidth() - content_display_rect.mLeft, -content_display_rect.mRight) + (mVisibleTextRect.mRight - content_display_rect.mRight)) / 2; +                    break; +                case LLFontGL::RIGHT: +                    h_delta = mVisibleTextRect.mRight - content_display_rect.mRight; +                    break; +                default: +                    break; +                } +                selection_rect.translate(h_delta, v_delta); +            }  			gl_rect_2d(selection_rect, selection_color);  		}  	} @@ -2116,7 +2158,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  		LLUrlMatch match;  		std::string text = new_text;  		while ( LLUrlRegistry::instance().findUrl(text, match, -				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted())) +				boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted() || mAlwaysShowIcons))  		{  			start = match.getStart();  			end = match.getEnd()+1; @@ -2141,7 +2183,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  			}  			// add icon before url if need -			LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); +			LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted() || mAlwaysShowIcons);  			if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() )  			{  				setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon")); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a4e83b42b4..25f8fa1c2b 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -321,7 +321,8 @@ public:  								parse_highlights,  								clip,  								clip_partial, -								trusted_content; +								trusted_content, +								always_show_icons;  		Optional<S32>			v_pad,  								h_pad; @@ -369,6 +370,8 @@ public:  	virtual void	onFocusReceived();  	virtual void	onFocusLost(); +    void        setParseHTML(bool parse_html) { mParseHTML = parse_html; } +  	// LLSpellCheckMenuHandler overrides  	/*virtual*/ bool		getSpellCheck() const; @@ -702,6 +705,8 @@ protected:  	bool						mAutoIndent;  	S32							mMaxTextByteLength;	// Maximum length mText is allowed to be in bytes  	bool						mSkipTripleClick; +	bool						mAlwaysShowIcons; +  	bool						mSkipLinkUnderline;  	// support widgets diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 70eb99c86c..32f0fa14c4 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -145,6 +145,8 @@ if (WINDOWS)    list(APPEND llwindow_LINK_LIBRARIES         comdlg32     # Common Dialogs for ChooseColor         ole32 +       dxgi +       d3d9         )  endif (WINDOWS) diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index fd20f2ad15..8d064ec86c 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -141,7 +141,12 @@ attributedStringInfo getSegments(NSAttributedString *str)      CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);      if(0 == the_err)      { -        CGLDescribeRenderer (info, 0, kCGLRPTextureMemoryMegabytes, &vram_megabytes); +        // The name, uses, and other platform definitions of gGLManager.mVRAM suggest that this is supposed to be total vram in MB, +        // rather than, say, just the texture memory. The two exceptions are: +        // 1. LLAppViewer::getViewerInfo() puts the value in a field labeled "TEXTURE_MEMORY" +        // 2. For years, this present function used kCGLRPTextureMemoryMegabytes +        // Now we use kCGLRPVideoMemoryMegabytes to bring it in line with everything else (except thatone label). +        CGLDescribeRenderer (info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);          CGLDestroyRendererInfo (info);      }      else diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0edf39f6ef..2c538a60c9 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -162,7 +162,10 @@ public:  	virtual F32	getNativeAspectRatio() = 0;  	virtual F32 getPixelAspectRatio() = 0;  	virtual void setNativeAspectRatio(F32 aspect) = 0; -	 + +	// query VRAM usage +	virtual U32 getAvailableVRAMMegabytes() = 0; +  	virtual void beforeDialog() {};	// prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)  	virtual void afterDialog() {};	// undo whatever was done in beforeDialog() diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 410da79623..2f2c0de5bd 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -32,72 +32,79 @@  class LLWindowHeadless : public LLWindow  {  public: -	/*virtual*/ void show() {}; -	/*virtual*/ void hide() {}; -	/*virtual*/ void close() {}; -	/*virtual*/ BOOL getVisible() {return FALSE;}; -	/*virtual*/ BOOL getMinimized() {return FALSE;}; -	/*virtual*/ BOOL getMaximized() {return FALSE;}; -	/*virtual*/ BOOL maximize() {return FALSE;}; -	/*virtual*/ void minimize() {}; -	/*virtual*/ void restore() {}; -	/*virtual*/ BOOL getFullscreen() {return FALSE;}; -	/*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;}; -	/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;}; -	/*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;}; -	/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; -	/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; -	/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; -	/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;}; -    void* createSharedContext()  { return nullptr; } -    void makeContextCurrent(void*)  {} -    void destroySharedContext(void*)  {} -    /*virtual*/ void toggleVSync(bool enable_vsync) { } -    /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; -    /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; +	/*virtual*/ void show() override {} +	/*virtual*/ void hide() override {} +	/*virtual*/ void close() override {} +	/*virtual*/ BOOL getVisible() override {return FALSE;} +	/*virtual*/ BOOL getMinimized() override {return FALSE;} +	/*virtual*/ BOOL getMaximized() override {return FALSE;} +	/*virtual*/ BOOL maximize() override {return FALSE;} +	/*virtual*/ void minimize() override {} +	/*virtual*/ void restore() override {} +	// TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual. +	// Apparently the coder of LLWindowHeadless didn't realize that. Is it a +	// mistake to shadow the base-class method with an LLWindowHeadless +	// override when called on the subclass, yet call the base-class method +	// when indirecting through a polymorphic pointer or reference? +	BOOL getFullscreen() {return FALSE;} +	/*virtual*/ BOOL getPosition(LLCoordScreen *position) override {return FALSE;} +	/*virtual*/ BOOL getSize(LLCoordScreen *size) override {return FALSE;} +	/*virtual*/ BOOL getSize(LLCoordWindow *size) override {return FALSE;} +	/*virtual*/ BOOL setPosition(LLCoordScreen position) override {return FALSE;} +	/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) override {return FALSE;} +	/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) override {return FALSE;} +	/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override {return FALSE;} +    void* createSharedContext() override  { return nullptr; } +    void makeContextCurrent(void*) override  {} +    void destroySharedContext(void*) override  {} +    /*virtual*/ void toggleVSync(bool enable_vsync) override { } +    /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) override {return FALSE;} +    /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) override {return FALSE;}  #if LL_WINDOWS -    /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; } +    /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) override { return FALSE; }  #endif -	/*virtual*/ void showCursor() {}; -	/*virtual*/ void hideCursor() {}; -	/*virtual*/ void showCursorFromMouseMove() {}; -	/*virtual*/ void hideCursorUntilMouseMove() {}; -	/*virtual*/ BOOL isCursorHidden() {return FALSE;}; -	/*virtual*/ void updateCursor() {}; -	//virtual ECursorType getCursor() { return mCurrentCursor; }; -	/*virtual*/ void captureMouse() {}; -	/*virtual*/ void releaseMouse() {}; -	/*virtual*/ void setMouseClipping( BOOL b ) {}; -	/*virtual*/ BOOL isClipboardTextAvailable() {return FALSE; }; -	/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) {return FALSE; }; -	/*virtual*/ BOOL copyTextToClipboard(const LLWString &src) {return FALSE; }; -	/*virtual*/ void flashIcon(F32 seconds) {}; -	/*virtual*/ F32 getGamma() {return 1.0f; }; -	/*virtual*/ BOOL setGamma(const F32 gamma) {return FALSE; }; // Set the gamma -	/*virtual*/ void setFSAASamples(const U32 fsaa_samples) { } -	/*virtual*/ U32 getFSAASamples() { return 0; } -	/*virtual*/ BOOL restoreGamma() {return FALSE; };	// Restore original gamma table (before updating gamma) -	//virtual ESwapMethod getSwapMethod() { return mSwapMethod; } -	/*virtual*/ void gatherInput() {}; -	/*virtual*/ void delayInputProcessing() {}; -	/*virtual*/ void swapBuffers(); +	/*virtual*/ void showCursor() override {} +	/*virtual*/ void hideCursor() override {} +	/*virtual*/ void showCursorFromMouseMove() override {} +	/*virtual*/ void hideCursorUntilMouseMove() override {} +	/*virtual*/ BOOL isCursorHidden() override {return FALSE;} +	/*virtual*/ void updateCursor() override {} +	//virtual ECursorType getCursor() override { return mCurrentCursor; } +	/*virtual*/ void captureMouse() override {} +	/*virtual*/ void releaseMouse() override {} +	/*virtual*/ void setMouseClipping( BOOL b ) override {} +	/*virtual*/ BOOL isClipboardTextAvailable() override {return FALSE; } +	/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) override {return FALSE; } +	/*virtual*/ BOOL copyTextToClipboard(const LLWString &src) override {return FALSE; } +	/*virtual*/ void flashIcon(F32 seconds) override {} +	/*virtual*/ F32 getGamma() override {return 1.0f; } +	/*virtual*/ BOOL setGamma(const F32 gamma) override {return FALSE; } // Set the gamma +	/*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { } +	/*virtual*/ U32 getFSAASamples() override { return 0; } +	/*virtual*/ BOOL restoreGamma() override {return FALSE; }	// Restore original gamma table (before updating gamma) +	//virtual ESwapMethod getSwapMethod() override { return mSwapMethod; } +	/*virtual*/ void gatherInput() override {} +	/*virtual*/ void delayInputProcessing() override {} +	/*virtual*/ void swapBuffers() override;      // handy coordinate space conversion routines -	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) { return FALSE; }; -	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) { return FALSE; }; -	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) { return FALSE; }; -	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) { return FALSE; }; -	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) { return FALSE; }; -	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) { return FALSE; }; +	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return FALSE; } +	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return FALSE; } +	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override { return FALSE; } +	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override { return FALSE; } +	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override { return FALSE; } +	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override { return FALSE; } -	/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; }; -	/*virtual*/ F32	getNativeAspectRatio() { return 1.0f; }; -	/*virtual*/ F32 getPixelAspectRatio() { return 1.0f; }; -	/*virtual*/ void setNativeAspectRatio(F32 ratio) {} +	/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; } +	/*virtual*/ F32	getNativeAspectRatio() override { return 1.0f; } +	/*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; } +	/*virtual*/ void setNativeAspectRatio(F32 ratio) override {} -	/*virtual*/ void *getPlatformWindow() { return 0; }; -	/*virtual*/ void bringToFront() {}; +    U32 getAvailableVRAMMegabytes() override { return 4096; } + +	/*virtual*/ void *getPlatformWindow() override { return 0; } +	/*virtual*/ void bringToFront() override {}  	LLWindowHeadless(LLWindowCallbacks* callbacks,  		const std::string& title, const std::string& name, @@ -113,12 +120,12 @@ private:  class LLSplashScreenHeadless : public LLSplashScreen  {  public: -	LLSplashScreenHeadless() {}; -	virtual ~LLSplashScreenHeadless() {}; +	LLSplashScreenHeadless() {} +	virtual ~LLSplashScreenHeadless() {} -	/*virtual*/ void showImpl() {}; -	/*virtual*/ void updateImpl(const std::string& mesg) {}; -	/*virtual*/ void hideImpl() {}; +	/*virtual*/ void showImpl() override {} +	/*virtual*/ void updateImpl(const std::string& mesg) override {} +	/*virtual*/ void hideImpl() override {}  }; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index bc4f07941b..4bcb9b3aef 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1222,6 +1222,16 @@ F32 LLWindowMacOSX::getPixelAspectRatio()  	return 1.f;  } +U32 LLWindowMacOSX::getAvailableVRAMMegabytes() { +    // MTL (and MoltenVK) has some additional gpu data, such as recommendedMaxWorkingSetSize and currentAllocatedSize. +    // But these are not available for OpenGL and/or our current mimimum OS version. +    // So we will estimate. +    static const U32 mb = 1024*1024; +    // We're asked for total available gpu memory, but we only have allocation info on texture usage. So estimate by doubling that. +    static const U32 total_factor = 2; // estimated total/textures +    return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb); +} +  //static SInt32 oldWindowLevel;  // MBW -- XXX -- There's got to be a better way than this.  Find it, please... diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index b0f339e1db..0f316f1ddf 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -100,6 +100,9 @@ public:  	F32 getPixelAspectRatio() override;  	void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } +	// query VRAM usage +    /*virtual*/ U32 getAvailableVRAMMegabytes() override; +  	void beforeDialog() override;  	void afterDialog() override; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 1f23040260..553507bc0c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -47,6 +47,9 @@  #include "llglslshader.h"  #include "llthreadsafequeue.h"  #include "stringize.h" +#include "llframetimer.h" +#include "commoncontrol.h" // TODO: Remove after testing +#include "llsd.h" // TODO: Remove after testing  // System includes  #include <commdlg.h> @@ -61,6 +64,9 @@  #include <sstream>  #include <utility>                  // std::pair +#include <d3d9.h> +#include <dxgi1_4.h> +  // Require DirectInput version 8  #define DIRECTINPUT_VERSION 0x0800 @@ -347,6 +353,20 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool      void run() override; +    // initialzie DXGI adapter (for querying available VRAM) +    void initDX(); +     +    // initialize D3D (if DXGI cannot be used) +    void initD3D(); + +    // call periodically to update available VRAM +    void updateVRAMUsage(); + +    U32 getAvailableVRAMMegabytes() +    { +        return mAvailableVRAM; +    } +      /// called by main thread to post work to this window thread      template <typename CALLABLE>      void post(CALLABLE&& func) @@ -395,6 +415,15 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool      void gatherInput();      HWND mWindowHandle = NULL;      HDC mhDC = 0; + +    // best guess at available video memory in MB +    std::atomic<U32> mAvailableVRAM; + +    bool mTryUseDXGIAdapter; // TODO: Remove after testing +    IDXGIAdapter3* mDXGIAdapter = nullptr; +    bool mTryUseD3DDevice; // TODO: Remove after testing +    LPDIRECT3D9 mD3D = nullptr; +    LPDIRECT3DDEVICE9 mD3DDevice = nullptr;  }; @@ -4531,12 +4560,24 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()  	return std::vector<std::string>();  } +U32 LLWindowWin32::getAvailableVRAMMegabytes() +{ +    return mWindowThread ? mWindowThread->getAvailableVRAMMegabytes() : 0; +}  #endif // LL_WINDOWS  inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()      : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE)  { +    const LLSD skipDXGI{ LL::CommonControl::get("Global", "DisablePrimaryGraphicsMemoryAccounting") }; // TODO: Remove after testing +    LL_WARNS() << "DisablePrimaryGraphicsMemoryAccounting: " << skipDXGI << ", as boolean: " << skipDXGI.asBoolean() << LL_ENDL; +    mTryUseDXGIAdapter = !skipDXGI.asBoolean(); +    LL_WARNS() << "mTryUseDXGIAdapter: " << mTryUseDXGIAdapter << LL_ENDL; +    const LLSD skipD3D{ LL::CommonControl::get("Global", "DisableSecondaryGraphicsMemoryAccounting") }; // TODO: Remove after testing +    LL_WARNS() << "DisableSecondaryGraphicsMemoryAccounting: " << skipD3D << ", as boolean: " << skipD3D.asBoolean() << LL_ENDL; +    mTryUseD3DDevice = !skipD3D.asBoolean(); +    LL_WARNS() << "mTryUseD3DDevice: " << mTryUseD3DDevice << LL_ENDL;      ThreadPool::start();  } @@ -4586,17 +4627,216 @@ private:      std::string mPrev;  }; +// Print hardware debug info about available graphics adapters in ordinal order +void debugEnumerateGraphicsAdapters() +{ +    LL_INFOS("Window") << "Enumerating graphics adapters..." << LL_ENDL; + +    IDXGIFactory1* factory; +    HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory); +    if (FAILED(res) || !factory) +    { +        LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL; +    } +    else +    { +        UINT graphics_adapter_index = 0; +        IDXGIAdapter3* dxgi_adapter; +        while (true) +        { +            res = factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&dxgi_adapter)); +            if (FAILED(res)) +            { +                if (graphics_adapter_index == 0) +                { +                    LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL; +                } +                else +                { +                    LL_INFOS("Window") << "Done enumerating graphics adapters" << LL_ENDL; +                } +            } +            else +            { +                DXGI_ADAPTER_DESC desc; +                dxgi_adapter->GetDesc(&desc); +                std::wstring description_w((wchar_t*)desc.Description); +                std::string description(description_w.begin(), description_w.end()); +                LL_INFOS("Window") << "Graphics adapter index: " << graphics_adapter_index << ", " +                    << "Description: " << description << ", " +                    << "DeviceId: " << desc.DeviceId << ", " +                    << "SubSysId: " << desc.SubSysId << ", " +                    << "AdapterLuid: " << desc.AdapterLuid.HighPart << "_" << desc.AdapterLuid.LowPart << ", " +                    << "DedicatedVideoMemory: " << desc.DedicatedVideoMemory / 1024 / 1024 << ", " +                    << "DedicatedSystemMemory: " << desc.DedicatedSystemMemory / 1024 / 1024 << ", " +                    << "SharedSystemMemory: " << desc.SharedSystemMemory / 1024 / 1024 << LL_ENDL; +            } + +            if (dxgi_adapter) +            { +                dxgi_adapter->Release(); +                dxgi_adapter = NULL; +            } +            else +            { +                break; +            } + +            graphics_adapter_index++; +        } +    } + +    if (factory) +    { +        factory->Release(); +    } +} + +void LLWindowWin32::LLWindowWin32Thread::initDX() +{ +    if (mDXGIAdapter == NULL && mTryUseDXGIAdapter) +    { +        debugEnumerateGraphicsAdapters(); + +        IDXGIFactory4* pFactory = nullptr; + +        HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory); + +        if (FAILED(res)) +        { +            LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL; +        } +        else +        { +            res = pFactory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&mDXGIAdapter)); +            if (FAILED(res)) +            { +                LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL; +            } +            else +            { +                LL_INFOS() << "EnumAdapters success" << LL_ENDL; +            } +        } + +        if (pFactory) +        { +            pFactory->Release(); +        } +    } +} + +void LLWindowWin32::LLWindowWin32Thread::initD3D() +{ +    if (mDXGIAdapter == NULL && mD3DDevice == NULL && mTryUseD3DDevice && mWindowHandle != 0) +    { +        mD3D = Direct3DCreate9(D3D_SDK_VERSION); +         +        D3DPRESENT_PARAMETERS d3dpp; + +        ZeroMemory(&d3dpp, sizeof(d3dpp)); +        d3dpp.Windowed = TRUE; +        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + +        HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); +         +        if (FAILED(res)) +        { +            LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL; +        } +        else +        { +            LL_INFOS() << "(fallback) CreateDevice success" << LL_ENDL; +        } +    } +} + +void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() +{ +    LL_PROFILE_ZONE_SCOPED; +    if (mDXGIAdapter != nullptr) +    { +        // NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware +        //  It doesn't make sense, but please don't refactor it to make sense. -- davep + +        DXGI_QUERY_VIDEO_MEMORY_INFO info; +        mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); + +#if 0 // debug 0 budget and 0 CU +        info.Budget = 0; +        info.CurrentUsage = 0; +#endif + +        U32 budget_mb = info.Budget / 1024 / 1024; +        U32 afr_mb = info.AvailableForReservation / 1024 / 1024; +        // correct for systems that misreport budget +        if (budget_mb == 0) +        {  +            // fall back to available for reservation clamped between 512MB and 2GB +            budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048); +        } + +        U32 cu_mb = info.CurrentUsage / 1024 / 1024; + +        // get an estimated usage based on texture bytes allocated +        U32 eu_mb = LLImageGL::getTextureBytesAllocated() * 2 / 1024 / 1024; + +        if (cu_mb == 0) +        { // current usage is sometimes unreliable on Intel GPUs, fall back to estimated usage +            cu_mb = llmax((U32)1, eu_mb); +        } +        F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb; + +        U32 target_mb = info.Budget / 1024 / 1024; + +        if (target_mb > 4096)  // if 4GB are installed, try to leave 2GB free  +        { +            target_mb -= 2048; +        } +        else // if less than 4GB are installed, try not to use more than half of it +        { +            target_mb /= 2; +        } + +        mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0; + +        LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024 +            << "\nBudget: " << info.Budget / 1024 / 1024 +            << "\nCR: " << info.CurrentReservation / 1024 / 1024 +            << "\nCU: " << info.CurrentUsage / 1024 / 1024 +            << "\nEU: " << eu_mb << llformat(" (%.2f)", eu_error) +            << "\nTU: " << target_mb +            << "\nAM: " << mAvailableVRAM << LL_ENDL; + +        /*mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info); +        LL_INFOS("Window") << "\nNon-Local\nAFR: " << info.AvailableForReservation / 1024 / 1024 +            << "\nBudget: " << info.Budget / 1024 / 1024 +            << "\nCR: " << info.CurrentReservation / 1024 / 1024 +            << "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;*/ +    } +    else if (mD3DDevice != NULL) +    { // fallback to D3D9 +        mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024; +    } +} +  void LLWindowWin32::LLWindowWin32Thread::run()  {      sWindowThreadId = std::this_thread::get_id();      LogChange logger("Window"); +    initDX(); +      while (! getQueue().done())      {          LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;          if (mWindowHandle != 0)          { +            // lazily call initD3D inside this loop to catch when mWindowHandle has been set +            // *TODO: Shutdown if this fails when mWindowHandle exists +            initD3D(); +              MSG msg;              BOOL status;              if (mhDC == 0) @@ -4629,6 +4869,13 @@ void LLWindowWin32::LLWindowWin32Thread::run()              getQueue().runPending();          } +        // update available vram once every 3 seconds +        static LLFrameTimer vramTimer; +        if (vramTimer.getElapsedTimeF32() > 3.f) +        { +            updateVRAMUsage(); +            vramTimer.reset(); +        }  #if 0          {              LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep"); @@ -4637,6 +4884,26 @@ void LLWindowWin32::LLWindowWin32Thread::run()          }  #endif      } + +    //clean up DXGI/D3D resources +    if (mDXGIAdapter) +    { +        mDXGIAdapter->Release(); +        mDXGIAdapter = nullptr; +    } + +    if (mD3DDevice) +    { +        mD3DDevice->Release(); +        mD3DDevice = nullptr; +    } + +    if (mD3D) +    { +        mD3D->Release(); +        mD3D = nullptr; +    } +  }  void LLWindowWin32::post(const std::function<void()>& func) diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index b391acc12d..bd53b3e92a 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -108,7 +108,9 @@ public:  	/*virtual*/ F32 getPixelAspectRatio();  	/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } -	/*virtual*/	BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b ); +    U32 getAvailableVRAMMegabytes() override; +	 +    /*virtual*/	BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );  	/*virtual*/ void *getPlatformWindow();  	/*virtual*/ void bringToFront(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b67bc91277..39baa23778 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -236,12 +236,14 @@ set(viewer_SOURCE_FILES      llfloatercamera.cpp      llfloatercamerapresets.cpp      llfloaterchatvoicevolume.cpp +    llfloaterclassified.cpp      llfloatercolorpicker.cpp      llfloaterconversationlog.cpp      llfloaterconversationpreview.cpp      llfloatercreatelandmark.cpp      llfloaterdeleteprefpreset.cpp      llfloaterdestinations.cpp +    llfloaterdisplayname.cpp      llfloatereditenvironmentbase.cpp      llfloatereditextdaycycle.cpp      llfloaterenvironmentadjust.cpp @@ -297,9 +299,11 @@ set(viewer_SOURCE_FILES      llfloaterpay.cpp      llfloaterperms.cpp      llfloaterpostprocess.cpp +    llfloaterprofile.cpp      llfloaterpreference.cpp      llfloaterpreferenceviewadvanced.cpp      llfloaterpreviewtrash.cpp +    llfloaterprofiletexture.cpp      llfloaterproperties.cpp      llfloaterregiondebugconsole.cpp      llfloaterregioninfo.cpp @@ -321,7 +325,6 @@ set(viewer_SOURCE_FILES      llfloatertelehub.cpp      llfloatertestinspectors.cpp      llfloatertestlistview.cpp -    llfloatertexturefetchdebugger.cpp      llfloatertools.cpp      llfloatertopobjects.cpp      llfloatertos.cpp @@ -332,7 +335,6 @@ set(viewer_SOURCE_FILES      llfloatervoiceeffect.cpp      llfloatervoicevolume.cpp      llfloaterwebcontent.cpp -    llfloaterwebprofile.cpp      llfloaterwhitelistentry.cpp      llfloaterwindowsize.cpp      llfloaterworldmap.cpp @@ -394,6 +396,7 @@ set(viewer_SOURCE_FILES      lllistcontextmenu.cpp      lllistview.cpp      lllocalbitmaps.cpp +    lllocalgltfmaterials.cpp      lllocationhistory.cpp      lllocationinputctrl.cpp      lllogchat.cpp @@ -480,7 +483,6 @@ set(viewer_SOURCE_FILES      llpanelmediasettingsgeneral.cpp      llpanelmediasettingspermissions.cpp      llpanelmediasettingssecurity.cpp -    llpanelme.cpp      llpanelnearbymedia.cpp      llpanelobject.cpp      llpanelobjectinventory.cpp @@ -490,8 +492,6 @@ set(viewer_SOURCE_FILES      llpanelpeople.cpp      llpanelpeoplemenus.cpp      llpanelpermissions.cpp -    llpanelpick.cpp -    llpanelpicks.cpp      llpanelplaceinfo.cpp      llpanelplaceprofile.cpp      llpanelplaces.cpp @@ -500,6 +500,8 @@ set(viewer_SOURCE_FILES      llpanelpresetspulldown.cpp      llpanelprimmediacontrols.cpp      llpanelprofile.cpp +    llpanelprofileclassifieds.cpp +    llpanelprofilepicks.cpp      llpanelsnapshot.cpp      llpanelsnapshotinventory.cpp      llpanelsnapshotlocal.cpp @@ -607,6 +609,7 @@ set(viewer_SOURCE_FILES      lltextureinfodetails.cpp      lltexturestats.cpp      lltextureview.cpp +    lltinygltfhelper.cpp      lltoast.cpp      lltoastalertpanel.cpp      lltoastgroupnotifypanel.cpp @@ -663,6 +666,7 @@ set(viewer_SOURCE_FILES      llviewercontrol.cpp      llviewercontrollistener.cpp      llviewerdisplay.cpp +    llviewerdisplayname.cpp      llviewerfloaterreg.cpp      llviewerfoldertype.cpp      llviewergenericmessage.cpp @@ -877,12 +881,14 @@ set(viewer_HEADER_FILES      llfloatercamerapresets.h      llfloatercamera.h      llfloaterchatvoicevolume.h +    llfloaterclassified.h      llfloatercolorpicker.h      llfloaterconversationlog.h      llfloaterconversationpreview.h      llfloatercreatelandmark.h      llfloaterdeleteprefpreset.h      llfloaterdestinations.h +    llfloaterdisplayname.h      llfloatereditenvironmentbase.h      llfloatereditextdaycycle.h      llfloaterenvironmentadjust.h @@ -941,9 +947,11 @@ set(viewer_HEADER_FILES      llfloaterpay.h      llfloaterperms.h      llfloaterpostprocess.h +    llfloaterprofile.h      llfloaterpreference.h      llfloaterpreferenceviewadvanced.h      llfloaterpreviewtrash.h +    llfloaterprofiletexture.h      llfloaterproperties.h      llfloaterregiondebugconsole.h      llfloaterregioninfo.h @@ -965,7 +973,6 @@ set(viewer_HEADER_FILES      llfloatertelehub.h      llfloatertestinspectors.h      llfloatertestlistview.h -    llfloatertexturefetchdebugger.h      llfloatertools.h      llfloatertopobjects.h      llfloatertos.h @@ -976,7 +983,6 @@ set(viewer_HEADER_FILES      llfloatervoiceeffect.h      llfloatervoicevolume.h      llfloaterwebcontent.h -    llfloaterwebprofile.h      llfloaterwhitelistentry.h      llfloaterwindowsize.h      llfloaterworldmap.h @@ -1036,6 +1042,7 @@ set(viewer_HEADER_FILES      lllistcontextmenu.h      lllistview.h      lllocalbitmaps.h +    lllocalgltfmaterials.h      lllocationhistory.h      lllocationinputctrl.h      lllogchat.h @@ -1114,7 +1121,6 @@ set(viewer_HEADER_FILES      llpanelmediasettingsgeneral.h      llpanelmediasettingspermissions.h      llpanelmediasettingssecurity.h -    llpanelme.h      llpanelnearbymedia.h      llpanelobject.h      llpanelobjectinventory.h @@ -1124,8 +1130,6 @@ set(viewer_HEADER_FILES      llpanelpeople.h      llpanelpeoplemenus.h      llpanelpermissions.h -    llpanelpick.h -    llpanelpicks.h      llpanelplaceinfo.h      llpanelplaceprofile.h      llpanelplaces.h @@ -1134,6 +1138,8 @@ set(viewer_HEADER_FILES      llpanelpresetspulldown.h      llpanelprimmediacontrols.h      llpanelprofile.h +    llpanelprofileclassifieds.h +    llpanelprofilepicks.h      llpanelsnapshot.h      llpanelteleporthistory.h      llpaneltiptoast.h @@ -1240,6 +1246,7 @@ set(viewer_HEADER_FILES      lltextureinfodetails.h      lltexturestats.h      lltextureview.h +    lltinygltfhelper.h      lltoast.h      lltoastalertpanel.h      lltoastgroupnotifypanel.h @@ -1298,6 +1305,7 @@ set(viewer_HEADER_FILES      llviewercontrol.h      llviewercontrollistener.h      llviewerdisplay.h +    llviewerdisplayname.h      llviewerfloaterreg.h      llviewerfoldertype.h      llviewergenericmessage.h @@ -2515,6 +2523,19 @@ if (LL_TESTS)      "${test_libs}"      ) +  set(llviewercontrollistener_test_sources +    llviewercontrollistener.cpp +    ../llxml/llcontrol.cpp +    ../llxml/llxmltree.cpp +    ../llxml/llxmlparser.cpp +    ../llcommon/commoncontrol.cpp +    ) + +  LL_ADD_INTEGRATION_TEST(llviewercontrollistener +    "${llviewercontrollistener_test_sources}" +    "${test_libs}" +    ) +    LL_ADD_INTEGRATION_TEST(llviewernetwork       llviewernetwork.cpp      "${test_libs}" diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 28179fc1f5..66ce77b7ea 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.2 +7.0.0 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 3dfe3f6634..2644f5f449 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -167,10 +167,8 @@             icon="Command_Picks_Icon"             label_ref="Command_Picks_Label"             tooltip_ref="Command_Picks_Tooltip" -           execute_function="Floater.ToggleOrBringToFront" -           execute_parameters="picks" -           is_running_function="Floater.IsOpen" -           is_running_parameters="picks" +           execute_function="Avatar.TogglePicks" +           is_running_function="Avatar.IsPicksTabOpen"             />    <command name="places"             available_in_toybox="true" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8a86faa18d..cd33690075 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3398,6 +3398,29 @@        <key>Value</key>        <integer>0</integer>      </map> +    <!-- TODO: Remove settings keys DisablePrimaryGraphicsMemoryAccounting and DisableSecondaryGraphicsMemoryAccounting after testing, and code that references them --> +    <key>DisablePrimaryGraphicsMemoryAccounting</key> +    <map> +      <key>Comment</key> +      <string>Disable the first method used to detect GPU memory use</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>DisableSecondaryGraphicsMemoryAccounting</key> +    <map> +      <key>Comment</key> +      <string>Disable the second method used to detect GPU memory use, used as a fallback when the first method fails</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>DisableTextHyperlinkActions</key>      <map>        <key>Comment</key> @@ -3924,7 +3947,7 @@          <key>Type</key>          <string>F32</string>          <key>Value</key> -        <real>0.1</real> +        <real>1.0</real>      </map>      <key>QueueInventoryFetchTimeout</key>      <map> @@ -10313,6 +10336,17 @@      <key>Value</key>      <integer>1</integer>    </map> +  <key>RenderReflectionProbeCount</key> +  <map> +    <key>Comment</key> +    <string>Number of reflection probes (maximum is 256, requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>S32</string> +    <key>Value</key> +    <integer>256</integer> +  </map>    <key>RenderReflectionProbeDrawDistance</key>    <map> @@ -10447,17 +10481,6 @@        <key>Value</key>        <real>12.0</real>      </map> -    <key>RenderTextureMemoryMultiple</key> -    <map> -      <key>Comment</key> -      <string>Multiple of texture memory value to use (should fit: 0 < value <= 1.0)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>F32</string> -      <key>Value</key> -      <real>1.0</real> -    </map>      <key>RenderTrackerBeacon</key>      <map>        <key>Comment</key> @@ -12537,17 +12560,6 @@        <key>Value</key>        <real>20.0</real>      </map> -    <key>TexelPixelRatio</key> -    <map> -      <key>Comment</key> -      <string>texel pixel ratio = texel / pixel</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>F32</string> -      <key>Value</key> -      <real>1.0</real> -    </map>      <key>TextureCameraMotionThreshold</key>      <map>        <key>Comment</key> @@ -12647,17 +12659,6 @@        <key>Value</key>        <integer>0</integer>      </map> -    <key>TextureFetchDebuggerEnabled</key> -    <map> -      <key>Comment</key> -      <string>Enable the texture fetching debugger if set</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>0</integer> -    </map>      <key>TextureFetchMinTimeToLog</key>      <map>        <key>Comment</key> @@ -12680,21 +12681,10 @@      <key>Value</key>      <real>0.0</real>    </map> -    <key>TextureFetchSource</key> -    <map> -      <key>Comment</key> -      <string>Debug use: Source to fetch textures</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>0</integer> -    </map> -    <key>TextureFetchUpdateHighPriority</key> +    <key>TextureFetchUpdateMinCount</key>      <map>        <key>Comment</key> -      <string>Number of high priority textures to update per frame</string> +      <string>Minimum number of textures to update per frame</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -12702,91 +12692,14 @@        <key>Value</key>        <integer>32</integer>      </map> -    <key>TextureFetchUpdateMaxMediumPriority</key> -    <map> -      <key>Comment</key> -      <string>Maximum number of medium priority textures to update per frame</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>256</integer> -    </map> -    <key>TextureFetchUpdateMinMediumPriority</key> -    <map> -      <key>Comment</key> -      <string>Minimum number of medium priority textures to update per frame</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>32</integer> -    </map> -    <key>TextureFetchUpdatePriorityThreshold</key> -    <map> -      <key>Comment</key> -      <string>Threshold under which textures will be considered too low priority and skipped for update</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>F32</string> -      <key>Value</key> -      <real>0.0</real> -    </map> -    <key>TextureFetchUpdateSkipLowPriority</key> -    <map> -      <key>Comment</key> -      <string>Flag indicating if we want to skip textures with too low of a priority</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>0</integer> -    </map> -    <key>TextureFetchUpdatePriorities</key> -    <map> -      <key>Comment</key> -      <string>Number of priority texture to update per frame</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>32</integer> -    </map> -    <key>TextureListFetchingThreshold</key> -    <map> -      <key>Comment</key> -      <string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>F32</string> -      <key>Value</key> -      <real>0.97</real> -    </map>      <key>TextureLoadFullRes</key>      <map>        <key>Comment</key>        <string>If TRUE, always load textures at full resolution (discard = 0)</string>        <key>Persist</key> -      <integer>0</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>0</integer> -    </map> -    <key>TextureMemory</key> -    <map> -      <key>Comment</key> -      <string>Amount of memory to use for textures in MB (0 = autodetect)</string> -      <key>Persist</key>        <integer>1</integer>        <key>Type</key> -      <string>S32</string> +      <string>Boolean</string>        <key>Value</key>        <integer>0</integer>      </map> @@ -12856,7 +12769,9 @@        <key>Value</key>        <map>          <key>General</key> -        <integer>4</integer> +        <integer>1</integer> +        <key>ImageDecode</key> +        <integer>9</integer>        </map>      </map>      <key>ThrottleBandwidthKBPS</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index ad3a93128d..68a57d12f0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -34,6 +34,7 @@ uniform vec3 proj_p; //plane projection is emitting from (in screen space)  uniform float proj_focus; // distance from plane to begin blurring  uniform float proj_lod  ; // (number of mips in proj map)  uniform float proj_range; // range between near clip and far clip plane of projection +uniform float proj_ambiance;  // light params  uniform vec3 color; // light_color @@ -43,9 +44,21 @@ uniform mat4 inv_proj;  uniform vec2 screen_res;  const float M_PI = 3.14159265; +const float ONE_OVER_PI = 0.3183098861;  vec3 srgb_to_linear(vec3 cs); +float calcLegacyDistanceAttenuation(float distance, float falloff) +{ +    float dist_atten = 1.0 - clamp((distance + falloff)/(1.0 + falloff), 0.0, 1.0); +    dist_atten *= dist_atten; + +    // Tweak falloff slightly to match pre-EEP attenuation +    // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit +    dist_atten *= 2.0; +    return dist_atten; +} +  // In:  //   lv  unnormalized surface to light vector  //   n   normal of the surface @@ -146,6 +159,18 @@ float getDepth(vec2 pos_screen)      return depth;  } +vec4 getTexture2DLodAmbient(vec2 tc, float lod) +{ +    vec4 ret = texture2DLod(projectionMap, tc, lod); +    ret.rgb = srgb_to_linear(ret.rgb); + +    vec2 dist = tc-vec2(0.5); +    float d = dot(dist,dist); +    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + +    return ret; +} +  vec4 getTexture2DLodDiffuse(vec2 tc, float lod)  {      vec4 ret = texture2DLod(projectionMap, tc, lod); @@ -160,8 +185,24 @@ vec4 getTexture2DLodDiffuse(vec2 tc, float lod)      return ret;  } -// Returns projected light in Linear +// lit     This is set by the caller: if (nl > 0.0) { lit = attenuation * nl * noise; }  // Uses: +//   color   Projected spotlight color +vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv) +{ +    vec4 amb_plcol = getTexture2DLodAmbient(projected_uv, proj_lod); +    vec3 amb_rgb   = amb_plcol.rgb * amb_plcol.a; + +    amb_da += proj_ambiance; +    amb_da += (nl*nl*0.5+0.5) * proj_ambiance; +    amb_da *= attenuation * noise; +    amb_da = min(amb_da, 1.0-lit); + +    return (amb_da * color.rgb * amb_rgb); +} + +// Returns projected light in Linear +// Uses global spotlight color:  //  color  // NOTE: projected.a will be pre-multiplied with projected.rgb  vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv) @@ -251,8 +292,41 @@ vec2 getScreenXY(vec4 clip)      return screen;  } +// Color utils + +vec3 colorize_dot(float x) +{ +    if (x > 0.0) return vec3( 0, x, 0 ); +    if (x < 0.0) return vec3(-x, 0, 0 ); +                 return vec3( 0, 0, 1 ); +} + +vec3 hue_to_rgb(float hue) +{ +    if (hue > 1.0) return vec3(0.5); +    vec3 rgb = abs(hue * 6. - vec3(3, 2, 4)) * vec3(1, -1, -1) + vec3(-1, 2, 2); +    return clamp(rgb, 0.0, 1.0); +} +  // PBR Utils +// ior Index of Refraction, normally 1.5 +// returns reflect0 +float calcF0(float ior) +{ +    float f0 = (1.0 - ior) / (1.0 + ior); +    return f0 * f0; +} + +vec3 fresnel(float vh, vec3 f0, vec3 f90 ) +{ +    float x  = 1.0 - abs(vh); +    float x2 = x*x; +    float x5 = x2*x2*x; +    vec3  fr = f0 + (f90 - f0)*x5; +    return fr; +} +  vec3 fresnelSchlick( vec3 reflect0, vec3 reflect90, float vh)  {      return reflect0 + (reflect90 - reflect0) * pow(clamp(1.0 - vh, 0.0, 1.0), 5.0); @@ -330,42 +404,68 @@ float D_GGX( float nh, float alphaRough )  }  // NOTE: This is different from the GGX texture +// See: +//   Real Time Rendering, 4th Edition +//   Page 341 +//   Equation 9.43 +// Also see: +//   https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg) +//   4.4.2 Geometric Shadowing (specular G)  float V_GGX( float nl, float nv, float alphaRough )  { +#if 1 +    // Note: When roughness is zero, has discontuinity in the bottom hemisphere      float rough2 = alphaRough * alphaRough;      float ggxv   = nl * sqrt(nv * nv * (1.0 - rough2) + rough2);      float ggxl   = nv * sqrt(nl * nl * (1.0 - rough2) + rough2); +      float ggx    = ggxv + ggxl;      if (ggx > 0.0)      {          return 0.5 / ggx;      }      return 0.0; +#else +    // See: smithVisibility_GGXCorrelated, V_SmithCorrelated, etc. +    float rough2 = alphaRough * alphaRough; +    float ggxv = nl * sqrt(nv * (nv - rough2 * nv) + rough2); +    float ggxl = nv * sqrt(nl * (nl - rough2 * nl) + rough2); +    return 0.5 / (ggxv + ggxl); +#endif +  } +// NOTE: Assumes a hard-coded IOR = 1.5  void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight )  {      float metal      = packedORM.b; -          c_diff     = mix(diffuse.rgb, vec3(0), metal); +          c_diff     = mix(diffuse, vec3(0), metal);      float IOR        = 1.5;                                // default Index Of Refraction 1.5 (dielectrics)            reflect0   = vec3(0.04);                         // -> incidence reflectance 0.04 -          reflect0   = mix( reflect0, diffuse.rgb, metal); // reflect at 0 degrees +//        reflect0   = vec3(calcF0(IOR)); +          reflect0   = mix(reflect0, diffuse, metal);      // reflect at 0 degrees            reflect90  = vec3(1);                            // reflect at 90 degrees            specWeight = 1.0; -    float perceptualRough = packedORM.g; +    // When roughness is zero blender shows a tiny specular +    float perceptualRough = max(packedORM.g, 0.1);            alphaRough      = perceptualRough * perceptualRough;  } +vec3 BRDFDiffuse(vec3 color) +{ +    return color * ONE_OVER_PI; +} +  vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh )  { -    return (1.0 - specWeight * fresnelSchlick( reflect0, reflect90, vh)) * (c_diff / M_PI); +    return (1.0 - specWeight * fresnelSchlick( reflect0, reflect90, vh)) * BRDFDiffuse(c_diff);  }  vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRough, float specWeight, float vh, float nl, float nv, float nh )  { -    vec3  fresnel    = fresnelSchlick( reflect0, reflect90, vh ); -    float vis       = V_GGX( nl, nv, alphaRough ); -    float d         = D_GGX( nh, alphaRough ); +    vec3 fresnel    = fresnelSchlick( reflect0, reflect90, vh ); // Fresnel +    float vis       = V_GGX( nl, nv, alphaRough );               // Visibility +    float d         = D_GGX( nh, alphaRough );                   // Distribution      return specWeight * fresnel * vis * d;  } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 7e29ada205..a1cab87092 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -1,5 +1,5 @@  /**  - * @file bumpV.glsl + * @file materialV.glsl   *   * $LicenseInfo:firstyear=2007&license=viewerlgpl$   * Second Life Viewer Source Code diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index e6f2c9d02b..b5c38bba04 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -31,6 +31,7 @@  #define DEBUG_VERTEX        0  #define DEBUG_NORMAL_MAP    0 // Output packed normal map "as is" to diffuse  #define DEBUG_NORMAL_OUT    0 // Output unpacked normal to diffuse +#define DEBUG_ORM           0 // Output Occlusion Roughness Metal "as is" to diffuse  #define DEBUG_POSITION      0  uniform sampler2D diffuseMap;  //always in sRGB space @@ -103,15 +104,16 @@ void main()      tnorm = normalize(tnorm.xyz);      norm.xyz = normalize(tnorm.xyz); +      // RGB = Occlusion, Roughness, Metal -    // default values -    //   occlusion ? -    //   roughness 1.0 -    //   metal     1.0 +    // default values, see LLViewerTexture::sDefaultPBRORMImagep +    //   occlusion 1.0 +    //   roughness 0.0 +    //   metal     0.0  #ifdef HAS_SPECULAR_MAP      vec3 spec = texture2D(specularMap, vary_texcoord2.xy).rgb;  #else -    vec3 spec = vec3(1,1,1); +    vec3 spec = vec3(1,0,0);  #endif      spec.g *= roughnessFactor; @@ -139,6 +141,9 @@ void main()  #if DEBUG_NORMAL_OUT      col.rgb = vary_normal;  #endif +#if DEBUG_ORM +    col.rgb = linear_to_srgb(spec); +#endif  #if DEBUG_POSITION      col.rgb = vary_position.xyz;  #endif diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl index 82338069a8..a2606ed771 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl @@ -78,24 +78,23 @@ VARYING vec2 vary_texcoord0;  void main()  { -	vec4 pos4 = vec4(position,1.0);  #ifdef HAS_SKIN  	mat4 mat = getObjectSkinnedTransform();  	mat = modelview_matrix * mat; -	vec3 pos = (mat*pos4).xyz; +	vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;  #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)  	vary_position = pos;  #endif -	gl_Position = projection_matrix*pos4; +	gl_Position = projection_matrix*vec4(pos,1.0);  #else  	//transform vertex +	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);  -	gl_Position = modelview_projection_matrix * pos4;  #endif  	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl index 699a9c0276..c7c241b76e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl @@ -27,7 +27,10 @@  /*[EXTRA_CODE_HERE]*/ -#define DEBUG_PBR_LIGHT_TYPE      0 +#define DEBUG_ANY_LIGHT_TYPE      0 // Output red light cone +#define DEBUG_PBR_LIGHT_TYPE      0 // Output PBR objects in red +#define DEBUG_LEG_LIGHT_TYPE      0 // Show Legacy objects in red +#define DEBUG_POINT_ZERO          0 // Output zero for point lights  #ifdef DEFINE_GL_FRAGCOLOR  out vec4 frag_color; @@ -57,6 +60,7 @@ VARYING vec4 vary_fragcoord;  vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );  vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );  void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); +float calcLegacyDistanceAttenuation(float distance, float falloff);  vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);  vec4 getPosition(vec2 pos_screen);  vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); @@ -64,6 +68,9 @@ vec2 getScreenXY(vec4 clip);  void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );  vec3 srgb_to_linear(vec3 c); +// Util +vec3 hue_to_rgb(float hue); +  void main()  {  #if defined(LOCAL_LIGHT_KILL) @@ -72,6 +79,10 @@ void main()      vec3 final_color = vec3(0, 0, 0);      vec2 tc          = getScreenXY(vary_fragcoord);      vec3 pos         = getPosition(tc).xyz; +    if (pos.z < far_z) +    { +        discard; +    }      float envIntensity; // not used for this shader      vec3 n; @@ -96,33 +107,29 @@ void main()          for (int light_idx = 0; light_idx < LIGHT_COUNT; ++light_idx)          { -            vec3  lightColor = light_col[ light_idx ].rgb; +            vec3  lightColor = light_col[ light_idx ].rgb; // Already in linear, see pipeline.cpp: volume->getLightLinearColor();              float falloff    = light_col[ light_idx ].a;              float lightSize  = light    [ light_idx ].w;              vec3  lv         =(light    [ light_idx ].xyz - pos);              calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist); -            if (nl > 0.0 || nv > 0.0) +            float dist = lightDist / lightSize; +            if (dist <= 1.0 && nl > 0.0)              { -                float dist = lightDist / lightSize; -                float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff); -                vec3 intensity = dist_atten * getLightIntensityPoint(lightColor, lightSize, lightDist); -                colorDiffuse += intensity * nl * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); -                colorSpec    += intensity * nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +                float dist_atten = calcLegacyDistanceAttenuation(dist, falloff); +                vec3 intensity = dist_atten * nl * lightColor; +                colorDiffuse += intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +                colorSpec    += intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);              }          }    #if DEBUG_PBR_LIGHT_TYPE -        colorDiffuse = vec3(0,0.5,0); colorSpec = vec3(0); +        colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0);    #endif          final_color = colorDiffuse + colorSpec;      }      else      { -        if (pos.z < far_z) -        { -            discard; -        }          float noise = texture2D(noiseMap, tc/128.0).b; @@ -140,14 +147,8 @@ void main()                      float lightDist;                      calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist); -                    float fa         = light_col[i].a + 1.0; -                    float dist_atten = clamp(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 0.0, 1.0); -                    dist_atten *= dist_atten; - -                    // Tweak falloff slightly to match pre-EEP attenuation -                    // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit -                    dist_atten *= 2.0; - +                    float fa         = light_col[i].a; +                    float dist_atten = calcLegacyDistanceAttenuation(dist, fa);                      dist_atten *= noise;                      float lit = nl * dist_atten; @@ -173,8 +174,18 @@ void main()                  }              }          } +  #if DEBUG_LEG_LIGHT_TYPE +        final_color.rgb = vec3(0.5,0,0.0); +  #endif      } +#if DEBUG_POINT_ZERO +    final_color = vec3(0); +#endif +#if DEBUG_ANY_LIGHT_TYPE +    final_color = vec3(0.3333,0,0); +#endif +      frag_color.rgb = final_color;      frag_color.a   = 0.0;  #endif // LOCAL_LIGHT_KILL diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl index 20309d9673..3efc9c1689 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl @@ -28,15 +28,39 @@  /*[EXTRA_CODE_HERE]*/ +#define DEBUG_ANY_LIGHT_TYPE         0 // Output blue light cone +#define DEBUG_LEG_LIGHT_TYPE         0 // Show Legacy objects in blue  #define DEBUG_PBR_LIGHT_TYPE         0 // Ouput gray if PBR multiSpot lights object  #define DEBUG_PBR_SPOT               0  #define DEBUG_PBR_SPOT_DIFFUSE       0 // PBR diffuse lit  #define DEBUG_PBR_SPOT_SPECULAR      0 // PBR spec lit -#define DEBUG_SPOT_DIFFUSE           0 -#define DEBUG_SPOT_NL                0 // monochome area effected by light -#define DEBUG_SPOT_SPEC_POS          0 -#define DEBUG_SPOT_REFLECTION        0 +#define DEBUG_LIGHT_FRUSTUM            0 // If projected light effects a surface +#define DEBUG_AMBIANCE_COLOR           0 // calculated ambiance color +#define DEBUG_AMBIANCE_AOE             0 // area of effect using inverse ambiance color +#define DEBUG_AMBIANCE_FINAL           0 // light color * ambiance color +#define DEBUG_NOISE                    0 // monochrome noise +#define DEBUG_SHADOW                   0 // Show inverted shadow +#define DEBUG_SPOT_DIFFUSE             0 // dot(n,l) * dist_atten +#define DEBUG_SPOT_NL                  0 // monochome area effected by light +#define DEBUG_SPOT_SPEC_POS            0 +#define DEBUG_SPOT_REFLECTION          0 // color: pos reflected along n +#define DEBUG_SPOT_ZERO                0 // Output zero for spotlight + +#define DEBUG_PBR_LIGHT_H              0 // Half vector +#define DEBUG_PBR_LIHGT_L              0 // Light vector +#define DEBUG_PBR_LIGHT_NH             0 // colorized dot(n,h) +#define DEBUG_PBR_LIGHT_NL             0 // colorized dot(n,l) +#define DEBUG_PBR_LIGHT_NV             0 // colorized dot(n,v) +#define DEBUG_PBR_LIGHT_VH             0 // colorized dot(v,h) +#define DEBUG_PBR_LIGHT_DIFFUSE_COLOR  0 // non PBR spotlight +#define DEBUG_PBR_LIGHT_SPECULAR_COLOR 0 // non PBR spotlight +#define DEBUG_PBR_LIGHT_INTENSITY      0 // Light intensity +#define DEBUG_PBR_LIGHT_INTENSITY_NL   0 // Light intensity * dot(n,l) +#define DEBUG_PBR_LIGHT_BRDF_DIFFUSE   0 // like "fullbright" if no "nl" factor +#define DEBUG_PBR_LIGHT_BRDF_SPECULAR  0 +#define DEBUG_PBR_LIGHT_BRDF_FINAL     0 // BRDF Diffuse + BRDF Specular +  #ifdef DEFINE_GL_FRAGCOLOR  out vec4 frag_color; @@ -86,9 +110,12 @@ uniform mat4 inv_proj;  vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );  vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );  void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); +float calcLegacyDistanceAttenuation(float distance, float falloff); +vec3 colorized_dot(float x);  bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );  vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);  vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); +vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);  vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );  vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);  vec2 getScreenXY(vec4 clip); @@ -96,20 +123,6 @@ void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3  vec3 srgb_to_linear(vec3 cs);  vec4 texture2DLodSpecular(vec2 tc, float lod); -vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) -{ -    vec4 ret = texture2DLod(projectionMap, tc, lod); -    ret.rgb = srgb_to_linear(ret.rgb); - -    vec2 dist = tc-vec2(0.5); - -    float d = dot(dist,dist); - -    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); - -    return ret; -} -  vec4 getPosition(vec2 pos_screen);  void main() @@ -143,7 +156,11 @@ void main()      vec3 n;      vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); -    float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff); +    float dist_atten = calcLegacyDistanceAttenuation(dist, falloff); +    if (dist_atten <= 0.0) +    { +        discard; +    }      lv = proj_origin-pos.xyz;      vec3  h, l, v = -normalize(pos); @@ -155,6 +172,8 @@ void main()      vec3 dlit    = vec3(0, 0, 0);      vec3 slit    = vec3(0, 0, 0); +    vec3 amb_rgb = vec3(0); +      if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))      {          vec3 colorDiffuse  = vec3(0); @@ -163,66 +182,119 @@ void main()          vec3 packedORM     = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl          float metal        = packedORM.b; -//        if (proj_tc.x > 0.0 && proj_tc.x < 1.0 -//        &&  proj_tc.y > 0.0 && proj_tc.y < 1.0) -        if (nl > 0.0) +        // We need this additional test inside a light's frustum since a spotlight's ambiance can be applied +        if (proj_tc.x > 0.0 && proj_tc.x < 1.0 +        &&  proj_tc.y > 0.0 && proj_tc.y < 1.0)          { -            vec3 c_diff, reflect0, reflect90; -            float alphaRough, specWeight; -            initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); +            float lit = 0.0; +            float amb_da = 0.0; -            dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy ); -            slit = getProjectedLightSpecularColor( pos, n ); +            if (nl > 0.0) +            { +                amb_da += (nl*0.5 + 0.5) * proj_ambiance; +                lit = nl * dist_atten; -//          vec3 intensity = getLightIntensitySpot( color, size, lightDist, v ); -            colorDiffuse = shadow * dlit * nl * dist_atten; -            colorSpec    = shadow * slit * nl * dist_atten; +                vec3 c_diff, reflect0, reflect90; +                float alphaRough, specWeight; +                initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); -//          colorDiffuse *= BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh ); -//          colorSpec    *= BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh ); +                dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy ); +                slit = getProjectedLightSpecularColor( pos, n ); + +                colorDiffuse = shadow * lit * (dlit*0.5 + BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh )); +                colorSpec    = shadow * lit * (slit     + BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh )); + +      #if DEBUG_PBR_SPOT_DIFFUSE +                colorDiffuse = dlit.rgb; colorSpec = vec3(0); +      #endif +      #if DEBUG_PBR_SPOT_SPECULAR +                colorDiffuse = vec3(0); colorSpec = slit.rgb; +      #endif +      #if DEBUG_PBR_SPOT +                colorDiffuse = dlit; colorSpec = vec3(0); +                colorDiffuse *= nl; +                colorDiffuse *= shadow; +      #endif +            } + +            amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy ); +            colorDiffuse += diffuse.rgb * amb_rgb; -  #if DEBUG_PBR_SPOT_DIFFUSE -            colorDiffuse = dlit.rgb; colorSpec = vec3(0); +  #if DEBUG_AMBIANCE_FINAL +            colorDiffuse = diffuse.rgb * amb_rgb; colorSpec = vec3(0);    #endif -  #if DEBUG_PBR_SPOT_SPECULAR -            colorDiffuse = vec3(0); colorSpec = slit.rgb; +  #if DEBUG_LIGHT_FRUSTUM +            colorDiffuse = vec3(0,1,0); colorSpec = vec3(0);    #endif -  #if DEBUG_PBR_SPOT -            colorDiffuse = dlit; colorSpec = vec3(0); -            colorDiffuse *= nl; -            colorDiffuse *= shadow; +  #if DEBUG_NOISE +            float noise = texture2D(noiseMap, tc/128.0).b; +            colorDiffuse = vec3(noise); colorSpec = vec3(0);    #endif +        } -  #if DEBUG_SPOT_SPEC_POS -            colorDiffuse = pos + ref * dot(pdelta, proj_n)/ds; colorSpec = vec3(0); -  #endif -  #if DEBUG_SPOT_REFLECTION -            colorDiffuse = ref; colorSpec = vec3(0); +  #if DEBUG_PBR_LIGHT_TYPE +        colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0);    #endif -        } +  #if DEBUG_PBR_LIGHT_H +        colorDiffuse = h*0.5 + 0.5;  colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIHGT_L +        colorDiffuse = l*0.5 + 0.5;  colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_NH +        colorDiffuse = colorized_dot(nh); colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_NL +        colorDiffuse = colorized_dot(nl); colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_NV +        colorDiffuse = colorized_dot(nv); colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_VH +        colorDiffuse = colorized_dot(vh); colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_DIFFUSE_COLOR +        colorDiffuse = dlit; +  #endif +  #if DEBUG_PBR_LIGHT_SPECULAR_COLOR +        colorDiffuse = slit; +  #endif +  #if DEBUG_PBR_LIGHT_INTENSITY +        colorDiffuse = getLightIntensitySpot( color, size, lightDist, v ); colorSpec = vec3(0); +//        colorDiffuse = nl * dist_atten; +  #endif +  #if DEBUG_PBR_LIGHT_INTENSITY_NL +        colorDiffuse = getLightIntensitySpot( color, size, lightDist, v ) * nl; colorSpec = vec3(0); +  #endif +  #if DEBUG_PBR_LIGHT_BRDF_DIFFUSE +        vec3 c_diff, reflect0, reflect90; +        float alphaRough, specWeight; +        initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); -  #if DEBUG_SPOT_DIFFUSE -        colorDiffuse = vec3(nl * dist_atten); +        colorDiffuse = BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh ); +        colorSpec = vec3(0);    #endif -  #if DEBUG_SPOT_NL -        colorDiffuse = vec3(nl); colorSpec = vec3(0); +  #if DEBUG_PBR_LIGHT_BRDF_SPECULAR +        vec3 c_diff, reflect0, reflect90; +        float alphaRough, specWeight; +        initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); + +        colorDiffuse = vec3(0); +        colorSpec = BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );    #endif -  #if DEBUG_PBR_LIGHT_TYPE -        colorDiffuse = vec3(0.5); colorSpec = vec3(0); +  #if DEBUG_PBR_LIGHT_BRDF_FINAL +        vec3 c_diff, reflect0, reflect90; +        float alphaRough, specWeight; +        initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); +        colorDiffuse = nl * BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh ); +        colorSpec    = nl * BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );    #endif          final_color = colorDiffuse + colorSpec;      }      else      { -        dist_atten *= dist_atten; -        dist_atten *= 2.0; -        if (dist_atten <= 0.0) -        { -            discard; -        } -          float noise = texture2D(noiseMap, tc/128.0).b;          if (proj_tc.z > 0.0 &&              proj_tc.x < 1.0 && @@ -230,7 +302,7 @@ void main()              proj_tc.x > 0.0 &&              proj_tc.y > 0.0)          { -            float amb_da = proj_ambiance; +            float amb_da = 0;              float lit = 0.0;              if (nl > 0.0) @@ -245,15 +317,11 @@ void main()                  amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;              } -            //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); -            vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - -            // use unshadowed for consistency between forward and deferred? -            amb_da += (nl*nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance; -            amb_da *= dist_atten * noise; -            amb_da = min(amb_da, 1.0-lit); - -            final_color += amb_da*color.rgb*diffuse.rgb*amb_plcol.rgb*amb_plcol.a; +            amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, noise, proj_tc.xy ); +            final_color += diffuse.rgb * amb_rgb; +#if DEBUG_LEG_LIGHT_TYPE +            final_color = vec3(0,0,0.5); +#endif          }          if (spec.a > 0.0) @@ -301,22 +369,58 @@ void main()                      }                  }              } -  #if DEBUG_SPOT_SPEC_POS -            final_color = pos + ref * dot(pdelta, proj_n)/ds; -  #endif    #if DEBUG_SPOT_REFLECTION              final_color = ref;    #endif          } +#if DEBUG_LIGHT_FRUSTUM +        if (proj_tc.x > 0.0 && proj_tc.x < 1.0 +        &&  proj_tc.y > 0.0 && proj_tc.y < 1.0) +        { +            final_color = vec3(0,0,1); +        } +#endif +    } + +#if DEBUG_AMBIANCE_AOE +    if (proj_tc.x > 0.0 && proj_tc.x < 1.0 +    &&  proj_tc.y > 0.0 && proj_tc.y < 1.0) +    { +        final_color = 1.0 - amb_rgb; +    } +#endif +#if DEBUG_AMBIANCE_COLOR +    if (proj_tc.x > 0.0 && proj_tc.x < 1.0 +    &&  proj_tc.y > 0.0 && proj_tc.y < 1.0) +    { +        final_color = amb_rgb; +    } +#endif +#if DEBUG_SHADOW +    final_color = 1.0 - vec3(shadow); +#endif +#if DEBUG_SPOT_DIFFUSE +    final_color = vec3(nl * dist_atten); +#endif  #if DEBUG_SPOT_NL      final_color =vec3(nl);  #endif -#if DEBUG_SPOT_DIFFUSE -    final_color = vec3(nl * dist_atten * noise); +#if DEBUG_SPOT_SPEC_POS +    vec3 ref = reflect(normalize(pos), n); +    vec3 pdelta = proj_p-pos; +    float ds = dot(ref, proj_n); +    final_color = pos + ref * dot(pdelta, proj_n)/ds; +#endif +#if DEBUG_SPOT_REFLECTION +    final_color = reflect(normalize(pos), n); +#endif +#if DEBUG_SPOT_ZERO +    final_color = vec3(0,0,0); +#endif +#if DEBUG_ANY_LIGHT_TYPE +    final_color = vec3(0,0,0.3333);  #endif - -    }      //not sure why, but this line prevents MATBUG-194      final_color = max(final_color, vec3(0.0)); diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl index defd577266..6f39b0173b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl @@ -27,7 +27,10 @@  /*[EXTRA_CODE_HERE]*/ -#define DEBUG_PBR_LIGHT_TYPE         0 +#define DEBUG_ANY_LIGHT_TYPE         0 // Output magenta light cone +#define DEBUG_LEG_LIGHT_TYPE         0 // Show Legacy objects in green +#define DEBUG_PBR_LIGHT_TYPE         0 // Show PBR objects in blue +#define DEBUG_POINT_ZERO             0 // Output zero for point light  #ifdef DEFINE_GL_FRAGCOLOR  out vec4 frag_color; @@ -62,6 +65,7 @@ uniform vec4 viewport;  vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );  vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );  void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); +float calcLegacyDistanceAttenuation(float distance, float falloff);  vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);  vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);  vec4 getPosition(vec2 pos_screen); @@ -88,8 +92,12 @@ void main()      float nh, nl, nv, vh, lightDist;      calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist); +    if (lightDist >= size) +    { +        discard; +    }      float dist = lightDist / size; -    float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff); +    float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);      if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))      { @@ -97,41 +105,32 @@ void main()          vec3 colorSpec     = vec3(0);          vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive.  See: pbropaqueF.glsl          vec3 packedORM     = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl +        float lightSize    = size; +        vec3 lightColor    = color; // Already in linear, see pipeline.cpp: volume->getLightLinearColor();          vec3 c_diff, reflect0, reflect90;          float alphaRough, specWeight;          initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); -        if (nl > 0.0 || nv > 0.0) +        if (nl > 0.0)          { -            vec3 intensity = dist_atten * getLightIntensityPoint(color, size, lightDist); -            colorDiffuse += intensity * nl * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); -            colorSpec    += intensity * nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +            vec3 intensity = dist_atten * nl * lightColor; // Legacy attenuation +            colorDiffuse += intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +            colorSpec    += intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);          }  #if DEBUG_PBR_LIGHT_TYPE          colorDiffuse = vec3(0,0,0.5); colorSpec = vec3(0);  #endif -          final_color = colorDiffuse + colorSpec;      }      else      { -        float dist = lightDist; -        if (dist >= size) -        { -            discard; -        } -        dist /= size; -          if (nl < 0.0)          {              discard;          } -        dist_atten *= dist_atten; -        dist_atten *= 2.0; -          float noise = texture2D(noiseMap, tc/128.0).b;          float lit = nl * dist_atten * noise; @@ -157,8 +156,19 @@ void main()          {              discard;          } + +#if DEBUG_LEG_LIGHT_TYPE +        final_color.rgb = vec3(0,0.25,0); +#endif      } +#if DEBUG_POINT_ZERO +    final_color = vec3(0); +#endif +#if DEBUG_ANY_LIGHT_TYPE +    final_color = vec3(0.25,0,0.25); +#endif +      frag_color.rgb = final_color;      frag_color.a = 0.0;  } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 83348077d7..1f5fdde9ca 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -364,7 +364,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, vec3 c, float r2, int i)      v -= c;      v = env_mat * v;      { -        return texture(irradianceProbes, vec4(v.xyz, refIndex[i].x)).rgb * refParams[i].x; +        return textureLod(irradianceProbes, vec4(v.xyz, refIndex[i].x), 0).rgb * refParams[i].x;      }  } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index c2a3e472d0..85bb9fbbd1 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -23,8 +23,12 @@   * $/LicenseInfo$   */ -#define PBR_USE_ATMOS              0 -#define PBR_USE_GGX_EMS_HACK       0 +#define PBR_USE_ATMOS              1 +#define PBR_USE_IBL                1 +#define PBR_USE_SUN                1 + +#define PBR_USE_LINEAR_ALBEDO      1 +#define PBR_USE_DEFAULT_IRRADIANCE 0 // PBR: irradiance, skins/default/textures/default_irradiance.png  #define PBR_USE_IRRADIANCE_HACK    1  #define DEBUG_PBR_LIGHT_TYPE       0 // Output no global light to make it easier to see pointLight and spotLight @@ -60,6 +64,8 @@  #define DEBUG_PBR_FRESNEL          0 // Output: roughness dependent fresnel  #define DEBUG_PBR_KSPEC            0 // Output: K spec  #define DEBUG_PBR_REFLECTION_DIR   0 // Output: reflection dir +#define DEBUG_PBR_SPEC_IBL         0 // Output: IBL specularity +#define DEBUG_PBR_SPEC_LEGACY      0 // Output: legacyenv  #define DEBUG_PBR_SPEC_REFLECTION  0 // Output: environment reflection  #define DEBUG_PBR_FSS_ESS_GGX      0 // Output: FssEssGGX  #define DEBUG_PBR_SPEC             0 // Output: Final spec @@ -67,7 +73,7 @@  // IBL Diffuse  #define DEBUG_PBR_DIFFUSE_C        0 // Output: diffuse non metal mix  #define DEBUG_PBR_IRRADIANCE_RAW   0 // Output: Diffuse Irradiance pre-mix -#define DEBUG_PBR_IRRADIANCE       0 // Output: Diffuse Irradiance +#define DEBUG_PBR_IRRADIANCE       0 // Output: Diffuse Irradiance, NOTE: SSAO is factored in  #define DEBUG_PBR_FSS_ESS_LAMBERT  0 // Output: FssEssLambert  #define DEBUG_PBR_EMS              0 // Output: Ems = (1 - BRDF Scale + BRDF Bias)  #define DEBUG_PBR_AVG              0 // Output: Avg @@ -77,6 +83,7 @@  #define DEBUG_PBR_DIFFUSE          0 // Output: diffuse post AO  // Atmospheric Lighting +#define DEBUG_PBR_AMBENV           0 // Output: ambient environment  #define DEBUG_PBR_AMBOCC           0 // Output: ambient occlusion  #define DEBUG_PBR_DA_RAW           0 // Output: da pre pow()  #define DEBUG_PBR_DA_POW           0 // Output: da post pow() @@ -85,6 +92,29 @@  #define DEBUG_PBR_SKY_ADDITIVE     0 // Output: additive  #define DEBUG_PBR_SKY_ATTEN        0 // Output: greyscale atten.r +// Sun +#define DEBUG_PBR_SUN_FULL_BRIGHT  0 // Sunlit color = <1,1,1> +#define DEBUG_PBR_SUN_OUT_DIFFUSE  0 // Final sun diffuse : intensity * nl * diffuse +#define DEBUG_PBR_SUN_OUT_SPECULAR 0 // Final sun specular: intensity * nl * specular +#define DEBUG_PBR_SUN_LAMBERT      0 // BRDF Diffuse: Lambertian Diffuse color +#define DEBUG_PBR_SUN_LAMBERT_NL   0 // BRDF Diffuse: nl * Lambertian Diffuse color +#define DEBUG_PBR_SUN_H            0 // Half Vector +#define DEBUG_PBR_SUN_L            0 // Light Vector +#define DEBUG_PBR_SUN_V            0 // Surface to Light Vector +#define DEBUG_PBR_SUN_NH           0 // dot(n,h) +#define DEBUG_PBR_SUN_NL           0 // dot(n,l) +#define DEBUG_PBR_SUN_NV           0 // dot(n,v) +#define DEBUG_PBR_SUN_VH           0 // dot(v,h) +#define DEBUG_PBR_SUN_REFLECT0     0 // reflect0 only +#define DEBUG_PBR_SUN_SPEC_FRESNEL 0 // Fresnel +#define DEBUG_PBR_SUN_SPEC_D       0 // D(h) +#define DEBUG_PBR_SUN_SPEC_V       0 // V(l,v,h) +#define DEBUG_PBR_SUN_SPEC_DF      0 // D() * F() +#define DEBUG_PBR_SUN_SPEC_DV      0 // D() * V() +#define DEBUG_PBR_SUN_SPEC_FV      0 // F() * V() +#define DEBUG_PBR_SUN_SPEC_DFV     0 // D() * F() * V() +#define DEBUG_PBR_SUN_SPEC_NL_DFV  0 // nl * D() * F() * V() +  #define DEBUG_PBR_IOR              0 // Output: grayscale IOR  #define DEBUG_PBR_REFLECT0_BASE    0 // Output: black reflect0 default from ior  #define DEBUG_PBR_REFLECT0_MIX     0 // Output: diffuse reflect0 calculated from ior @@ -109,6 +139,9 @@ uniform sampler2DRect diffuseRect;  uniform sampler2DRect specularRect;  uniform sampler2DRect normalMap;  uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl +uniform sampler2D altDiffuseMap; // PBR: irradiance, skins/default/textures/default_irradiance.png + +const float M_PI = 3.14159265;  #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)  uniform sampler2DRect lightMap; @@ -134,9 +167,16 @@ uniform vec2 screen_res;  vec3 getNorm(vec2 pos_screen);  vec4 getPositionWithDepth(vec2 pos_screen, float depth); +vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh ); +vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );  void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao); +float calcF0(float ior); +void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); +  float getAmbientClamp();  vec2 getGGX( vec2 brdfPoint ); +void initMaterial( vec3 diffuse, vec3 packedORM, +        out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );  vec3  atmosFragLighting(vec3 l, vec3 additive, vec3 atten);  vec3  scaleSoftClipFrag(vec3 l);  vec3  fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten); @@ -151,18 +191,19 @@ void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3  vec3 linear_to_srgb(vec3 c);  vec3 srgb_to_linear(vec3 c); +// Debug Utils +vec3 BRDFDiffuse(vec3 color); +vec3 colorize_dot(float x); +vec3 fresnelSchlick( vec3 reflect0, vec3 reflect90, float vh); +float D_GGX( float nh, float alphaRough ); +float V_GGX( float nl, float nv, float alphaRough ); +  #ifdef WATER_FOG  vec4 applyWaterFogView(vec3 pos, vec4 color);  #endif  uniform vec3 view_dir; // PBR -vec3 calcBaseReflect0(float ior) -{ -    vec3   reflect0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)); -    return reflect0; -} -  void main()  {      vec2  tc           = vary_fragcoord.xy; @@ -173,12 +214,7 @@ void main()      norm.xyz           = getNorm(tc);      vec3  light_dir   = (sun_up_factor == 1) ? sun_dir : moon_dir; -    float da          = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); -#if DEBUG_PBR_DA_RAW -    float debug_da    = da; -#endif      float light_gamma = 1.0 / 1.3; -    da                = pow(da, light_gamma);      vec4 diffuse     = texture2DRect(diffuseRect, tc);      vec4 spec        = texture2DRect(specularRect, vary_fragcoord.xy); // NOTE: PBR sRGB Emissive @@ -236,17 +272,11 @@ void main()               packedORM        = vec3(1,1,1);  #endif          float IOR             = 1.5;         // default Index Of Refraction 1.5 (dielectrics) -        vec3  reflect0        = vec3(0.04);  // -> incidence reflectance 0.04 -#if HAS_IOR -              reflect0        = calcBaseReflect0(IOR); -#endif  #if DEBUG_PBR_REFLECT0_BASE -        vec3  debug_reflect0  = reflect0; +        vec3  debug_reflect0  = vec3(calcF0(IOR));  #endif - +        float ao         = packedORM.r;          float metal      = packedORM.b; -        vec3  c_diff     = mix(diffuse.rgb,vec3(0),metal); -        vec3  reflect90  = vec3(0);          vec3  v          = -normalize(pos.xyz);  #if DEBUG_PBR_VERT2CAM1                v = vec3(0,0,1); @@ -259,26 +289,32 @@ void main()          vec3  b          = cross( n,t);          vec3  reflectVN  = normalize(reflect(-v,n)); -        float dotNV = clamp(dot(n,v),0,1); -        float dotTV = clamp(dot(t,v),0,1); -        float dotBV = clamp(dot(b,v),0,1); +        vec3  h, l; +        float nh, nl, nv, vh, lightDist; +        calcHalfVectors(light_dir, n, v, h, l, nh, nl, nv, vh, lightDist); + +        float tv = clamp(dot(t,v),0,1); +        float bv = clamp(dot(b,v),0,1);          // Reference: getMetallicRoughnessInfo -        float perceptualRough = packedORM.g; -        float alphaRough      = perceptualRough * perceptualRough; -        vec3  colorDiff       = mix( diffuse.rgb, vec3(0)    , metal); -              reflect0        = mix( reflect0   , diffuse.rgb, metal); // reflect at 0 degrees -              reflect90       = vec3(1);                               // reflect at 90 degrees +#if PBR_USE_LINEAR_ALBEDO +        vec3  base            = diffuse.rgb; +#else +        vec3  base            = linear_to_srgb(diffuse.rgb); +#endif +        float perceptualRough = packedORM.g;  // NOTE: do NOT clamp here to be consistent with Blender, Blender is wrong and Substance is right +        vec3 c_diff, reflect0, reflect90; +        float alphaRough, specWeight; +        initMaterial( base, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );  #if DEBUG_PBR_REFLECTANCE          float reflectance     = max( max( reflect0.r, reflect0.g ), reflect0.b );  #endif          // Common to RadianceGGX and RadianceLambertian -        float specWeight = 1.0; -        vec2  brdfPoint  = clamp(vec2(dotNV, perceptualRough), vec2(0,0), vec2(1,1)); +        vec2  brdfPoint  = clamp(vec2(nv, perceptualRough), vec2(0,0), vec2(1,1));          vec2  vScaleBias = getGGX( brdfPoint); // Environment BRDF: scale and bias applied to reflect0          vec3  fresnelR   = max(vec3(1.0 - perceptualRough), reflect0) - reflect0; // roughness dependent fresnel -        vec3  kSpec      = reflect0 + fresnelR*pow(1.0 - dotNV, 5.0); +        vec3  kSpec      = reflect0 + fresnelR*pow(1.0 - nv, 5.0);          // Reference: getIBLRadianceGGX          // https://forum.substance3d.com/index.php?topic=3243.0 @@ -291,9 +327,13 @@ void main()  #if DEBUG_PBR_IRRADIANCE_RAW          vec3 debug_irradiance = irradiance;  #endif -        irradiance       = max(amblit,irradiance); + +#if PBR_USE_DEFAULT_IRRADIANCE +        vec2 iruv  = vec2(0.5f + 0.5f * atan(reflectVN.z, reflectVN.x) / M_PI, 1.f - acos(reflectVN.y) / M_PI); +        irradiance = texture2D(altDiffuseMap, iruv).rgb * ambocc; +#endif  #if PBR_USE_IRRADIANCE_HACK -        irradiance      += amblit*0.5*vec3(dot(n, light_dir)); +        irradiance       = max(amblit,irradiance) * ambocc;  #endif          specLight        = srgb_to_linear(specLight);  #if DEBUG_PBR_SPECLIGHT051 @@ -304,7 +344,12 @@ void main()          kSpec          = mix( kSpec, iridescenceFresnel, iridescenceFactor);  #endif          vec3 FssEssGGX = kSpec*vScaleBias.x + vScaleBias.y; +#if DEBUG_PBR_SPEC_IBL +        vec3 debug_color_spec = specWeight * specLight * FssEssGGX; +#endif +#if PBR_USE_IBL          colorSpec += specWeight * specLight * FssEssGGX; +#endif          // Reference: getIBLRadianceLambertian          vec3  FssEssLambert = specWeight * kSpec * vScaleBias.x + vScaleBias.y; // NOTE: Very similar to FssEssRadiance but with extra specWeight term @@ -313,18 +358,144 @@ void main()          vec3  AvgEms        = avg * Ems;          vec3  FmsEms        = AvgEms * FssEssLambert / (1.0 - AvgEms);          vec3  kDiffuse      = c_diff * (1.0 - FssEssLambert + FmsEms); +#if PBR_USE_IBL          colorDiffuse       += (FmsEms + kDiffuse) * irradiance; +#endif      #if DEBUG_PBR_DIFFUSE_PRE_AO          vec3 debug_diffuse  = colorDiffuse;      #endif -        colorDiffuse *= packedORM.r; // Occlusion -- NOTE: pbropaque will need occlusion_strength pre-multiplied into spec.r + +        colorDiffuse *= ao; // Occlusion -- NOTE: pbropaque will need occlusion_strength pre-multiplied into spec.r +        colorSpec    *= ao; + +        // Add in sun/moon reflection +        if (nl > 0.0 || nv > 0.0) +        { +            float scale = 4.9; +            vec3 sunColor = srgb_to_linear(sunlit * scale); // NOTE: Midday should have strong sunlight +#if DEBUG_PBR_SUN_FULL_BRIGHT +            sunColor = vec3(1); +#endif +            // scol = sun shadow +            vec3 intensity  = ambocc * sunColor * nl * scol; +#if PBR_USE_LINEAR_ALBEDO +            vec3 sunDiffuse = intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +            vec3 sunSpec    = intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +#else +            vec3 sunDiffuse = base * intensity * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +            vec3 sunSpec    =        intensity * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +#endif +            // Disabling PBR bloom due to two reasons: +            //   1. The glTF 2.0 Specification does not specify bloom, +            //   2. As the camera moves there are lots of bloom shimmering. +            //bloom = dot(sunSpec, sunSpec) / (scale * scale * scale); + +    #if DEBUG_PBR_SUN_SPEC_FRESNEL +            colorDiffuse = vec3(0); +            colorSpec = fresnelSchlick( reflect0, reflect90, vh ); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_D +            colorDiffuse = vec3(0); +            colorSpec = vec3(D_GGX( nh, alphaRough )); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_V +            colorDiffuse = vec3(0); +            colorSpec = vec3(V_GGX( nl, nv, alphaRough )); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_DF +            colorDiffuse = vec3(0); +            colorSpec  = fresnelSchlick( reflect0, reflect90, vh ); +            colorSpec *= D_GGX( nh, alphaRough ); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_DV +            colorDiffuse = vec3(0); +            colorSpec  = vec3(D_GGX( nh, alphaRough )); +            colorSpec *= vec3(V_GGX( nl, nv, alphaRough )); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_FV +            colorDiffuse = vec3(0); +            colorSpec  = fresnelSchlick( reflect0, reflect90, vh ); +            colorSpec *= V_GGX( nl, nv, alphaRough ); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_DFV +            colorDiffuse = vec3(0); +            colorSpec  = fresnelSchlick( reflect0, reflect90, vh ); +            colorSpec *= D_GGX( nh, alphaRough ); +            colorSpec *= V_GGX( nl, nv, alphaRough ); +            bloom = 0; +    #endif +    #if DEBUG_PBR_SUN_SPEC_NL_DFV +            colorDiffuse = vec3(0); +            colorSpec  = nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +    #endif +    #if DEBUG_PBR_SUN_FINAL +            colorDiffuse = nl * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +            colorSpec    = nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh); +    #endif + +    #if DEBUG_PBR_SUN_OUT_DIFFUSE +            colorDiffuse = linear_to_srgb(sunDiffuse); +            colorSpec = vec3(0); +            bloom = 0.0; +    #endif +    #if DEBUG_PBR_SUN_OUT_SPECULAR +            colorDiffuse = linear_to_srgb(sunSpec); +            colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_REFLECT0 +            colorDiffuse = reflect0; +            colorSpec = vec3(0); +    #endif + +#if PBR_USE_SUN +             colorDiffuse += sunDiffuse; +             colorSpec    += sunSpec; +#endif +        } + +#if DEBUG_PBR_SUN_LAMBERT +        colorDiffuse = BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +        colorSpec    = vec3(0); +        bloom        = 0; +#endif +#if DEBUG_PBR_SUN_LAMBERT_NL +        colorDiffuse = nl * BRDFLambertian (reflect0, reflect90, c_diff    , specWeight, vh); +        colorSpec    = vec3(0); +        bloom        = 0; +#endif + +    #if DEBUG_PBR_SUN_H +        colorDiffuse = h*0.5 + 0.5; colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_L +        colorDiffuse = l*0.5 + 0.5; colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_V +        colorDiffuse = v*0.5 + 0.5; colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_NH +        colorDiffuse = colorize_dot(nh); colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_NL +        colorDiffuse = colorize_dot(nl); colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_NV +        colorDiffuse = colorize_dot(nv); colorSpec = vec3(0); +    #endif +    #if DEBUG_PBR_SUN_VH +        colorDiffuse = colorize_dot(vh); colorSpec = vec3(0); +    #endif          color.rgb = colorDiffuse + colorEmissive + colorSpec; -        vec3 sun_contrib = min(da, scol) * sunlit;  #if PBR_USE_ATMOS          color  = linear_to_srgb(color); -        color += 2.0*sun_contrib;       // 2x = Undo legacy hack of calcAtmosphericVars() returning sunlight.rgb * 0.5;          color *= atten.r;          color += 2.0*additive;          color  = scaleSoftClipFrag(color); @@ -344,7 +515,7 @@ void main()          color.rgb = diffuse.rgb;      #endif      #if DEBUG_PBR_OCCLUSION -        color.rgb = vec3(packedORM.r); +        color.rgb = vec3(ao);      #endif      #if DEBUG_PBR_ORM          color.rgb = packedORM; @@ -367,13 +538,13 @@ void main()          color.rgb = b;      #endif      #if DEBUG_PBR_DOT_NV -        color.rgb = vec3(dotNV); +        color.rgb = vec3(nv);      #endif      #if DEBUG_PBR_DOT_TV -        color.rgb = vec3(dotTV); +        color.rgb = vec3(tv);      #endif      #if DEBUG_PBR_DOT_BV -        color.rgb = vec3(dotBV); +        color.rgb = vec3(bv);      #endif      #if DEBUG_PBR_AVG @@ -427,9 +598,11 @@ void main()      #endif      #if DEBUG_PBR_IRRADIANCE_RAW          color.rgb = debug_irradiance; +        bloom = 0;      #endif      #if DEBUG_PBR_IRRADIANCE          color.rgb = irradiance; +        bloom = 0;      #endif      #if DEBUG_PBR_KSPEC          color.rgb = kSpec; @@ -462,9 +635,6 @@ void main()          color.rgb = v*0.5 + vec3(0.5);      #endif -    #if DEBUG_PBR_AMBOCC -        color.rgb = vec3(ambocc); -    #endif      #if DEBUG_PBR_DA_RAW          color.rgb = vec3(debug_da);      #endif @@ -486,10 +656,17 @@ void main()      #if DEBUG_PBR_LIGHT_TYPE          color.rgb = vec3(0);      #endif +          frag_color.rgb = color.rgb; // PBR is done in linear      }  else  { +    float da          = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); +#if DEBUG_PBR_DA_RAW +    float debug_da    = da; +#endif +    da                = pow(da, light_gamma); +      diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035      sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity); @@ -529,7 +706,7 @@ else      if (envIntensity > 0.0)      {  // add environmentmap          //fudge darker -        legacyenv *= 0.5*diffuse.a+0.5;; +        legacyenv *= 0.5*diffuse.a+0.5;          applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);      } @@ -544,12 +721,20 @@ else      color       = fogged.rgb;      bloom       = fogged.a;  #endif +    #if DEBUG_PBR_LIGHT_TYPE +        color.rgb = vec3(0); +    #endif      // convert to linear as fullscreen lights need to sum in linear colorspace      // and will be gamma (re)corrected downstream... -    //color = vec3(ambocc);      //color = ambenv;      //color.b = diffuse.a;      frag_color.rgb = srgb_to_linear(color.rgb);  } +#if DEBUG_PBR_AMBOCC +    frag_color.rgb = vec3(ambocc); +#endif +#if DEBUG_PBR_AMBENV +    frag_color.rgb = ambenv; +#endif      frag_color.a = bloom;  } diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl index a82581d1a1..87b7977f64 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl @@ -28,12 +28,16 @@  /*[EXTRA_CODE_HERE]*/ -#define DEBUG_PBR_LIGHT_TYPE         0 +#define DEBUG_ANY_LIGHT_TYPE         0 // Output green light cone +#define DEBUG_LEG_LIGHT_TYPE         0 // Show Legacy objects in green +#define DEBUG_PBR_LIGHT_TYPE         0 // Show PBR objects in green  #define DEBUG_PBR_SPOT               0 -#define DEBUG_PBR_NL                 0 // monochome area effected by light  #define DEBUG_PBR_SPOT_DIFFUSE       0  #define DEBUG_PBR_SPOT_SPECULAR      0 +#define DEBUG_SPOT_NL                  0 // monochome area effected by light +#define DEBUG_SPOT_ZERO                0 // Output zero for spotlight +  #ifdef DEFINE_GL_FRAGCOLOR  out vec4 frag_color;  #else @@ -81,9 +85,11 @@ uniform mat4 inv_proj;  vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );  vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );  void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); +float calcLegacyDistanceAttenuation(float distance, float falloff);  bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );  vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);  vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); +vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);  vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );  vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);  vec2 getScreenXY(vec4 clip_point); @@ -91,18 +97,6 @@ void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3  vec3 srgb_to_linear(vec3 c);  vec4 texture2DLodSpecular(vec2 tc, float lod); -vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) -{ -    vec4 ret = texture2DLod(projectionMap, tc, lod); -    ret.rgb = srgb_to_linear(ret.rgb); - -    vec2 dist = tc-vec2(0.5); -    float d = dot(dist,dist); -    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); - -    return ret; -} -  vec4 getPosition(vec2 pos_screen);  void main() @@ -136,7 +130,11 @@ void main()      vec3 n;      vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG() -    float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff); +    float dist_atten = calcLegacyDistanceAttenuation(dist, falloff); +    if (dist_atten <= 0.0) +    { +        discard; +    }      lv = proj_origin-pos.xyz; // NOTE: Re-using lv      vec3  h, l, v = -normalize(pos); @@ -156,47 +154,46 @@ void main()          vec3 packedORM     = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl          float metal        = packedORM.b; -//        if (proj_tc.x > 0.0 && proj_tc.x < 1.0 -//        &&  proj_tc.y > 0.0 && proj_tc.y < 1.0) -        if (nl > 0.0) +        // We need this additional test inside a light's frustum since a spotlight's ambiance can be applied +        if (proj_tc.x > 0.0 && proj_tc.x < 1.0 +        &&  proj_tc.y > 0.0 && proj_tc.y < 1.0)          { -            vec3 c_diff, reflect0, reflect90; -            float alphaRough, specWeight; -            initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); +            float lit = 0.0; +            float amb_da = 0.0; -            dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy ); -            slit = getProjectedLightSpecularColor( pos, n ); +            if (nl > 0.0) +            { +                amb_da += (nl*0.5 + 0.5) * proj_ambiance; +                lit = nl * dist_atten; -//          vec3 intensity = getLightIntensitySpot( color, size, lightDist, v ); -//          colorDiffuse = shadow * dlit * nl; -//          colorSpec    = shadow * slit * nl; +                vec3 c_diff, reflect0, reflect90; +                float alphaRough, specWeight; +                initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight ); -//            colorDiffuse *= BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh ); -//            colorSpec    *= BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh ); +                dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy ); +                slit = getProjectedLightSpecularColor( pos, n ); -            colorDiffuse = shadow * dlit * nl * dist_atten; -            colorSpec    = shadow * slit * nl * dist_atten; +                colorDiffuse = shadow * dist_atten * nl * (dlit*0.5 + BRDFLambertian ( reflect0, reflect90, c_diff    , specWeight, vh )); +                colorSpec    = shadow * dist_atten * nl * (slit     + BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh ));    #if DEBUG_PBR_SPOT_DIFFUSE -            colorDiffuse = dlit.rgb; colorSpec = vec3(0); +                colorDiffuse = dlit.rgb; colorSpec = vec3(0);    #endif    #if DEBUG_PBR_SPOT_SPECULAR -            colorDiffuse = vec3(0); colorSpec = slit.rgb; +                colorDiffuse = vec3(0); colorSpec = slit.rgb;    #endif    #if DEBUG_PBR_SPOT -            colorDiffuse = dlit; colorSpec = vec3(0); -            colorDiffuse *= nl; -            colorDiffuse *= shadow; +                colorDiffuse = dlit; colorSpec = vec3(0); +                colorDiffuse *= nl; +                colorDiffuse *= shadow;    #endif +            } + +            vec3 amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy ); +            colorDiffuse += diffuse.rgb * amb_rgb;          } -  #if DEBUG_SPOT_DIFFUSE -        colorDiffuse = vec3(nl * dist_atten); -  #endif -  #if DEBUG_PBR_NL -            colorDiffuse = vec3(nl); colorSpec = vec3(0); -  #endif    #if DEBUG_PBR_LIGHT_TYPE          colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0.0);    #endif @@ -205,14 +202,6 @@ void main()      }      else      { -        dist_atten *= dist_atten; -        dist_atten *= 2.0; - -        if (dist_atten <= 0.0) -        { -            discard; -        } -          float noise = texture2D(noiseMap, tc/128.0).b;          if (proj_tc.z > 0.0 &&              proj_tc.x < 1.0 && @@ -234,14 +223,11 @@ void main()                  amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;              } -            //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); -            vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); - -            amb_da += (nl*nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance; -            amb_da *= dist_atten * noise; -            amb_da = min(amb_da, 1.0-lit); - -            final_color += amb_da*color.rgb*diffuse.rgb*amb_plcol.rgb*amb_plcol.a; +            vec3 amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, noise, proj_tc.xy ); +            final_color += diffuse.rgb*amb_rgb; +  #if DEBUG_LEG_LIGHT_TYPE +            final_color = vec3(0,0.5,0); +  #endif          }          if (spec.a > 0.0) @@ -291,6 +277,19 @@ void main()          }      } +#if DEBUG_SPOT_DIFFUSE +    final_color = vec3(nl * dist_atten); +#endif +#if DEBUG_SPOT_NL +    final_color = vec3(nl); +#endif +#if DEBUG_SPOT_ZERO +    final_color = vec3(0,0,0); +#endif +#if DEBUG_ANY_LIGHT_TYPE +    final_color = vec3(0,0.3333,0); +#endif +      //not sure why, but this line prevents MATBUG-194      final_color = max(final_color, vec3(0.0)); diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 58500cc7af..6b4ab1be17 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 35 +version 36  // The version number above should be incremented IF AND ONLY IF some  // change has been made that is sufficiently important to justify  // resetting the graphics preferences of all users to the recommended @@ -44,6 +44,7 @@ RenderGamma					1	0  RenderGlowResolutionPow		1	9  RenderGround				1	1  RenderMaxPartCount			1	8192 +RenderObjectBump			1	1  RenderLocalLights			1	1  RenderReflectionDetail		1	4  RenderTerrainDetail			1	1 @@ -59,10 +60,10 @@ WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  Disregard128DefaultDrawDistance	1	1  Disregard96DefaultDrawDistance	1	1 -RenderTextureMemoryMultiple		1	1.0  RenderCompressTextures		1	1  RenderShaderLightingMaxLevel	1	3  RenderPBR                   1   1 +RenderReflectionProbeCount  1   256  RenderDeferred				1	1  RenderDeferredSSAO			1	1  RenderUseAdvancedAtmospherics 1 0 @@ -290,8 +291,11 @@ RenderGLContextCoreProfile         1   0  // AMD cards generally perform better when not using VBOs for streaming data  // AMD cards also prefer an OpenGL Compatibility Profile Context +// HACK: Current AMD drivers have bugged cubemap arrays, limit number of reflection probes to 16  list AMD  RenderUseStreamVBO			1	0  RenderGLContextCoreProfile         1   0 +RenderReflectionProbeCount  1   16 + diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 7bad9b56f1..311b669d7f 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -60,7 +60,6 @@ WindLightUseAtmosShaders	1	1  WLSkyDetail					1	128  Disregard128DefaultDrawDistance	1	1  Disregard96DefaultDrawDistance	1	1 -RenderTextureMemoryMultiple		1	1.0  RenderCompressTextures		1	1  RenderShaderLightingMaxLevel	1	3  RenderDeferred				1	1 diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index f981e08ff7..21df036cb7 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -74,10 +74,10 @@ public:  	void decrementNumberOfPicks() { --mNumberOfPicks; } -private: -  	void onServerRespond(LLAvatarPicks* picks); +private: +  	/**  	* Sets number of Picks.  	*/ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1dfd7bfc86..6ca35684d9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -103,7 +103,6 @@  #include "lldiskcache.h"  #include "llvopartgroup.h"  #include "llweb.h" -#include "llfloatertexturefetchdebugger.h"  #include "llspellcheck.h"  #include "llscenemonitor.h"  #include "llavatarrenderinfoaccountant.h" @@ -567,8 +566,8 @@ static void settings_to_globals()  static void settings_modify()  {      LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); -    LLPipeline::sRenderBump             = gSavedSettings.getBOOL("RenderObjectBump"); -    LLPipeline::sRenderDeferred         = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); +    LLPipeline::sRenderBump = TRUE; // FALSE is deprecated --  gSavedSettings.getBOOL("RenderObjectBump"); +    LLPipeline::sRenderDeferred = TRUE; // FALSE is deprecated --  LLPipeline::sRenderBump&& gSavedSettings.getBOOL("RenderDeferred");      LLRenderTarget::sUseFBO             = LLPipeline::sRenderDeferred;      LLVOSurfacePatch::sLODFactor        = gSavedSettings.getF32("RenderTerrainLODFactor");      LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor;  // square lod factor to get exponential range of [1,4] @@ -1551,7 +1550,6 @@ bool LLAppViewer::doFrame()  			{  				S32 non_interactive_ms_sleep_time = 100;  				LLAppViewer::getTextureCache()->pause(); -				LLAppViewer::getImageDecodeThread()->pause();  				ms_sleep(non_interactive_ms_sleep_time);  			} @@ -1571,7 +1569,6 @@ bool LLAppViewer::doFrame()  					ms_sleep(milliseconds_to_sleep);  					// also pause worker threads during this wait period  					LLAppViewer::getTextureCache()->pause(); -					LLAppViewer::getImageDecodeThread()->pause();  				}  			} @@ -1620,7 +1617,6 @@ bool LLAppViewer::doFrame()  			{  				LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" )  				LLAppViewer::getTextureCache()->pause(); -				LLAppViewer::getImageDecodeThread()->pause();  				LLAppViewer::getTextureFetch()->pause();  			}  			if(!total_io_pending) //pause file threads if nothing to process. @@ -1629,21 +1625,9 @@ bool LLAppViewer::doFrame()  				LLLFSThread::sLocal->pause();  			} -			//texture fetching debugger -			if(LLTextureFetchDebugger::isEnabled()) -			{ -				LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df tex_fetch_debugger_instance" ) -				LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = -					LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); -				if(tex_fetch_debugger_instance) -				{ -					tex_fetch_debugger_instance->idle() ; -				} -			} -  			{  				LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) -			resumeMainloopTimeout(); +			    resumeMainloopTimeout();  			}  			pingMainloopTimeout("Main:End");  		} @@ -1695,16 +1679,20 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)  void LLAppViewer::flushLFSIO()  { -	while (1) -	{ -		S32 pending = LLLFSThread::updateClass(0); -		if (!pending) -		{ -			break; -		} -		LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL; -		ms_sleep(100); -	} +    S32 pending = LLLFSThread::updateClass(0); +    if (pending > 0) +    { +        LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL; +        while (1) +        { +            pending = LLLFSThread::updateClass(0); +            if (!pending) +            { +                break; +            } +            ms_sleep(100); +        } +    }  }  bool LLAppViewer::cleanup() @@ -1861,8 +1849,6 @@ bool LLAppViewer::cleanup()  	LL_INFOS() << "Cache files removed" << LL_ENDL; -	// Wait for any pending LFS IO -	flushLFSIO();  	LL_INFOS() << "Shutting down Views" << LL_ENDL;  	// Destroy the UI @@ -2062,13 +2048,13 @@ bool LLAppViewer::cleanup()  	sTextureCache->shutdown();  	sImageDecodeThread->shutdown();  	sPurgeDiskCacheThread->shutdown(); -    if (mGeneralThreadPool) -    { -        mGeneralThreadPool->close(); -    } +	if (mGeneralThreadPool) +	{ +		mGeneralThreadPool->close(); +	}  	sTextureFetch->shutDownTextureCacheThread() ; -	sTextureFetch->shutDownImageDecodeThread() ; +    LLLFSThread::sLocal->shutdown();  	LL_INFOS() << "Shutting down message system" << LL_ENDL;  	end_messaging_system(); @@ -2082,8 +2068,12 @@ bool LLAppViewer::cleanup()  	//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)  	delete sTextureCache;      sTextureCache = NULL; -	delete sTextureFetch; -    sTextureFetch = NULL; +    if (sTextureFetch) +    { +        sTextureFetch->shutdown(); +        delete sTextureFetch; +        sTextureFetch = NULL; +    }  	delete sImageDecodeThread;      sImageDecodeThread = NULL;  	delete mFastTimerLogThread; @@ -2185,14 +2175,7 @@ void LLAppViewer::initGeneralThread()          return;      } -    LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") }; -    LLSD sizeSpec{ poolSizes["General"] }; -    LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 }; -    LL_DEBUGS("ThreadPool") << "Instantiating General pool with " -        << poolSize << " threads" << LL_ENDL; -    // We don't want anyone, especially the main thread, to have to block -    // due to this ThreadPool being full. -    mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024); +    mGeneralThreadPool = new LL::ThreadPool("General", 3);      mGeneralThreadPool->start();  } @@ -2202,13 +2185,12 @@ bool LLAppViewer::initThreads()  	LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); -	LLLFSThread::initClass(enable_threads && false); +	LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo  	// Image decoding  	LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);  	LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);  	LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), -													sImageDecodeThread,  													enable_threads && true,  													app_metrics_qa_mode);  	LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread(); @@ -2717,19 +2699,14 @@ bool LLAppViewer::initConfiguration()  	if (clp.hasOption("graphicslevel"))  	{ -		// User explicitly requested --graphicslevel on the command line. We -		// expect this switch has already set RenderQualityPerformance. Check -		// that value for validity. -		U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance"); -		if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel)) -        { -			// graphicslevel is valid: save it and engage it later. Capture -			// the requested value separately from the settings variable -			// because, if this is the first run, LLViewerWindow's constructor -			// will call LLFeatureManager::applyRecommendedSettings(), which -			// overwrites this settings variable! -			mForceGraphicsLevel = graphicslevel; -        } +        // User explicitly requested --graphicslevel on the command line. We +        // expect this switch has already set RenderQualityPerformance. Check +        // that value for validity later. +        // Capture the requested value separately from the settings variable +        // because, if this is the first run, LLViewerWindow's constructor +        // will call LLFeatureManager::applyRecommendedSettings(), which +        // overwrites this settings variable! +        mForceGraphicsLevel = gSavedSettings.getU32("RenderQualityPerformance");  	}  	LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); @@ -3087,7 +3064,7 @@ bool LLAppViewer::initWindow()  	// Initialize GL stuff  	// -	if (mForceGraphicsLevel) +	if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel)))  	{  		LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);  		gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel); @@ -3284,7 +3261,7 @@ LLSD LLAppViewer::getViewerInfo() const      info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");      info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");      info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled"; -    info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory"); +    info["TEXTURE_MEMORY"] = gGLManager.mVRAM;  #if LL_DARWIN      info["HIDPI"] = gHiDPISupport; @@ -4716,10 +4693,6 @@ void LLAppViewer::idle()  	//  	// Special case idle if still starting up  	// -	if (LLStartUp::getStartupState() >= STATE_WORLD_INIT) -	{ -		update_texture_time(); -	}  	if (LLStartUp::getStartupState() < STATE_STARTED)  	{  		// Skip rest if idle startup returns false (essentially, no world yet) diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 1797d2dd6e..25ba7c365f 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -48,6 +48,7 @@  #include "llfloatergroups.h"  #include "llfloaterreg.h"  #include "llfloaterpay.h" +#include "llfloaterprofile.h"  #include "llfloatersidepanelcontainer.h"  #include "llfloaterwebcontent.h"  #include "llfloaterworldmap.h" @@ -62,11 +63,14 @@  #include "llnotificationsutil.h"	// for LLNotificationsUtil  #include "llpaneloutfitedit.h"  #include "llpanelprofile.h" +#include "llparcel.h"  #include "llrecentpeople.h"  #include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewerobjectlist.h"  #include "llviewermessage.h"	// for handle_lure +#include "llviewernetwork.h" //LLGridManager +#include "llviewerparcelmgr.h"  #include "llviewerregion.h"  #include "lltrans.h"  #include "llcallingcard.h" @@ -81,6 +85,19 @@ const U32 KICK_FLAGS_FREEZE		= 1 << 0;  const U32 KICK_FLAGS_UNFREEZE	= 1 << 1; +std::string getProfileURL(const std::string& agent_name, bool feed_only) +{ +    std::string url = "[WEB_PROFILE_URL][AGENT_NAME][FEED_ONLY]"; +	LLSD subs; +	subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); +	subs["AGENT_NAME"] = agent_name; +    subs["FEED_ONLY"] = feed_only ? "/?feed_only=true" : ""; +	url = LLWeb::expandURLSubstitutions(url, subs); +	LLStringUtil::toLower(url); +	return url; +} + +  // static  void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)  { @@ -316,57 +333,144 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& float  	make_ui_sound("UISndStartIM");  } -static const char* get_profile_floater_name(const LLUUID& avatar_id) +// static +void LLAvatarActions::showProfile(const LLUUID& avatar_id) +{ +	if (avatar_id.notNull()) +	{ +		LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id)); +	} +} + +// static +void LLAvatarActions::showPicks(const LLUUID& avatar_id) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showPick(); +        } +	} +} + +// static +void LLAvatarActions::showPick(const LLUUID& avatar_id, const LLUUID& pick_id) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showPick(pick_id); +        } +	} +} + +// static +void LLAvatarActions::createPick()  { -	// Use different floater XML for our profile to be able to save its rect. -	return avatar_id == gAgentID ? "my_profile" : "profile"; +    LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgent.getID()))); +    LLViewerRegion* region = gAgent.getRegion(); +    if (profilefloater && region) +    { +        LLPickData data; +        data.pos_global = gAgent.getPositionGlobal(); +        data.sim_name = region->getName(); + +        LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +        if (parcel) +        { +            data.name = parcel->getName(); +            data.desc = parcel->getDesc(); +            data.snapshot_id = parcel->getSnapshotID(); +            data.parcel_id = parcel->getID(); +        } +        else +        { +            data.name = region->getName(); +        } + +        profilefloater->createPick(data); +    }  } -static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name) +// static +bool LLAvatarActions::isPickTabSelected(const LLUUID& avatar_id)  { -	std::string url = getProfileURL(av_name.getAccountName()); +    if (avatar_id.notNull()) +    { +        LLFloaterProfile* profilefloater = LLFloaterReg::findTypedInstance<LLFloaterProfile>("profile", LLSD().with("id", avatar_id)); +        if (profilefloater) +        { +            return profilefloater->isPickTabSelected(); +        } +    } +    return false; +} -	// PROFILES: open in webkit window -	LLFloaterWebContent::Params p; -	p.url(url).id(agent_id.asString()); -	LLFloaterReg::showInstance(get_profile_floater_name(agent_id), p); +// static +void LLAvatarActions::showClassifieds(const LLUUID& avatar_id) +{ +	if (avatar_id.notNull()) +	{ +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showClassified(); +        } +	}  }  // static -void LLAvatarActions::showProfile(const LLUUID& id) +void LLAvatarActions::showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit)  { -	if (id.notNull()) +	if (avatar_id.notNull())  	{ -		LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_show_profile, _1, _2)); +        LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", avatar_id))); +        if (profilefloater) +        { +            profilefloater->showClassified(classified_id, edit); +        }  	}  } +// static +void LLAvatarActions::createClassified() +{ +    LLFloaterProfile* profilefloater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgent.getID()))); +    if (profilefloater) +    { +        profilefloater->createClassified(); +    } +} +  //static  -bool LLAvatarActions::profileVisible(const LLUUID& id) +bool LLAvatarActions::profileVisible(const LLUUID& avatar_id)  {  	LLSD sd; -	sd["id"] = id; -	LLFloater* browser = getProfileFloater(id); -	return browser && browser->isShown(); +	sd["id"] = avatar_id; +	LLFloater* floater = getProfileFloater(avatar_id); +	return floater && floater->isShown();  }  //static -LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& id) +LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& avatar_id)  { -	LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> -		(LLFloaterReg::findInstance(get_profile_floater_name(id), LLSD().with("id", id))); -	return browser; +    LLFloaterProfile* floater = LLFloaterReg::findTypedInstance<LLFloaterProfile>("profile", LLSD().with("id", avatar_id)); +    return floater;  }  //static  -void LLAvatarActions::hideProfile(const LLUUID& id) +void LLAvatarActions::hideProfile(const LLUUID& avatar_id)  {  	LLSD sd; -	sd["id"] = id; -	LLFloater* browser = getProfileFloater(id); -	if (browser) +	sd["id"] = avatar_id; +	LLFloater* floater = getProfileFloater(avatar_id); +	if (floater)  	{ -		browser->closeFloater(); +		floater->closeFloater();  	}  } @@ -990,7 +1094,7 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  }  // static -void LLAvatarActions::toggleBlock(const LLUUID& id) +bool LLAvatarActions::toggleBlock(const LLUUID& id)  {  	LLAvatarName av_name;  	LLAvatarNameCache::get(id, &av_name); @@ -1000,10 +1104,12 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)  	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))  	{  		LLMuteList::getInstance()->remove(mute); +		return false;  	}  	else  	{  		LLMuteList::getInstance()->add(mute); +		return true;  	}  } diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 7c721076c8..86183cc119 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -38,6 +38,8 @@ class LLInventoryPanel;  class LLFloater;  class LLView; +std::string getProfileURL(const std::string& agent_name, bool feed_only = false); +  /**   * Friend-related actions (add, remove, offer teleport, etc)   */ @@ -91,13 +93,20 @@ public:  	 */  	static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null); -	/** -	 * Show avatar profile. -	 */ -	static void showProfile(const LLUUID& id); -	static void hideProfile(const LLUUID& id); -	static bool profileVisible(const LLUUID& id); -	static LLFloater* getProfileFloater(const LLUUID& id); +    /** +     * Show avatar profile. +     */ +    static void showProfile(const LLUUID& avatar_id); +    static void showPicks(const LLUUID& avatar_id); +    static void showPick(const LLUUID& avatar_id, const LLUUID& pick_id); +    static void createPick(); +    static void showClassifieds(const LLUUID& avatar_id); +    static void showClassified(const LLUUID& avatar_id, const LLUUID& classified_id, bool edit = false); +    static void createClassified(); +    static void hideProfile(const LLUUID& avatar_id); +    static bool profileVisible(const LLUUID& avatar_id); +    static bool isPickTabSelected(const LLUUID& avatar_id); +    static LLFloater* getProfileFloater(const LLUUID& avatar_id);  	/**  	 * Show avatar on world map. @@ -126,9 +135,10 @@ public:  	static void shareWithAvatars(LLView * panel);  	/** -	 * Block/unblock the avatar. +	 * Block/unblock the avatar by id. +	 * Returns true if blocked, returns false if unblocked  	 */ -	static void toggleBlock(const LLUUID& id); +	static bool toggleBlock(const LLUUID& id);  	/**  	 * Mute/unmute avatar. diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index f41eb3daf4..dd0d06a8c8 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -36,6 +36,7 @@  #include "llstartup.h"  // Linden library includes +#include "llavataractions.h" // for getProfileUrl  #include "lldate.h"  #include "lltrans.h"  #include "llui.h"				// LLUI::getLanguage() @@ -94,54 +95,98 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat  	}  } - -void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method) +void LLAvatarPropertiesProcessor::sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method)  { +    // this is the startup state when send_complete_agent_movement() message is sent. +    // Before this messages won't work so don't bother trying +    if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) +    { +        return; +    } + +    if (avatar_id.isNull()) +    { +        return; +    } +  	// Suppress duplicate requests while waiting for a response from the network  	if (isPendingRequest(avatar_id, type))  	{  		// waiting for a response, don't re-request  		return;  	} -	// indicate we're going to make a request -	addPendingRequest(avatar_id, type); -	std::vector<std::string> strings; -	strings.push_back( avatar_id.asString() ); -	send_generic_message(method, strings); +    std::string cap; + +    switch (type) +    { +    case APT_PROPERTIES: +        // indicate we're going to make a request +        sendAvatarPropertiesRequestMessage(avatar_id); +        // can use getRegionCapability("AgentProfile"), but it is heavy +        // initAgentProfileCapRequest(avatar_id, cap); +        break; +    case APT_PICKS: +    case APT_GROUPS: +    case APT_NOTES: +        if (cap.empty()) +        { +            // indicate we're going to make a request +            sendGenericRequest(avatar_id, type, method); +        } +        else +        { +            initAgentProfileCapRequest(avatar_id, cap); +        } +        break; +    default: +        sendGenericRequest(avatar_id, type, method); +        break; +    }  } -void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) +void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method)  { -	// this is the startup state when send_complete_agent_movement() message is sent. -	// Before this, the AvatarPropertiesRequest message   -	// won't work so don't bother trying -	if (LLStartUp::getStartupState() <= STATE_AGENT_SEND) -	{ -		return; -	} +    // indicate we're going to make a request +    addPendingRequest(avatar_id, type); -	if (isPendingRequest(avatar_id, APT_PROPERTIES)) -	{ -		// waiting for a response, don't re-request -		return; -	} -	// indicate we're going to make a request -	addPendingRequest(avatar_id, APT_PROPERTIES); +    std::vector<std::string> strings; +    strings.push_back(avatar_id.asString()); +    send_generic_message(method, strings); +} -	LLMessageSystem *msg = gMessageSystem; +void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id) +{ +    addPendingRequest(avatar_id, APT_PROPERTIES); -	msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); -	msg->nextBlockFast( _PREHASH_AgentData); -	msg->addUUIDFast(   _PREHASH_AgentID, gAgent.getID() ); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->addUUIDFast(   _PREHASH_AvatarID, avatar_id); -	gAgent.sendReliableMessage(); +    LLMessageSystem *msg = gMessageSystem; + +    msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); +    msg->nextBlockFast(_PREHASH_AgentData); +    msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +    msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +    msg->addUUIDFast(_PREHASH_AvatarID, avatar_id); +    gAgent.sendReliableMessage(); +} + +void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url) +{ +    addPendingRequest(avatar_id, APT_PROPERTIES); +    addPendingRequest(avatar_id, APT_PICKS); +    addPendingRequest(avatar_id, APT_GROUPS); +    addPendingRequest(avatar_id, APT_NOTES); +    LLCoros::instance().launch("requestAgentUserInfoCoro", +        boost::bind(requestAvatarPropertiesCoro, cap_url, avatar_id)); +} + +void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) +{ +    sendRequest(avatar_id, APT_PROPERTIES, "AvatarPropertiesRequest");  }  void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id)  { -	sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest"); +    sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest");  }  void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id) @@ -174,7 +219,7 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData*  		return;  	} -	LL_INFOS() << "Sending avatarinfo update" << LL_ENDL; +	LL_WARNS() << "Sending avatarinfo update. This trims profile descriptions!!!" << LL_ENDL;  	// This value is required by sendAvatarPropertiesUpdate method.  	//A profile should never be mature. (From the original code) @@ -266,6 +311,113 @@ bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avata  	return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED));  } +// static +void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAvatarPropertiesCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders; + +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    httpOpts->setFollowRedirects(true); + +    std::string finalUrl = cap_url + "/" + agent_id.asString(); + +    LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status +        || !result.has("id") +        || agent_id != result["id"].asUUID()) +    { +        LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; +        LLAvatarPropertiesProcessor* self = getInstance(); +        self->removePendingRequest(agent_id, APT_PROPERTIES); +        self->removePendingRequest(agent_id, APT_PICKS); +        self->removePendingRequest(agent_id, APT_GROUPS); +        self->removePendingRequest(agent_id, APT_NOTES); +        return; +    } + +    // Avatar Data + +    LLAvatarData avatar_data; +    std::string birth_date; + +    avatar_data.agent_id = agent_id; +    avatar_data.avatar_id = agent_id; +    avatar_data.image_id = result["sl_image_id"].asUUID(); +    avatar_data.fl_image_id = result["fl_image_id"].asUUID(); +    avatar_data.partner_id = result["partner_id"].asUUID(); +    avatar_data.about_text = result["sl_about_text"].asString(); +    avatar_data.fl_about_text = result["fl_about_text"].asString(); +    avatar_data.born_on = result["member_since"].asDate(); +    avatar_data.profile_url = getProfileURL(agent_id.asString()); + +    avatar_data.flags = 0; +    avatar_data.caption_index = 0; + +    LLAvatarPropertiesProcessor* self = getInstance(); +    // Request processed, no longer pending +    self->removePendingRequest(agent_id, APT_PROPERTIES); +    self->notifyObservers(agent_id, &avatar_data, APT_PROPERTIES); + +    // Picks + +    LLSD picks_array = result["picks"]; +    LLAvatarPicks avatar_picks; +    avatar_picks.agent_id = agent_id; // Not in use? +    avatar_picks.target_id = agent_id; + +    for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) +    { +        const LLSD& pick_data = *it; +        avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); +    } + +    // Request processed, no longer pending +    self->removePendingRequest(agent_id, APT_PICKS); +    self->notifyObservers(agent_id, &avatar_picks, APT_PICKS); + +    // Groups + +    LLSD groups_array = result["groups"]; +    LLAvatarGroups avatar_groups; +    avatar_groups.agent_id = agent_id; // Not in use? +    avatar_groups.avatar_id = agent_id; // target_id + +    for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) +    { +        const LLSD& group_info = *it; +        LLAvatarGroups::LLGroupData group_data; +        group_data.group_powers = 0; // Not in use? +        group_data.group_title = group_info["name"].asString(); // Missing data, not in use? +        group_data.group_id = group_info["id"].asUUID(); +        group_data.group_name = group_info["name"].asString(); +        group_data.group_insignia_id = group_info["image_id"].asUUID(); + +        avatar_groups.group_list.push_back(group_data); +    } + +    self->removePendingRequest(agent_id, APT_GROUPS); +    self->notifyObservers(agent_id, &avatar_groups, APT_GROUPS); + +    // Notes +    LLAvatarNotes avatar_notes; + +    avatar_notes.agent_id = agent_id; +    avatar_notes.target_id = agent_id; +    avatar_notes.notes = result["notes"].asString(); + +    // Request processed, no longer pending +    self->removePendingRequest(agent_id, APT_NOTES); +    self->notifyObservers(agent_id, &avatar_notes, APT_NOTES); +} +  void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)  {  	LLAvatarData avatar_data; @@ -312,6 +464,21 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m  	That will suppress the warnings and be compatible with old server versions.  	WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply  */ + +    LLInterestsData interests_data; +     +    msg->getUUIDFast(   _PREHASH_AgentData,         _PREHASH_AgentID,       interests_data.agent_id ); +    msg->getUUIDFast(   _PREHASH_AgentData,         _PREHASH_AvatarID,      interests_data.avatar_id ); +    msg->getU32Fast(    _PREHASH_PropertiesData,	_PREHASH_WantToMask,    interests_data.want_to_mask ); +    msg->getStringFast( _PREHASH_PropertiesData,    _PREHASH_WantToText,    interests_data.want_to_text ); +    msg->getU32Fast(    _PREHASH_PropertiesData,	_PREHASH_SkillsMask,    interests_data.skills_mask ); +    msg->getStringFast( _PREHASH_PropertiesData,    _PREHASH_SkillsText,    interests_data.skills_text ); +    msg->getString(     _PREHASH_PropertiesData,    _PREHASH_LanguagesText, interests_data.languages_text ); +     +    LLAvatarPropertiesProcessor* self = getInstance(); +    // Request processed, no longer pending +    self->removePendingRequest(interests_data.avatar_id, APT_INTERESTS_INFO); +    self->notifyObservers(interests_data.avatar_id, &interests_data, APT_INTERESTS_INFO);  }  void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**) @@ -385,7 +552,7 @@ void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg,  void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**)  {  	LLAvatarPicks avatar_picks; -	msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.target_id); +	msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.agent_id);  	msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id);  	S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data); @@ -551,6 +718,29 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_  	gAgent.sendReliableMessage();  } +void LLAvatarPropertiesProcessor::sendInterestsInfoUpdate(const LLInterestsData* interests_data) +{ +    if(!interests_data) +    { +        return; +    } + +    LLMessageSystem* msg = gMessageSystem; + +    msg->newMessage(_PREHASH_AvatarInterestsUpdate); +    msg->nextBlockFast( _PREHASH_AgentData); +    msg->addUUIDFast(	_PREHASH_AgentID,       gAgent.getID() ); +    msg->addUUIDFast(   _PREHASH_SessionID,     gAgent.getSessionID() ); +    msg->nextBlockFast( _PREHASH_PropertiesData); +    msg->addU32Fast(	_PREHASH_WantToMask,    interests_data->want_to_mask); +    msg->addStringFast(	_PREHASH_WantToText,    interests_data->want_to_text); +    msg->addU32Fast(	_PREHASH_SkillsMask,    interests_data->skills_mask); +    msg->addStringFast(	_PREHASH_SkillsText,    interests_data->skills_text); +    msg->addString(     _PREHASH_LanguagesText, interests_data->languages_text); +     +    gAgent.sendReliableMessage(); +} +  void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)  {  	if (!new_pick) return; diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index b063048c26..f778634d25 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -56,10 +56,22 @@ enum EAvatarProcessorType  	APT_PICKS,  	APT_PICK_INFO,  	APT_TEXTURES, +    APT_INTERESTS_INFO,  	APT_CLASSIFIEDS,  	APT_CLASSIFIED_INFO  }; +struct LLInterestsData +{ +    LLUUID      agent_id; +    LLUUID      avatar_id; //target id +    U32         want_to_mask; +    std::string want_to_text; +    U32         skills_mask; +    std::string skills_text; +    std::string languages_text; +}; +  struct LLAvatarData  {  	LLUUID 		agent_id; @@ -223,6 +235,8 @@ public:  	void sendClassifiedDelete(const LLUUID& classified_id); +    void sendInterestsInfoUpdate(const LLInterestsData* interests_data); +  	// Returns translated, human readable string for account type, such  	// as "Resident" or "Linden Employee".  Used for profiles, inspectors.  	static std::string accountType(const LLAvatarData* avatar_data); @@ -234,6 +248,8 @@ public:  	static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data); +    static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id); +  	static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);  	static void processAvatarInterestsReply(LLMessageSystem* msg, void**); @@ -252,7 +268,10 @@ public:  protected: -	void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method); +	void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); +    void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); +    void sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id); +    void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url);  	void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 8d1e9a438e..fa7d5139ae 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -640,6 +640,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)  			if(mBuddyInfo.find(agent_related) != mBuddyInfo.end())  			{  				(mBuddyInfo[agent_related])->setRightsTo(new_rights); +				mChangedBuddyIDs.insert(agent_related);  			}  		}  		else diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 20fa6d490b..48c7df40df 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -272,9 +272,9 @@ BOOL LLConversationViewSession::postBuild()  		default:  			break;  		} -	} -	refresh(); +        refresh(); // requires vmi +	}  	return TRUE;  } @@ -490,17 +490,20 @@ void LLConversationViewSession::refresh()  {  	// Refresh the session view from its model data  	LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); -	vmi->resetRefresh(); +    if (vmi) +    { +        vmi->resetRefresh(); -	if (mSessionTitle) -	{		 -		if (!highlightFriendTitle(vmi)) -		{ -			LLStyle::Params title_style; -			title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); -			mSessionTitle->setText(vmi->getDisplayName(), title_style); -		} -	} +        if (mSessionTitle) +        { +            if (!highlightFriendTitle(vmi)) +            { +                LLStyle::Params title_style; +                title_style.color = LLUIColorTable::instance().getColor("LabelTextColor"); +                mSessionTitle->setText(vmi->getDisplayName(), title_style); +            } +        } +    }  	// Update all speaking indicators  	LLSpeakingIndicatorManager::updateSpeakingIndicators(); @@ -524,8 +527,11 @@ void LLConversationViewSession::refresh()  	}  	requestArrange(); -	// Do the regular upstream refresh -	LLFolderViewFolder::refresh(); +    if (vmi) +    { +        // Do the regular upstream refresh +        LLFolderViewFolder::refresh(); +    }  }  void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) @@ -627,8 +633,11 @@ BOOL LLConversationViewParticipant::postBuild()      }      updateChildren(); -	LLFolderViewItem::postBuild(); -    refresh(); +    if (getViewModelItem()) +    { +        LLFolderViewItem::postBuild(); +        refresh(); +    }      return TRUE;  } @@ -712,10 +721,10 @@ void LLConversationViewParticipant::refresh()          // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat          mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); +         +        // Do the regular upstream refresh +        LLFolderViewItem::refresh();      } - -	// Do the regular upstream refresh -	LLFolderViewItem::refresh();  }  void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 288ba8f536..33ac91f88b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -682,6 +682,7 @@ void LLDrawPoolBump::endBump(U32 pass)  S32 LLDrawPoolBump::getNumDeferredPasses()  {  +#if 0 //DEPRECATED -- RenderObjectBump should always be TRUE  	if (gSavedSettings.getBOOL("RenderObjectBump"))  	{  		return 1; @@ -690,6 +691,9 @@ S32 LLDrawPoolBump::getNumDeferredPasses()  	{  		return 0;  	} +#else  +    return 1; +#endif  }  void LLDrawPoolBump::renderDeferred(S32 pass) diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp index b59bffea1a..3930e11cf3 100644 --- a/indra/newview/lldrawpoolpbropaque.cpp +++ b/indra/newview/lldrawpoolpbropaque.cpp @@ -54,18 +54,6 @@ void LLDrawPoolPBROpaque::render(S32 pass)  {  } -// Deferred -void LLDrawPoolPBROpaque::beginDeferredPass(S32 pass) -{ -    gDeferredPBROpaqueProgram.bind(); -} - -void LLDrawPoolPBROpaque::endDeferredPass(S32 pass) -{ -    gDeferredPBROpaqueProgram.unbind(); -    LLRenderPass::endRenderPass(pass); -} -  void LLDrawPoolPBROpaque::renderDeferred(S32 pass)  {      if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_MATERIALS)) @@ -84,63 +72,87 @@ void LLDrawPoolPBROpaque::renderDeferred(S32 pass)      LLGLDisable blend(GL_BLEND);      LLGLDisable alpha_test(GL_ALPHA_TEST); -    // TODO: handle HUDs? -    //if (LLPipeline::sRenderingHUDs) -    //    mShader->uniform1i(LLShaderMgr::NO_ATMO, 1); -    //else -    //    mShader->uniform1i(LLShaderMgr::NO_ATMO, 0); +    LLVOAvatar* lastAvatar = nullptr; +    U64 lastMeshId = 0; -    // TODO: handle under water? -    // if (LLPipeline::sUnderWaterRender) -    LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); -    LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - -    for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) +    for (int i = 0; i < 2; ++i)      { -        LLDrawInfo& params = **i; - -        //gGL.getTexUnit(0)->activate(); +        bool rigged = (i == 1); +        LLGLSLShader* shader = &gDeferredPBROpaqueProgram; +        U32 vertex_data_mask = getVertexDataMask(); -        if (params.mTexture.notNull()) +        if (rigged)          { -            gGL.getTexUnit(0)->bindFast(params.mTexture); // diffuse -        } -        else -        { -            gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sWhiteImagep); +            shader = shader->mRiggedVariant; +            vertex_data_mask |= LLVertexBuffer::MAP_WEIGHT4;          } -        if (params.mNormalMap) -        { -            gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap); -        } -        else -        { -            // TODO: bind default normal map (???? WTF is it ??? ) -        } +        shader->bind(); -        if (params.mSpecularMap) -        { -            gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); // PBR linear packed Occlusion, Roughness, Metal. -        } -        else -        { -            gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); -        } +        LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type+i); +        LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type+i); -        if (params.mEmissiveMap) -        { -            gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, params.mEmissiveMap);  // PBR sRGB Emissive -        } -        else +        for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)          { -            gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep); +            LLDrawInfo* pparams = *i; + +            if (pparams->mTexture.notNull()) +            { +                gGL.getTexUnit(0)->bindFast(pparams->mTexture); // diffuse +            } +            else +            { +                gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sWhiteImagep); +            } + +            if (pparams->mNormalMap) +            { +                shader->bindTexture(LLShaderMgr::BUMP_MAP, pparams->mNormalMap); +            } +            else +            { +                shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); +            } + +            if (pparams->mSpecularMap) +            { +                shader->bindTexture(LLShaderMgr::SPECULAR_MAP, pparams->mSpecularMap); // PBR linear packed Occlusion, Roughness, Metal. +            } +            else +            { +                shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); +            } + +            if (pparams->mEmissiveMap) +            { +                shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, pparams->mEmissiveMap);  // PBR sRGB Emissive +            } +            else +            { +                shader->bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep); +            } + +            shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, pparams->mGLTFMaterial->mRoughnessFactor); +            shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, pparams->mGLTFMaterial->mMetallicFactor); +            shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, pparams->mGLTFMaterial->mEmissiveColor.mV); + +            if (rigged) +            { +                if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)) +                { +                    uploadMatrixPalette(*pparams); +                    lastAvatar = pparams->mAvatar; +                    lastMeshId = pparams->mSkinInfo->mHash; +                } + +                pushBatch(*pparams, vertex_data_mask, FALSE, FALSE); +            } +            else +            { +                pushBatch(*pparams, vertex_data_mask, FALSE, FALSE); +            }          } -         -        gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, params.mGLTFMaterial->mRoughnessFactor); -        gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::METALLIC_FACTOR, params.mGLTFMaterial->mMetallicFactor); -        gDeferredPBROpaqueProgram.uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, params.mGLTFMaterial->mEmissiveColor.mV); - -        LLRenderPass::pushBatch(params, getVertexDataMask(), FALSE, FALSE);      } + +    LLGLSLShader::sCurBoundShaderPtr->unbind();  } diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h index 478d4e1bd4..c355b10b12 100644 --- a/indra/newview/lldrawpoolpbropaque.h +++ b/indra/newview/lldrawpoolpbropaque.h @@ -49,8 +49,6 @@ public:      LLDrawPoolPBROpaque();      /*virtual*/ S32 getNumDeferredPasses() { return 1; } -    /*virtual*/ void beginDeferredPass(S32 pass); -    /*virtual*/ void endDeferredPass(S32 pass);      /*virtual*/ void renderDeferred(S32 pass);      // Non ALM isn't supported diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index cc5cb667f0..be33e1b30a 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -148,7 +148,7 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures()  	for (S32 i = 0; i < 4; i++)  	{  		compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); -		compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area +        gPipeline.touchTexture(compp->mDetailTextures[i], 1024.f * 1024.f);  	}  } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 499d8d161d..52aacb607c 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2321,6 +2321,7 @@ void LLFace::resetVirtualSize()  F32 LLFace::getTextureVirtualSize()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	F32 radius;  	F32 cos_angle_to_view_dir;	  	BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 3c5ac963f6..1dd9a43b72 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -61,6 +61,7 @@ LLFilePicker LLFilePicker::sInstance;  #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"  #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"  #define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0" +#define MATERIAL_TEXTURES_FILTER L"GLTF Import (*.gltf; *.glb; *.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.gltf;*.glb;*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"  #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"  #define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"  #endif @@ -220,6 +221,12 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)          mOFN.lpstrFilter = MATERIAL_FILTER \              L"\0";          break; +    case FFLOAD_MATERIAL_TEXTURE: +        mOFN.lpstrFilter = MATERIAL_TEXTURES_FILTER \ +            MATERIAL_FILTER \ +            IMAGE_FILTER \ +            L"\0"; +        break;  	case FFLOAD_SCRIPT:  		mOFN.lpstrFilter = SCRIPT_FILTER \  			L"\0"; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index cb57c8437d..a03f3f6711 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -87,7 +87,8 @@ public:  		FFLOAD_DICTIONARY = 12,          FFLOAD_DIRECTORY = 13,   // To call from lldirpicker.          FFLOAD_EXE = 14,          // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin -        FFLOAD_MATERIAL = 15 +        FFLOAD_MATERIAL = 15, +        FFLOAD_MATERIAL_TEXTURE = 16,  	};  	enum ESaveFilter diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp index ec05ba924c..0964daa4d5 100644 --- a/indra/newview/llfloaterautoreplacesettings.cpp +++ b/indra/newview/llfloaterautoreplacesettings.cpp @@ -350,7 +350,7 @@ void LLFloaterAutoReplaceSettings::onDeleteEntry()  // called when the Import List button is pressed  void LLFloaterAutoReplaceSettings::onImportList()  { -	(new LLFilePickerReplyThread(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile(); +	LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::loadListFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);  }  void LLFloaterAutoReplaceSettings::loadListFromFile(const std::vector<std::string>& filenames) @@ -537,7 +537,7 @@ void LLFloaterAutoReplaceSettings::onExportList()  {  	std::string listName=mListNames->getFirstSelected()->getColumn(0)->getValue().asString();  	std::string listFileName = listName + ".xml"; -	(new LLFilePickerReplyThread(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName))->getFile(); +	LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterAutoReplaceSettings::saveListToFile, this, _1, listName), LLFilePicker::FFSAVE_XML, listFileName);  }  void LLFloaterAutoReplaceSettings::saveListToFile(const std::vector<std::string>& filenames, std::string listName) diff --git a/indra/newview/llfloaterchatvoicevolume.cpp b/indra/newview/llfloaterchatvoicevolume.cpp index 45aea00a49..67c412dfa6 100644 --- a/indra/newview/llfloaterchatvoicevolume.cpp +++ b/indra/newview/llfloaterchatvoicevolume.cpp @@ -35,7 +35,7 @@ LLFloaterChatVoiceVolume::LLFloaterChatVoiceVolume(const LLSD& key)  void LLFloaterChatVoiceVolume::onOpen(const LLSD& key)  {  	LLInspect::onOpen(key); -	LLUI::getInstance()->positionViewNearMouse(this); +	LLInspect::repositionInspector(key);  }  LLFloaterChatVoiceVolume::~LLFloaterChatVoiceVolume() diff --git a/indra/newview/llfloaterclassified.cpp b/indra/newview/llfloaterclassified.cpp new file mode 100644 index 0000000000..3520b0f67a --- /dev/null +++ b/indra/newview/llfloaterclassified.cpp @@ -0,0 +1,71 @@ +/** + * @file llfloaterclassified.cpp + * @brief LLFloaterClassified for displaying classifieds. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterclassified.h" + +LLFloaterClassified::LLFloaterClassified(const LLSD& key) + : LLFloater(key) +{ +} + +LLFloaterClassified::~LLFloaterClassified() +{ +} + +void LLFloaterClassified::onOpen(const LLSD& key) +{ +    LLPanel* panel = findChild<LLPanel>("main_panel", true); +    if (panel) +    { +        panel->onOpen(key); +    } +    if (key.has("classified_name")) +    { +        setTitle(key["classified_name"].asString()); +    } +    LLFloater::onOpen(key); +} + +BOOL LLFloaterClassified::postBuild() +{ +    return TRUE; +} + + +bool LLFloaterClassified::matchesKey(const LLSD& key) +{ +    bool is_mkey_valid = mKey.has("classified_id"); +    bool is_key_valid = key.has("classified_id"); +    if (is_mkey_valid && is_key_valid) +    { +        return key["classified_id"].asUUID() == mKey["classified_id"].asUUID(); +    } +    return is_mkey_valid == is_key_valid; +} + +// eof diff --git a/indra/newview/llfloaterwebprofile.h b/indra/newview/llfloaterclassified.h index 4c355e401b..2c95d82b2c 100644 --- a/indra/newview/llfloaterwebprofile.h +++ b/indra/newview/llfloaterclassified.h @@ -1,59 +1,45 @@ -/**  - * @file llfloaterwebprofile.h - * @brief Avatar profile floater. +/** + * @file llfloaterclassified.h + * @brief LLFloaterClassified for displaying classifieds.   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  + * Copyright (C) 2022, 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_LLFLOATERWEBPROFILE_H -#define LL_LLFLOATERWEBPROFILE_H - -#include "llfloaterwebcontent.h" -#include "llviewermediaobserver.h" +#ifndef LL_LLFLOATERCLASSIFIED_H +#define LL_LLFLOATERCLASSIFIED_H -#include <string> +#include "llfloater.h" -class LLMediaCtrl; - -/** - * Displays avatar profile web page. - */ -class LLFloaterWebProfile -:	public LLFloaterWebContent +class LLFloaterClassified : public LLFloater  { -	LOG_CLASS(LLFloaterWebProfile); +    LOG_CLASS(LLFloaterClassified);  public: -	typedef LLFloaterWebContent::Params Params; +    LLFloaterClassified(const LLSD& key); +    virtual ~LLFloaterClassified(); -	LLFloaterWebProfile(const Params& key); +    void onOpen(const LLSD& key) override; +    BOOL postBuild() override; -	/*virtual*/ void onOpen(const LLSD& key); -	/*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); - -	static LLFloater* create(const LLSD& key); - -private: -	void applyPreferredRect(); +    bool matchesKey(const LLSD& key) override;  }; -#endif  // LL_LLFLOATERWEBPROFILE_H - +#endif // LL_LLFLOATERCLASSIFIED_H diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp new file mode 100644 index 0000000000..3b0c67415a --- /dev/null +++ b/indra/newview/llfloaterdisplayname.cpp @@ -0,0 +1,200 @@ +/**  + * @file llfloaterdisplayname.cpp + * @author Leyla Farazha + * @brief Implementation of the LLFloaterDisplayName class. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" +#include "llfloaterreg.h" +#include "llfloater.h" + +#include "llnotificationsutil.h" +#include "llviewerdisplayname.h" + +#include "llnotifications.h" +#include "llfloaterdisplayname.h" +#include "llavatarnamecache.h" + +#include "llagent.h" + + +class LLFloaterDisplayName : public LLFloater +{ +public: +	LLFloaterDisplayName(const LLSD& key); +	virtual ~LLFloaterDisplayName() { } +	/*virtual*/	BOOL	postBuild(); +	void onSave(); +	void onCancel(); +	/*virtual*/ void onOpen(const LLSD& key); +	 +private: +	 +	void onCacheSetName(bool success, +										  const std::string& reason, +										  const LLSD& content); +}; + +LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) : +	LLFloater(key) +{ +} + +void LLFloaterDisplayName::onOpen(const LLSD& key) +{ +	getChild<LLUICtrl>("display_name_editor")->clear(); +	getChild<LLUICtrl>("display_name_confirm")->clear(); + +	LLAvatarName av_name; +	LLAvatarNameCache::get(gAgent.getID(), &av_name); + +	F64 now_secs = LLDate::now().secondsSinceEpoch(); + +	if (now_secs < av_name.mNextUpdate) +	{ +		// ...can't update until some time in the future +		F64 next_update_local_secs = +			av_name.mNextUpdate - LLStringOps::getLocalTimeOffset(); +		LLDate next_update_local(next_update_local_secs); +		// display as "July 18 12:17 PM" +		std::string next_update_string = +		next_update_local.toHTTPDateString("%B %d %I:%M %p"); +		getChild<LLUICtrl>("lockout_text")->setTextArg("[TIME]", next_update_string); +		getChild<LLUICtrl>("lockout_text")->setVisible(true); +		getChild<LLUICtrl>("save_btn")->setEnabled(false); +		getChild<LLUICtrl>("display_name_editor")->setEnabled(false); +		getChild<LLUICtrl>("display_name_confirm")->setEnabled(false); +		getChild<LLUICtrl>("cancel_btn")->setFocus(TRUE); +		 +	} +	else +	{ +		getChild<LLUICtrl>("lockout_text")->setVisible(false); +		getChild<LLUICtrl>("save_btn")->setEnabled(true); +		getChild<LLUICtrl>("display_name_editor")->setEnabled(true); +		getChild<LLUICtrl>("display_name_confirm")->setEnabled(true); + +	} +} + +BOOL LLFloaterDisplayName::postBuild() +{ +	getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onCancel, this));	 +	getChild<LLUICtrl>("save_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onSave, this));	 +	 +	center(); + +	return TRUE; +} + +void LLFloaterDisplayName::onCacheSetName(bool success, +										  const std::string& reason, +										  const LLSD& content) +{ +	if (success) +	{ +		// Inform the user that the change took place, but will take a while +		// to percolate. +		LLSD args; +		args["DISPLAY_NAME"] = content["display_name"]; +		LLNotificationsUtil::add("SetDisplayNameSuccess", args); +		return; +	} + +	// Request failed, notify the user +	std::string error_tag = content["error_tag"].asString(); +	LL_INFOS() << "set name failure error_tag " << error_tag << LL_ENDL; + +	// We might have a localized string for this message +	// error_args will usually be empty from the server. +	if (!error_tag.empty() +		&& LLNotifications::getInstance()->templateExists(error_tag)) +	{ +		LLNotificationsUtil::add(error_tag); +		return; +	} + +	// The server error might have a localized message for us +	std::string lang_code = LLUI::getLanguage(); +	LLSD error_desc = content["error_description"]; +	if (error_desc.has( lang_code )) +	{ +		LLSD args; +		args["MESSAGE"] = error_desc[lang_code].asString(); +		LLNotificationsUtil::add("GenericAlert", args); +		return; +	} + +	// No specific error, throw a generic one +	LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +} + +void LLFloaterDisplayName::onCancel() +{ +	setVisible(false); +} + +void LLFloaterDisplayName::onSave() +{ +	std::string display_name_utf8 = getChild<LLUICtrl>("display_name_editor")->getValue().asString(); +	std::string display_name_confirm = getChild<LLUICtrl>("display_name_confirm")->getValue().asString(); + +	if (display_name_utf8.compare(display_name_confirm)) +	{ +		LLNotificationsUtil::add("SetDisplayNameMismatch"); +		return; +	} + +	const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes +	LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8); +	if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH) +	{ +		LLSD args; +		args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH); +		LLNotificationsUtil::add("SetDisplayNameFailedLength", args); +		return; +	} +	 +    if (LLAvatarNameCache::getInstance()->hasNameLookupURL()) +	{ +		LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3));	 +	} +	else +	{ +		LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +	} + +	setVisible(false); +} + + +////////////////////////////////////////////////////////////////////////////// +// LLInspectObjectUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterDisplayNameUtil::registerFloater() +{ +	LLFloaterReg::add("display_name", "floater_display_name.xml", +					  &LLFloaterReg::build<LLFloaterDisplayName>); +} diff --git a/indra/newview/llpanelme.h b/indra/newview/llfloaterdisplayname.h index 60e9d4317d..a00bf56712 100644 --- a/indra/newview/llpanelme.h +++ b/indra/newview/llfloaterdisplayname.h @@ -1,6 +1,5 @@  /**  - * @file llpanelme.h - * @brief Side tray "Me" (My Profile) panel + * @file llfloaterdisplayname.h   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -24,27 +23,16 @@   * $/LicenseInfo$   */ -#ifndef LL_LLPANELMEPROFILE_H -#define LL_LLPANELMEPROFILE_H +#ifndef LLFLOATERDISPLAYNAME_H +#define LLFLOATERDISPLAYNAME_H -#include "llpanel.h" -#include "llpanelprofile.h" -/** -* Panel for displaying Agent's Picks and Classifieds panel. -* LLPanelMe allows user to edit his picks and classifieds. -*/ -class LLPanelMe : public LLPanelProfile +namespace LLFloaterDisplayNameUtil  { -	LOG_CLASS(LLPanelMe); +	// Register with LLFloaterReg +	void registerFloater(); +} -public: -	LLPanelMe(); -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ BOOL postBuild(); -}; - -#endif // LL_LLPANELMEPROFILE_H +#endif diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 24673d5a7c..a6a825500d 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -1523,7 +1523,7 @@ bool LLFloaterEditExtDayCycle::isAddingFrameAllowed()  void LLFloaterEditExtDayCycle::doImportFromDisk()  {   // Load a a legacy Windlight XML from disk. -    (new LLFilePickerReplyThread(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);  }  void LLFloaterEditExtDayCycle::loadSettingFromFile(const std::vector<std::string>& filenames) diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index fec218ca3b..68bb458e61 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -439,7 +439,7 @@ void LLFloaterFixedEnvironmentWater::onOpen(const LLSD& key)  void LLFloaterFixedEnvironmentWater::doImportFromDisk()  {   // Load a a legacy Windlight XML from disk. -    (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);  }  void LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile(const std::vector<std::string>& filenames) @@ -525,7 +525,7 @@ void LLFloaterFixedEnvironmentSky::onClose(bool app_quitting)  void LLFloaterFixedEnvironmentSky::doImportFromDisk()  {   // Load a a legacy Windlight XML from disk. -    (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentSky::loadSkySettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterFixedEnvironmentSky::loadSkySettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false);  }  void LLFloaterFixedEnvironmentSky::loadSkySettingFromFile(const std::vector<std::string>& filenames) diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 6e326ff3cf..d17889bed1 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -122,7 +122,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)  	mObserver = new LLFloaterGestureObserver(this);  	LLGestureMgr::instance().addObserver(mObserver); -	mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); +	mCommitCallbackRegistrar.add("Gesture.Action.ToggleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this));  	mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));  	mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));  	mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 34499ac170..93a0b39e02 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -551,7 +551,7 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part  void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& participant_id)  {  	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); -	if (widget) +	if (widget && widget->getViewModelItem())  	{  		widget->refresh();  	} @@ -576,8 +576,11 @@ void LLFloaterIMSessionTab::refreshConversation()  		{  			participants_uuids.push_back(widget_it->first);  		} -		widget_it->second->refresh(); -		widget_it->second->setVisible(TRUE); +        if (widget_it->second->getViewModelItem()) +        { +            widget_it->second->refresh(); +            widget_it->second->setVisible(TRUE); +        }  		++widget_it;  	}  	if (is_ad_hoc || mIsP2PChat) @@ -1126,7 +1129,10 @@ void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids)      for (; it != it_end; ++it)      {          LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); -        selected_uuids.push_back(conversation_item->getUUID()); +        if (conversation_item) +        { +            selected_uuids.push_back(conversation_item->getUUID()); +        }      }  } diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp index f72f2631a1..db00f69f03 100644 --- a/indra/newview/llfloaterlagmeter.cpp +++ b/indra/newview/llfloaterlagmeter.cpp @@ -179,7 +179,7 @@ void LLFloaterLagMeter::determineClient()  		{  			mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) );  		} -		else if(LLViewerTexture::sBoundTextureMemory > LLViewerTexture::sMaxBoundTextureMemory) +		else if(LLViewerTexture::isMemoryForTextureLow())  		{  			mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) );  		} diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index b77341f806..b7c98c915c 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -741,7 +741,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)      {      case LLModelPreview::MESH_OPTIMIZER_AUTO:      case LLModelPreview::MESH_OPTIMIZER_SLOPPY: -    case LLModelPreview::MESH_OPTIMIZER_COMBINE: +    case LLModelPreview::MESH_OPTIMIZER_PRECISE:          mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, mode);          break;      default: @@ -1745,7 +1745,7 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)      S32 index = lod_source_combo->getCurrentIndex();  	if (index == LLModelPreview::MESH_OPTIMIZER_AUTO          || index == LLModelPreview::MESH_OPTIMIZER_SLOPPY -        || index == LLModelPreview::MESH_OPTIMIZER_COMBINE) +        || index == LLModelPreview::MESH_OPTIMIZER_PRECISE)  	{ //rebuild LoD to update triangle counts  		onLODParamCommit(lod, true);  	} diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp index dccef88e41..ad5e97e067 100644 --- a/indra/newview/llfloateroutfitsnapshot.cpp +++ b/indra/newview/llfloateroutfitsnapshot.cpp @@ -42,7 +42,6 @@  #include "llviewercontrol.h"  #include "lltoolfocus.h"  #include "lltoolmgr.h" -#include "llwebprofile.h"  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 20749b67b2..dd9a212c1c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -333,60 +333,59 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t  		const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData );  		if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null))  		{ -			storeAvatarProperties( pAvatarData ); -			processProfileProperties( pAvatarData ); +            mAllowPublish = (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH); +            mAvatarDataInitialized = true; +            getChild<LLUICtrl>("online_searchresults")->setValue(mAllowPublish);  		}  	}	  } -void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData ) +void LLFloaterPreference::saveAvatarProperties( void )  { -	if (LLStartUp::getStartupState() == STATE_STARTED) -	{ -		mAvatarProperties.avatar_id		= pAvatarData->avatar_id; -		mAvatarProperties.image_id		= pAvatarData->image_id; -		mAvatarProperties.fl_image_id   = pAvatarData->fl_image_id; -		mAvatarProperties.about_text	= pAvatarData->about_text; -		mAvatarProperties.fl_about_text = pAvatarData->fl_about_text; -		mAvatarProperties.profile_url   = pAvatarData->profile_url; -		mAvatarProperties.flags		    = pAvatarData->flags; -		mAvatarProperties.allow_publish	= pAvatarData->flags & AVATAR_ALLOW_PUBLISH; +    const bool allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue(); -		mAvatarDataInitialized = true; -	} -} +    if ((LLStartUp::getStartupState() == STATE_STARTED) +        && mAvatarDataInitialized +        && (allowPublish != mAllowPublish)) +    { +        std::string cap_url = gAgent.getRegionCapability("AgentProfile"); +        if (!cap_url.empty()) +        { +            mAllowPublish = allowPublish; -void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData ) -{ -	getChild<LLUICtrl>("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) );	 +            LLCoros::instance().launch("requestAgentUserInfoCoro", +                boost::bind(saveAvatarPropertiesCoro, cap_url, allowPublish)); +        } +    }  } -void LLFloaterPreference::saveAvatarProperties( void ) +void LLFloaterPreference::saveAvatarPropertiesCoro(const std::string cap_url, bool allow_publish)  { -	const BOOL allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue(); +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders; -	if (allowPublish) -	{ -		mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH; -	} +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    httpOpts->setFollowRedirects(true); -	// -	// NOTE: We really don't want to send the avatar properties unless we absolutely -	//       need to so we can avoid the accidental profile reset bug, so, if we're -	//       logged in, the avatar data has been initialized and we have a state change -	//       for the "allow publish" flag, then set the flag to its new value and send -	//       the properties update. -	// -	// NOTE: The only reason we can not remove this update altogether is because of the -	//       "allow publish" flag, the last remaining profile setting in the viewer -	//       that doesn't exist in the web profile. -	// -	if ((LLStartUp::getStartupState() == STATE_STARTED) && mAvatarDataInitialized && (allowPublish != mAvatarProperties.allow_publish)) -	{ -		mAvatarProperties.allow_publish = allowPublish; +    std::string finalUrl = cap_url + "/" + gAgentID.asString(); +    LLSD data; +    data["allow_publish"] = allow_publish; -		LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties ); -	} +    LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS("Preferences") << "Failed to put agent information " << data << " for id " << gAgentID << LL_ENDL; +        return; +    } + +    LL_DEBUGS("Preferences") << "Agent id: " << gAgentID << " Data: " << data << " Result: " << httpResults << LL_ENDL;  }  BOOL LLFloaterPreference::postBuild() @@ -938,7 +937,7 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata)  	else  	{  		// Show beep, pop up dialog, etc. -		LL_INFOS() << "Can't close preferences!" << LL_ENDL; +		LL_INFOS("Preferences") << "Can't close preferences!" << LL_ENDL;  	}  	LLPanelLogin::updateLocationSelectorsVisibility();	 @@ -1180,36 +1179,10 @@ void LLFloaterPreference::buildPopupLists()  void LLFloaterPreference::refreshEnabledState()  { -	LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); -	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); -    LLCheckBoxCtrl* ctrl_pbr = getChild<LLCheckBoxCtrl>("UsePBRShaders"); - -	// if vertex shaders off, disable all shader related products -	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) -	{ -		ctrl_wind_light->setEnabled(FALSE); -		ctrl_wind_light->setValue(FALSE); -	} -	else -	{ -		ctrl_wind_light->setEnabled(TRUE); -	} - -	//Deferred/SSAO/Shadows -	BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump"); -	BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); -	BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && -						bumpshiny && -						shaders &&  -						gGLManager.mHasFramebufferObject && -						(ctrl_wind_light->get()) ? TRUE : FALSE; - -	ctrl_deferred->setEnabled(enabled); +	LLCheckBoxCtrl* ctrl_pbr = getChild<LLCheckBoxCtrl>("UsePBRShaders");      //PBR -    BOOL deferred = gSavedSettings.getBOOL("RenderDeferred"); -    // TODO: add "RenderPBR" to LLFeatureManager -    ctrl_pbr->setEnabled(deferred); +    ctrl_pbr->setEnabled(TRUE);  	// Cannot have floater active until caps have been received  	getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); @@ -1251,12 +1224,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()  	shadow_text->setEnabled(enabled);  	// Hardware settings -	F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); -	S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); -	S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); -	getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value()); -	getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); - +	  	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||  		!gGLManager.mHasVertexBufferObject)  	{ @@ -1321,58 +1289,11 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()  {	  	LLComboBox* ctrl_reflections   = getChild<LLComboBox>("Reflections");  	LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); -	LLCheckBoxCtrl* ctrl_wind_light    = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); -	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");  	LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");  	LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText");  	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); -	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); -	LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); -	LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); - -	// disabled windlight -	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) -	{ -		ctrl_wind_light->setEnabled(FALSE); -		ctrl_wind_light->setValue(FALSE); - -		sky->setEnabled(FALSE); -		sky_text->setEnabled(FALSE); - -		//deferred needs windlight, disable deferred -		ctrl_shadows->setEnabled(FALSE); -		ctrl_shadows->setValue(0); -		shadows_text->setEnabled(FALSE); -		 -		ctrl_ssao->setEnabled(FALSE); -		ctrl_ssao->setValue(FALSE); - -		ctrl_dof->setEnabled(FALSE); -		ctrl_dof->setValue(FALSE); - -		ctrl_deferred->setEnabled(FALSE); -		ctrl_deferred->setValue(FALSE); -	} - -	// disabled deferred -	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") || -		!gGLManager.mHasFramebufferObject) -	{ -		ctrl_shadows->setEnabled(FALSE); -		ctrl_shadows->setValue(0); -		shadows_text->setEnabled(FALSE); -		 -		ctrl_ssao->setEnabled(FALSE); -		ctrl_ssao->setValue(FALSE); - -		ctrl_dof->setEnabled(FALSE); -		ctrl_dof->setValue(FALSE); - -		ctrl_deferred->setEnabled(FALSE); -		ctrl_deferred->setValue(FALSE); -	} -	// disabled deferred SSAO +    // disabled deferred SSAO  	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))  	{  		ctrl_ssao->setEnabled(FALSE); @@ -1756,13 +1677,13 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map      if (!LLXMLNode::parseFile(filename, root, NULL))      { -        LL_WARNS() << "Unable to parse file " << filename << LL_ENDL; +        LL_WARNS("Preferences") << "Unable to parse file " << filename << LL_ENDL;          return false;      }      if (!root->hasName("labels"))      { -        LL_WARNS() << filename << " is not a valid definition file" << LL_ENDL; +        LL_WARNS("Preferences") << filename << " is not a valid definition file" << LL_ENDL;          return false;      } @@ -1782,7 +1703,7 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map      }      else      { -        LL_WARNS() << filename << " failed to load" << LL_ENDL; +        LL_WARNS("Preferences") << filename << " failed to load" << LL_ENDL;          return false;      } @@ -2688,7 +2609,7 @@ bool LLPanelPreferenceControls::addControlTableColumns(const std::string &filena      LLScrollListCtrl::Contents contents;      if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode))      { -        LL_WARNS() << "Failed to load " << filename << LL_ENDL; +        LL_WARNS("Preferences") << "Failed to load " << filename << LL_ENDL;          return false;      }      LLXUIParser parser; @@ -2715,7 +2636,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename)      LLScrollListCtrl::Contents contents;      if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode))      { -        LL_WARNS() << "Failed to load " << filename << LL_ENDL; +        LL_WARNS("Preferences") << "Failed to load " << filename << LL_ENDL;          return false;      }      LLXUIParser parser; @@ -2821,7 +2742,7 @@ void LLPanelPreferenceControls::populateControlTable()          {              // Either unknown mode or MODE_SAVED_SETTINGS              // It doesn't have UI or actual settings yet -            LL_WARNS() << "Unimplemented mode" << LL_ENDL; +            LL_WARNS("Preferences") << "Unimplemented mode" << LL_ENDL;              // Searchable columns were removed, mark searchables for an update              LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); @@ -2861,7 +2782,7 @@ void LLPanelPreferenceControls::populateControlTable()      }      else      { -        LL_WARNS() << "Unimplemented mode" << LL_ENDL; +        LL_WARNS("Preferences") << "Unimplemented mode" << LL_ENDL;      }      // explicit update to make sure table is ready for llsearchableui diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 5ef2ca68d3..542df18ddb 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -100,9 +100,8 @@ public:  	static void updateShowFavoritesCheckbox(bool val);  	void processProperties( void* pData, EAvatarProcessorType type ); -	void processProfileProperties(const LLAvatarData* pAvatarData ); -	void storeAvatarProperties( const LLAvatarData* pAvatarData );  	void saveAvatarProperties( void ); +    static void saveAvatarPropertiesCoro(const std::string url, bool allow_publish);  	void selectPrivacyPanel();  	void selectChatPanel();  	void getControlNames(std::vector<std::string>& names); @@ -213,7 +212,7 @@ private:  	bool mOriginalHideOnlineStatus;  	std::string mDirectoryVisibility; -	LLAvatarData mAvatarProperties; +	bool mAllowPublish; // Allow showing agent in search  	std::string mSavedCameraPreset;  	std::string mSavedGraphicsPreset;  	LOG_CLASS(LLFloaterPreference); diff --git a/indra/newview/llfloaterprofile.cpp b/indra/newview/llfloaterprofile.cpp new file mode 100644 index 0000000000..6ccdace6c5 --- /dev/null +++ b/indra/newview/llfloaterprofile.cpp @@ -0,0 +1,170 @@ +/** + * @file llfloaterprofile.cpp + * @brief Avatar profile floater. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterprofile.h" + +#include "llagent.h" //gAgent +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llpanelprofile.h" + +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +LLFloaterProfile::LLFloaterProfile(const LLSD& key) + : LLFloater(key), + mAvatarId(key["id"].asUUID()), + mNameCallbackConnection() +{ +	mDefaultRectForGroup = false; +} + +LLFloaterProfile::~LLFloaterProfile() +{ +    if (mNameCallbackConnection.connected()) +    { +        mNameCallbackConnection.disconnect(); +    } +} + +void LLFloaterProfile::onOpen(const LLSD& key) +{ +    mPanelProfile->onOpen(key); + +    // Update the avatar name. +    mNameCallbackConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLFloaterProfile::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLFloaterProfile::postBuild() +{ +    mPanelProfile = findChild<LLPanelProfile>(PANEL_PROFILE_VIEW); + +    return TRUE; +} + +void LLFloaterProfile::onClickCloseBtn(bool app_quitting) +{ +    if (!app_quitting) +    { +        if (mPanelProfile->hasUnpublishedClassifieds()) +        { +            LLNotificationsUtil::add("ProfileUnpublishedClassified", LLSD(), LLSD(), +                boost::bind(&LLFloaterProfile::onUnsavedChangesCallback, this, _1, _2, false)); +        } +        else if (mPanelProfile->hasUnsavedChanges()) +        { +            LLNotificationsUtil::add("ProfileUnsavedChanges", LLSD(), LLSD(), +                boost::bind(&LLFloaterProfile::onUnsavedChangesCallback, this, _1, _2, true)); +        } +        else +        { +            closeFloater(); +        } +    } +    else +    { +        closeFloater(); +    } +} + +void LLFloaterProfile::onUnsavedChangesCallback(const LLSD& notification, const LLSD& response, bool can_save) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +    if (can_save) +    { +        // savable content + +        if (option == 0) // Save +        { +            mPanelProfile->commitUnsavedChanges(); +            closeFloater(); +        } +        if (option == 1) // Discard +        { +            closeFloater(); +        } +        // else cancel +    } +    else +    { +        // classifieds + +        if (option == 0) // Ok +        { +            closeFloater(); +        } +        // else cancel +    } + +} + +void LLFloaterProfile::createPick(const LLPickData &data) +{ +    mPanelProfile->createPick(data); +} + +void LLFloaterProfile::showPick(const LLUUID& pick_id) +{ +    mPanelProfile->showPick(pick_id); +} + +bool LLFloaterProfile::isPickTabSelected() +{ +    return mPanelProfile->isPickTabSelected(); +} + +void LLFloaterProfile::refreshName() +{ +    if (!mNameCallbackConnection.connected()) +    { +        mNameCallbackConnection = LLAvatarNameCache::get(mAvatarId, boost::bind(&LLFloaterProfile::onAvatarNameCache, this, _1, _2)); +    } + +    LLPanelProfileSecondLife *panel = findChild<LLPanelProfileSecondLife>("panel_profile_secondlife"); +    if (panel) +    { +        panel->refreshName(); +    } +} + +void LLFloaterProfile::showClassified(const LLUUID& classified_id, bool edit) +{ +    mPanelProfile->showClassified(classified_id, edit); +} + +void LLFloaterProfile::createClassified() +{ +    mPanelProfile->createClassified(); +} + +void LLFloaterProfile::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mNameCallbackConnection.disconnect(); +    setTitle(av_name.getCompleteName()); +} + +// eof diff --git a/indra/newview/llfloaterprofile.h b/indra/newview/llfloaterprofile.h new file mode 100644 index 0000000000..b3ed02fc2c --- /dev/null +++ b/indra/newview/llfloaterprofile.h @@ -0,0 +1,66 @@ +/** + * @file llfloaterprofile.h + * @brief Avatar profile floater. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LLFLOATERPROFILE_H +#define LL_LLFLOATERPROFILE_H + +#include "llavatarnamecache.h" +#include "llavatarpropertiesprocessor.h" +#include "llfloater.h" + +class LLPanelProfile; + +class LLFloaterProfile : public LLFloater +{ +    LOG_CLASS(LLFloaterProfile); +public: +    LLFloaterProfile(const LLSD& key); +    virtual ~LLFloaterProfile(); + +    BOOL postBuild() override; + +    void onOpen(const LLSD& key) override; +    void onClickCloseBtn(bool app_quitting = false) override; +    void onUnsavedChangesCallback(const LLSD& notification, const LLSD& response, bool can_save); + +    void createPick(const LLPickData &data); +    void showPick(const LLUUID& pick_id = LLUUID::null); +    bool isPickTabSelected(); +    void refreshName(); + +    void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); +    void createClassified(); + +private: +    LLAvatarNameCache::callback_connection_t mNameCallbackConnection; +    void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +    LLPanelProfile* mPanelProfile; + +    LLUUID mAvatarId; +}; + +#endif // LL_LLFLOATERPROFILE_H diff --git a/indra/newview/llfloaterprofiletexture.cpp b/indra/newview/llfloaterprofiletexture.cpp new file mode 100644 index 0000000000..bf1f56a6d1 --- /dev/null +++ b/indra/newview/llfloaterprofiletexture.cpp @@ -0,0 +1,223 @@ +/**  + * @file llfloaterprofiletexture.cpp + * @brief LLFloaterProfileTexture class implementation + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterprofiletexture.h" + +#include "llbutton.h" +#include "llfloaterreg.h" +#include "llpreview.h" // fors constants +#include "lltrans.h" +#include "llviewercontrol.h" +#include "lltextureview.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" + + + +LLFloaterProfileTexture::LLFloaterProfileTexture(LLView* owner) +    : LLFloater(LLSD()) +    , mUpdateDimensions(TRUE) +    , mLastHeight(0) +    , mLastWidth(0) +    , mImage(NULL) +    , mImageOldBoostLevel(LLGLTexture::BOOST_NONE) +    , mOwnerHandle(owner->getHandle()) +{ +    buildFromFile("floater_profile_texture.xml"); +} + +LLFloaterProfileTexture::~LLFloaterProfileTexture() +{ +    if (mImage.notNull()) +    { +        mImage->setBoostLevel(mImageOldBoostLevel); +        mImage = NULL; +    } +} + +// virtual +BOOL LLFloaterProfileTexture::postBuild() +{ +    mProfileIcon = getChild<LLIconCtrl>("profile_pic"); + +    mCloseButton = getChild<LLButton>("close_btn"); +    mCloseButton->setCommitCallback([this](LLUICtrl*, void*) { closeFloater(); }, nullptr); + +	return TRUE; +} + +// virtual +void LLFloaterProfileTexture::reshape(S32 width, S32 height, BOOL called_from_parent) +{ +	LLFloater::reshape(width, height, called_from_parent); +} + +// It takes a while until we get height and width information. +// When we receive it, reshape the window accordingly. +void LLFloaterProfileTexture::updateDimensions() +{ +    if (mImage.isNull()) +    { +        return; +    } +    if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) +    { +        return; +    } + +    S32 img_width = mImage->getFullWidth(); +    S32 img_height = mImage->getFullHeight(); + +    if (mAssetStatus != LLPreview::PREVIEW_ASSET_LOADED +        || mLastWidth != img_width +        || mLastHeight != img_height) +    { +        mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; +        // Asset has been fully loaded +        mUpdateDimensions = TRUE; +    } + +    mLastHeight = img_height; +    mLastWidth = img_width; + +    // Reshape the floater only when required +    if (mUpdateDimensions) +    { +        mUpdateDimensions = FALSE; + +        LLRect old_floater_rect = getRect(); +        LLRect old_image_rect = mProfileIcon->getRect(); +        S32 width = old_floater_rect.getWidth() - old_image_rect.getWidth() + mLastWidth; +        S32 height = old_floater_rect.getHeight() - old_image_rect.getHeight() + mLastHeight; + +        const F32 MAX_DIMENTIONS = 512; // most profiles are supposed to be 256x256 + +        S32 biggest_dim = llmax(width, height); +        if (biggest_dim > MAX_DIMENTIONS) +        { +            F32 scale_down = MAX_DIMENTIONS / (F32)biggest_dim; +            width *= scale_down; +            height *= scale_down; +        } + +        //reshape floater +        reshape(width, height); + +        gFloaterView->adjustToFitScreen(this, FALSE); +    } +} + +void LLFloaterProfileTexture::draw() +{ +    // drawFrustum +    LLView *owner = mOwnerHandle.get(); +    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); +    drawConeToOwner(mContextConeOpacity, max_opacity, owner); + +    LLFloater::draw(); +} + +void LLFloaterProfileTexture::onOpen(const LLSD& key) +{ +    mCloseButton->setFocus(true); +} + +void LLFloaterProfileTexture::resetAsset() +{ +    mProfileIcon->setValue("Generic_Person_Large"); +    mImageID = LLUUID::null; +    if (mImage.notNull()) +    { +        mImage->setBoostLevel(mImageOldBoostLevel); +        mImage = NULL; +    } +} +void LLFloaterProfileTexture::loadAsset(const LLUUID &image_id) +{ +    if (mImageID != image_id) +    { +        if (mImage.notNull()) +        { +            mImage->setBoostLevel(mImageOldBoostLevel); +            mImage = NULL; +        } +    } +    else +    { +        return; +    } + +    mProfileIcon->setValue(image_id); +    mImageID = image_id; +    mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +    mImageOldBoostLevel = mImage->getBoostLevel(); + +    if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) +    { +        mImage->setLoadedCallback(LLFloaterProfileTexture::onTextureLoaded, +            0, TRUE, FALSE, new LLHandle<LLFloater>(getHandle()), &mCallbackTextureList); + +        mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); +        mAssetStatus = LLPreview::PREVIEW_ASSET_LOADING; +    } +    else +    { +        mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; +    } + +    mUpdateDimensions = TRUE; +    updateDimensions(); +} + +// static +void LLFloaterProfileTexture::onTextureLoaded( +    BOOL success, +    LLViewerFetchedTexture *src_vi, +    LLImageRaw* src, +    LLImageRaw* aux_src, +    S32 discard_level, +    BOOL final, +    void* userdata) +{ +    LLHandle<LLFloater>* handle = (LLHandle<LLFloater>*)userdata; + +    if (!handle->isDead()) +    { +        LLFloaterProfileTexture* floater = static_cast<LLFloaterProfileTexture*>(handle->get()); +        if (floater && success) +        { +            floater->mUpdateDimensions = TRUE; +            floater->updateDimensions(); +        } +    } + +    if (final || !success) +    { +        delete handle; +    } +} diff --git a/indra/newview/llfloaterprofiletexture.h b/indra/newview/llfloaterprofiletexture.h new file mode 100644 index 0000000000..66a61213dd --- /dev/null +++ b/indra/newview/llfloaterprofiletexture.h @@ -0,0 +1,81 @@ +/**  + * @file llfloaterprofiletexture.h + * @brief LLFloaterProfileTexture class definition + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LLFLOATERPROFILETEXTURE_H +#define LL_LLFLOATERPROFILETEXTURE_H + +#include "llfloater.h" +#include "llviewertexture.h" + +class LLButton; +class LLImageRaw; +class LLIconCtrl; + +class LLFloaterProfileTexture : public LLFloater +{ +public: +    LLFloaterProfileTexture(LLView* owner); +    ~LLFloaterProfileTexture(); + +    void draw() override; +    void onOpen(const LLSD& key) override; + +    void resetAsset(); +    void loadAsset(const LLUUID &image_id); + + +    static void onTextureLoaded( +        BOOL success, +        LLViewerFetchedTexture *src_vi, +        LLImageRaw* src, +        LLImageRaw* aux_src, +        S32 discard_level, +        BOOL final, +        void* userdata); + +    void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; +protected: +    BOOL postBuild() override; + +private: +    void updateDimensions(); + +    LLUUID mImageID; +    LLPointer<LLViewerFetchedTexture> mImage; +    S32 mImageOldBoostLevel; +    S32 mAssetStatus; +    F32 mContextConeOpacity; +    S32 mLastHeight; +    S32 mLastWidth; +    BOOL mUpdateDimensions; + +    LLHandle<LLView> mOwnerHandle; +    LLIconCtrl* mProfileIcon; +    LLButton* mCloseButton; + +    LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList; +}; +#endif  // LL_LLFLOATERPROFILETEXTURE_H diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp index de5d59f484..32eb70cd39 100644 --- a/indra/newview/llfloaterspellchecksettings.cpp +++ b/indra/newview/llfloaterspellchecksettings.cpp @@ -259,7 +259,7 @@ BOOL LLFloaterSpellCheckerImport::postBuild(void)  void LLFloaterSpellCheckerImport::onBtnBrowse()  { -	(new LLFilePickerReplyThread(boost::bind(&LLFloaterSpellCheckerImport::importSelectedDictionary, this, _1), LLFilePicker::FFLOAD_DICTIONARY, false))->getFile(); +	LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterSpellCheckerImport::importSelectedDictionary, this, _1), LLFilePicker::FFLOAD_DICTIONARY, false);  }  void LLFloaterSpellCheckerImport::importSelectedDictionary(const std::vector<std::string>& filenames) diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp deleted file mode 100644 index cda4dc8bcc..0000000000 --- a/indra/newview/llfloatertexturefetchdebugger.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/**  - * @file llfloatertexturefetchdebugger.cpp - * @brief LLFloaterTextureFetchDebugger class definition - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloatertexturefetchdebugger.h" - -#include "lluictrlfactory.h" -#include "llbutton.h" -#include "llspinctrl.h" -#include "llresmgr.h" - -#include "llmath.h" -#include "llviewerwindow.h" -#include "llappviewer.h" -#include "lltexturefetch.h" -#include "llviewercontrol.h" -#include "llviewerassetstats.h" //gTextureTimer - -LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key) -	: LLFloater(key), -	mDebugger(NULL) -{ -	setTitle("Texture Fetching Debugger Floater"); -	 -	mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio",	boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this)); - -	mCommitCallbackRegistrar.add("TexFetchDebugger.Start",	boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.Clear",	boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.Close",	boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.ResetFetchTime",	boost::bind(&LLFloaterTextureFetchDebugger::onClickResetFetchTime, this)); - -	mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead",	boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite",	boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad",	boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.Decode",	boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture",	boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this)); - -	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllCache",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllCache, this)); -	mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllHTTP",	boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP, this)); -} -//---------------------------------------------- - -BOOL LLFloaterTextureFetchDebugger::postBuild(void)  -{	 -	mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger(); -	mStartStatus = (S32)LLTextureFetchDebugger::IDLE; - -	//set states for buttons -	mButtonStateMap["start_btn"] = true; -	mButtonStateMap["close_btn"] = true; -	mButtonStateMap["clear_btn"] = true; -	mButtonStateMap["cacheread_btn"] = false; -	mButtonStateMap["cachewrite_btn"] = false; -	mButtonStateMap["http_btn"] = false; -	mButtonStateMap["decode_btn"] = false; -	mButtonStateMap["gl_btn"] = false; - -	mButtonStateMap["refetchviscache_btn"] = false; -	mButtonStateMap["refetchvishttp_btn"] = false; -	mButtonStateMap["refetchallcache_btn"] = false; -	mButtonStateMap["refetchallhttp_btn"] = false; - -	updateButtons(); - -	getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio")); - -	return TRUE ; -} - -LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger() -{ -	//stop everything -	mDebugger->setStopDebug(); -} - -void LLFloaterTextureFetchDebugger::updateButtons() -{ -	for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter) -	{ -		if(iter->second) -		{ -			childEnable(iter->first.c_str()); -		} -		else -		{ -			childDisable(iter->first.c_str()); -		} -	} -} - -void LLFloaterTextureFetchDebugger::disableButtons() -{ -	childDisable("start_btn"); -	childDisable("clear_btn"); -	childDisable("cacheread_btn"); -	childDisable("cachewrite_btn"); -	childDisable("http_btn"); -	childDisable("decode_btn"); -	childDisable("gl_btn"); -	childDisable("refetchviscache_btn"); -	childDisable("refetchvishttp_btn"); -	childDisable("refetchallcache_btn"); -	childDisable("refetchallhttp_btn"); -} -void LLFloaterTextureFetchDebugger::setStartStatus(S32 status) -{ -	llassert_always(LLTextureFetchDebugger::IDLE == (LLTextureFetchDebugger::e_debug_state)mStartStatus) ; -	mStartStatus = status; -} -	 -bool LLFloaterTextureFetchDebugger::idleStart() -{ -	if(mStartStatus != (S32)LLTextureFetchDebugger::IDLE) -	{ -		mDebugger->startWork((LLTextureFetchDebugger::e_debug_state)mStartStatus); -		mStartStatus = (S32)LLTextureFetchDebugger::IDLE; -		return true; -	} - -	return false; -} - -void LLFloaterTextureFetchDebugger::idle() -{	 -	if(idleStart()) -	{ -		return; -	} - -	const F32 max_time = 0.005f; //5ms -	LLTextureFetchDebugger::e_debug_state state = mDebugger->getState();	 -	if(mDebugger->update(max_time)) -	{ -		switch(state) -		{ -		case LLTextureFetchDebugger::IDLE: -			break; -		case LLTextureFetchDebugger::START_DEBUG: -			mButtonStateMap["cacheread_btn"] = true; -			mButtonStateMap["http_btn"] = true; -			mButtonStateMap["refetchviscache_btn"] = true; -			mButtonStateMap["refetchvishttp_btn"] = true; -			mButtonStateMap["refetchallcache_btn"] = true; -			mButtonStateMap["refetchallhttp_btn"] = true; -			break; -		case LLTextureFetchDebugger::READ_CACHE:			 -			mButtonStateMap["decode_btn"] = true;			 -			break; -		case LLTextureFetchDebugger::WRITE_CACHE:			 -			break; -		case LLTextureFetchDebugger::DECODING: -			mButtonStateMap["gl_btn"] = true;			 -			break; -		case LLTextureFetchDebugger::HTTP_FETCHING: -			mButtonStateMap["cacheread_btn"] = true; -			mButtonStateMap["cachewrite_btn"] = true; -			mButtonStateMap["decode_btn"] = true;			 -			break; -		case LLTextureFetchDebugger::GL_TEX:			 -			break; -		case LLTextureFetchDebugger::REFETCH_VIS_CACHE:			 -			break; -		case LLTextureFetchDebugger::REFETCH_VIS_HTTP:			 -			break; -		case LLTextureFetchDebugger::REFETCH_ALL_CACHE:			 -			break; -		case LLTextureFetchDebugger::REFETCH_ALL_HTTP: -			break; -		default: -			break; -		} - -		if(state != LLTextureFetchDebugger::IDLE) -		{ -			updateButtons(); -		} -	} -} - -//---------------------- -void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio() -{ -	gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal()); -} - -void LLFloaterTextureFetchDebugger::onClickStart() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::START_DEBUG);	 - -	mButtonStateMap["start_btn"] = false; - -	updateButtons(); -} - -void LLFloaterTextureFetchDebugger::onClickClose() -{ -	setVisible(FALSE); -	 -	//stop everything -	mDebugger->setStopDebug(); - -	delete this; -} - -void LLFloaterTextureFetchDebugger::onClickResetFetchTime() -{ -	gTextureTimer.start(); -	gTextureTimer.pause(); -} - -void LLFloaterTextureFetchDebugger::onClickClear() -{ -	mButtonStateMap["start_btn"] = true; -	mButtonStateMap["close_btn"] = true; -	mButtonStateMap["clear_btn"] = true; -	mButtonStateMap["cacheread_btn"] = false; -	mButtonStateMap["cachewrite_btn"] = false; -	mButtonStateMap["http_btn"] = false; -	mButtonStateMap["decode_btn"] = false; -	mButtonStateMap["gl_btn"] = false; -	mButtonStateMap["refetchviscache_btn"] = true; -	mButtonStateMap["refetchvishttp_btn"] = true; -	updateButtons(); - -	//stop everything -	mDebugger->setStopDebug(); -	mDebugger->clearHistory(); -} - -void LLFloaterTextureFetchDebugger::onClickCacheRead() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::READ_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickCacheWrite() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::WRITE_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickHTTPLoad() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::HTTP_FETCHING); -} - -void LLFloaterTextureFetchDebugger::onClickDecode() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::DECODING); -} - -void LLFloaterTextureFetchDebugger::onClickGLTexture() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::GL_TEX);	 -} - -void LLFloaterTextureFetchDebugger::onClickRefetchVisCache() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_HTTP);	 -} - -void LLFloaterTextureFetchDebugger::onClickRefetchAllCache() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP() -{ -	disableButtons(); - -	setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_HTTP);	 -} - -void LLFloaterTextureFetchDebugger::draw() -{ -	//total number of fetched textures -	{ -		getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures())); -	} - -	//total number of fetching requests -	{ -		getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests())); -	} - -	//total number of cache hits -	{ -		getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits())); -	} - -	//total number of visible textures -	{ -		getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures())); -	} - -	//total number of visible texture fetching requests -	{ -		getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests())); -	} - -	//total number of fetched data -	{ -		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10));		 -		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10)); -		getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f)); -	} - -	//total number of visible fetched data -	{		 -		getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10));		 -		getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10)); -	} - -	//total number of rendered fetched data -	{ -		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10));		 -		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10)); -		getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f)); -	} - -	//total time on cache readings -	if(mDebugger->getCacheReadTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime())); -	} - -	//total time on cache writings -	if(mDebugger->getCacheWriteTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime())); -	} - -	//total time on decoding -	if(mDebugger->getDecodeTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime())); -	} - -	//total time on gl texture creation -	if(mDebugger->getGLCreationTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime())); -	} - -	//total time on HTTP fetching -	if(mDebugger->getHTTPTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime())); -	} - -	//total time on entire fetching -	{ -		getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime())); -	} - -	//total time on refetching visible textures from cache -	if(mDebugger->getRefetchVisCacheTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime())); -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10)); -		getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f)); -	} - -	//total time on refetching all textures from cache -	if(mDebugger->getRefetchAllCacheTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllCacheTime())); -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10)); -		getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f)); -	} - -	//total time on refetching visible textures from http -	if(mDebugger->getRefetchVisHTTPTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime())); -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10)); -		getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f)); -	} - -	//total time on refetching all textures from http -	if(mDebugger->getRefetchAllHTTPTime() < 0.f) -	{ -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", std::string("----")); -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", std::string("----")); -	} -	else -	{ -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllHTTPTime())); -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10)); -		getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f)); -	} - -	LLFloater::draw(); -} diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h deleted file mode 100644 index 637f3b03e5..0000000000 --- a/indra/newview/llfloatertexturefetchdebugger.h +++ /dev/null @@ -1,77 +0,0 @@ -/**  - * @file llfloatertexturefetchdebugger.h - * @brief texture fetching debugger window, debug use only - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H -#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H - -#include "llfloater.h" -class LLTextureFetchDebugger; - -class LLFloaterTextureFetchDebugger : public LLFloater -{ -	friend class LLFloaterReg; -public: -	/// initialize all the callbacks for the menu - -	virtual BOOL postBuild() ; -	virtual void draw() ; -	 -	void onChangeTexelPixelRatio(); -	 -	void onClickStart(); -	void onClickClear(); -	void onClickClose(); -	void onClickResetFetchTime(); - -	void onClickCacheRead(); -	void onClickCacheWrite(); -	void onClickHTTPLoad(); -	void onClickDecode(); -	void onClickGLTexture(); - -	void onClickRefetchVisCache(); -	void onClickRefetchVisHTTP(); -	void onClickRefetchAllCache(); -	void onClickRefetchAllHTTP(); -public: -	void idle() ; - -private:	 -	LLFloaterTextureFetchDebugger(const LLSD& key); -	virtual ~LLFloaterTextureFetchDebugger(); - -	void updateButtons(); -	void disableButtons(); - -	void setStartStatus(S32 status); -	bool idleStart(); -private:	 -	LLTextureFetchDebugger* mDebugger; -	std::map<std::string, bool> mButtonStateMap; -	S32 mStartStatus; -}; - -#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 0429749e11..77a04bc5d7 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -480,30 +480,61 @@ void LLFloaterTools::refresh()  	else  #endif  	{ -		F32 link_cost  = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost(); -		S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); +        LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +        F32 link_cost = selection->getSelectedLinksetCost(); +        S32 link_count = selection->getRootObjectCount(); +        S32 object_count = selection->getObjectCount(); -		LLCrossParcelFunctor func; -		if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) -		{ -			// Selection crosses parcel bounds. -			// We don't display remaining land capacity in this case. -			const LLStringExplicit empty_str(""); -			childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", empty_str); -		} -		else -		{ -			LLViewerObject* selected_object = mObjectSelection->getFirstObject(); -			if (selected_object) -			{ -				// Select a parcel at the currently selected object's position. -				LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); -			} -			else -			{ -				LL_WARNS() << "Failed to get selected object" << LL_ENDL; -			} -		} +        LLCrossParcelFunctor func; +        if (!LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true)) +        { +            // Unless multiple parcels selected, higlight parcel object is at. +            LLViewerObject* selected_object = mObjectSelection->getFirstObject(); +            if (selected_object) +            { +                // Select a parcel at the currently selected object's position. +                LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal()); +            } +            else +            { +                LL_WARNS() << "Failed to get selected object" << LL_ENDL; +            } +        } + +        if (object_count == 1) +        { +            // "selection_faces" shouldn't be visible if not LLToolFace::getInstance() +            // But still need to be populated in case user switches + +            std::string faces_str = ""; + +            for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end();) +            { +                LLObjectSelection::iterator nextiter = iter++; // not strictly needed, we have only one object +                LLSelectNode* node = *nextiter; +                LLViewerObject* object = (*nextiter)->getObject(); +                if (!object) +                    continue; +                S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); +                for (S32 te = 0; te < num_tes; ++te) +                { +                    if (node->isTESelected(te)) +                    { +                        if (!faces_str.empty()) +                        { +                            faces_str += ", "; +                        } +                        faces_str += llformat("%d", te); +                    } +                } +            } + +            childSetTextArg("selection_faces", "[FACES_STRING]", faces_str); +        } + +        bool show_faces = (object_count == 1) +                          && LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); +        getChildView("selection_faces")->setVisible(show_faces);  		LLStringUtil::format_map_t selection_args;  		selection_args["OBJ_COUNT"] = llformat("%.1d", link_count); @@ -824,7 +855,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  	bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty();  	getChildView("selection_count")->setVisible(!land_visible && have_selection); -	getChildView("remaining_capacity")->setVisible(!land_visible && have_selection); +    getChildView("selection_faces")->setVisible(LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool() +                                                && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1);  	getChildView("selection_empty")->setVisible(!land_visible && !have_selection);  	mTab->setVisible(!land_visible); @@ -1095,7 +1127,7 @@ void LLFloaterTools::onClickGridOptions()  {  	LLFloater* floaterp = LLFloaterReg::showInstance("build_options");  	// position floater next to build tools, not over -	floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp)); +	floaterp->setShape(gFloaterView->findNeighboringPosition(this, floaterp), true);  }  // static @@ -1181,26 +1213,6 @@ void LLFloaterTools::updateLandImpacts()  		return;  	} -	S32 rezzed_prims = parcel->getSimWidePrimCount(); -	S32 total_capacity = parcel->getSimWideMaxPrimCapacity(); -	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); -	if (region) -	{ -		S32 max_tasks_per_region = (S32)region->getMaxTasks(); -		total_capacity = llmin(total_capacity, max_tasks_per_region); -	} -	std::string remaining_capacity_str = ""; - -	bool show_mesh_cost = gMeshRepo.meshRezEnabled(); -	if (show_mesh_cost) -	{ -		LLStringUtil::format_map_t remaining_capacity_args; -		remaining_capacity_args["LAND_CAPACITY"] = llformat("%d", total_capacity - rezzed_prims); -		remaining_capacity_str = getString("status_remaining_capacity", remaining_capacity_args); -	} - -	childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str); -  	// Update land impacts info in the weights floater  	LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights");  	if(object_weights_floater) diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index e67c79a3a0..67a205417e 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -1023,7 +1023,7 @@ void LLFloaterUIPreview::onClickEditFloater()  void LLFloaterUIPreview::onClickBrowseForEditor()  {      // Let the user choose an executable through the file picker dialog box -    (new LLFilePickerReplyThread(boost::bind(&LLFloaterUIPreview::getExecutablePath, this, _1), LLFilePicker::FFLOAD_EXE, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterUIPreview::getExecutablePath, this, _1), LLFilePicker::FFLOAD_EXE, false);  }  void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filenames) @@ -1077,7 +1077,7 @@ void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filen  void LLFloaterUIPreview::onClickBrowseForDiffs()  {  	// create load dialog box -    (new LLFilePickerReplyThread(boost::bind(&LLFloaterUIPreview::getDiffsFilePath, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterUIPreview::getDiffsFilePath, this, _1), LLFilePicker::FFLOAD_XML, false);  }  void LLFloaterUIPreview::getDiffsFilePath(const std::vector<std::string>& filenames) diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp index 59e1f49f81..23f19dd5aa 100644 --- a/indra/newview/llfloatervoicevolume.cpp +++ b/indra/newview/llfloatervoicevolume.cpp @@ -127,7 +127,7 @@ void LLFloaterVoiceVolume::onOpen(const LLSD& data)  	// Extract appropriate avatar id  	mAvatarID = data["avatar_id"]; -	LLUI::getInstance()->positionViewNearMouse(this); +	LLInspect::repositionInspector(data);  	getChild<LLUICtrl>("avatar_name")->setValue("");  	updateVolumeControls(); diff --git a/indra/newview/llfloaterwebprofile.cpp b/indra/newview/llfloaterwebprofile.cpp deleted file mode 100644 index 891bb90c0e..0000000000 --- a/indra/newview/llfloaterwebprofile.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/**  - * @file llfloaterwebprofile.cpp - * @brief Avatar profile floater. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterwebprofile.h" - -#include "llviewercontrol.h" - -LLFloaterWebProfile::LLFloaterWebProfile(const Params& key) : -	LLFloaterWebContent(key) -{ -} - -void LLFloaterWebProfile::onOpen(const LLSD& key) -{ -	Params p(key); -	p.show_chrome(true); -	p.window_class("profile"); -	p.allow_address_entry(false); -	p.trusted_content(true); -	LLFloaterWebContent::onOpen(p); -	applyPreferredRect(); -} - -// virtual -void LLFloaterWebProfile::handleReshape(const LLRect& new_rect, bool by_user) -{ -	LL_DEBUGS() << "handleReshape: " << new_rect << LL_ENDL; - -	if (by_user && !isMinimized()) -	{ -		LL_DEBUGS() << "Storing new rect" << LL_ENDL; -		gSavedSettings.setRect("WebProfileFloaterRect", new_rect); -	} - -	LLFloaterWebContent::handleReshape(new_rect, by_user); -} - -LLFloater* LLFloaterWebProfile::create(const LLSD& key) -{ -	LLFloaterWebContent::Params p(key); -	preCreate(p); -	return new LLFloaterWebProfile(p); -} - -void LLFloaterWebProfile::applyPreferredRect() -{ -	const LLRect preferred_rect = gSavedSettings.getRect("WebProfileFloaterRect"); -	LL_DEBUGS() << "Applying preferred rect: " << preferred_rect << LL_ENDL; - -	// Don't override position that may have been set by floater stacking code. -	LLRect new_rect = getRect(); -	new_rect.setLeftTopAndSize( -		new_rect.mLeft, new_rect.mTop, -		preferred_rect.getWidth(), preferred_rect.getHeight()); -	setShape(new_rect); -} diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 2c84cd1f93..09235d8fb2 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -45,6 +45,7 @@  //#include "llfirstuse.h"  #include "llfloaterreg.h"		// getTypedInstance()  #include "llfocusmgr.h" +#include "lliconctrl.h"  #include "llinventoryfunctions.h"  #include "llinventorymodel.h"  #include "llinventorymodelbackgroundfetch.h" @@ -307,6 +308,8 @@ BOOL LLFloaterWorldMap::postBuild()  	mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f);  	getChild<LLUICtrl>("zoom slider")->setValue(mCurZoomVal); + +    getChild<LLPanel>("expand_btn_panel")->setMouseDownCallback(boost::bind(&LLFloaterWorldMap::onExpandCollapseBtn, this));  	setDefaultBtn(NULL); @@ -1315,6 +1318,22 @@ void LLFloaterWorldMap::onCopySLURL()  	LLNotificationsUtil::add("CopySLURL", args);  } +void LLFloaterWorldMap::onExpandCollapseBtn() +{ +    LLLayoutStack* floater_stack = getChild<LLLayoutStack>("floater_map_stack"); +    LLLayoutPanel* controls_panel = getChild<LLLayoutPanel>("controls_lp"); +     +    bool toggle_collapse = !controls_panel->isCollapsed(); +    floater_stack->collapsePanel(controls_panel, toggle_collapse); +    floater_stack->updateLayout(); +    +    std::string image_name = getString(toggle_collapse ? "expand_icon" : "collapse_icon"); +    std::string tooltip = getString(toggle_collapse ? "expand_tooltip" : "collapse_tooltip"); +    getChild<LLIconCtrl>("expand_collapse_icon")->setImage(LLUI::getUIImage(image_name)); +    getChild<LLIconCtrl>("expand_collapse_icon")->setToolTip(tooltip); +    getChild<LLPanel>("expand_btn_panel")->setToolTip(tooltip); +} +  // protected  void LLFloaterWorldMap::centerOnTarget(BOOL animate)  { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 14a9c26fb9..fcb55e9666 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -130,6 +130,8 @@ protected:  	void			onShowAgentBtn();  	void			onCopySLURL(); +    void            onExpandCollapseBtn(); +  	void			centerOnTarget(BOOL animate);  	void			updateLocation(); diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 7ecbc6eeac..af00cdd05f 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -30,86 +30,13 @@  #include "llassetstorage.h"  #include "llfilesystem.h"  #include "llsdserialize.h" +#include "lltinygltfhelper.h"  #include "tinygltf/tiny_gltf.h"  #include <strstream>  LLGLTFMaterialList gGLTFMaterialList; -static LLColor4 get_color(const std::vector<double>& in) -{ -    LLColor4 out; -    for (S32 i = 0; i < llmin((S32)in.size(), 4); ++i) -    { -        out.mV[i] = in[i]; -    } - -    return out; -} - -static void set_from_model(LLGLTFMaterial* mat, tinygltf::Model& model) -{ -     -    S32 index; -     -    auto& material_in = model.materials[0]; - -    // get albedo texture -    index = material_in.pbrMetallicRoughness.baseColorTexture.index; -    if (index >= 0) -    { -        mat->mAlbedoId.set(model.images[index].uri); -    } -    else -    { -        mat->mAlbedoId.setNull(); -    } - -    // get normal map -    index = material_in.normalTexture.index; -    if (index >= 0) -    { -        mat->mNormalId.set(model.images[index].uri); -    } -    else -    { -        mat->mNormalId.setNull(); -    } - -    // get metallic-roughness texture -    index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index; -    if (index >= 0) -    { -        mat->mMetallicRoughnessId.set(model.images[index].uri); -    } -    else -    { -        mat->mMetallicRoughnessId.setNull(); -    } - -    // get emissive texture -    index = material_in.emissiveTexture.index; -    if (index >= 0) -    { -        mat->mEmissiveId.set(model.images[index].uri); -    } -    else -    { -        mat->mEmissiveId.setNull(); -    } - -    mat->setAlphaMode(material_in.alphaMode); -    mat->mAlphaCutoff = material_in.alphaCutoff; - -    mat->mAlbedoColor = get_color(material_in.pbrMetallicRoughness.baseColorFactor); -    mat->mEmissiveColor = get_color(material_in.emissiveFactor); - -    mat->mMetallicFactor = material_in.pbrMetallicRoughness.metallicFactor; -    mat->mRoughnessFactor = material_in.pbrMetallicRoughness.roughnessFactor; - -    mat->mDoubleSided = material_in.doubleSided; -} -  LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)  {      List::iterator iter = mList.find(id); @@ -158,7 +85,7 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)                                  if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))                                  { -                                    set_from_model(mat, model_in); +                                    LLTinyGLTFHelper::setFromModel(mat, model_in);                                  }                                  else                                  { @@ -184,3 +111,13 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)      return iter->second;  } +void LLGLTFMaterialList::addMaterial(const LLUUID& id, LLGLTFMaterial* material) +{ +    mList[id] = material; +} + +void LLGLTFMaterialList::removeMaterial(const LLUUID& id) +{ +    mList.erase(id); +} + diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index c22134c468..49760504e6 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -41,6 +41,9 @@ public:      LLGLTFMaterial* getMaterial(const LLUUID& id); +    void addMaterial(const LLUUID& id, LLGLTFMaterial* material); +    void removeMaterial(const LLUUID& id); +  };  extern LLGLTFMaterialList gGLTFMaterialList; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 62414d3bbb..32af2592d3 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -45,7 +45,6 @@  #include "llvoiceclient.h"  static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); -S32 LLGroupListItem::sIconWidth = 0;  class LLGroupComparator : public LLFlatListView::ItemComparator  { @@ -65,21 +64,81 @@ public:  	}  }; -static const LLGroupComparator GROUP_COMPARATOR; +class LLSharedGroupComparator : public LLFlatListView::ItemComparator +{ +public: +    LLSharedGroupComparator() {}; + +    /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const +    { +        const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1); +        std::string name1 = group_item1->getGroupName(); +        bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true); + +        const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2); +        std::string name2 = group_item2->getGroupName(); +        bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true); +        if (item2_shared != item1_shared) +        { +            return item1_shared; +        } + +        LLStringUtil::toUpper(name1); +        LLStringUtil::toUpper(name2); + +        return name1 < name2; +    } +}; + +static LLGroupComparator GROUP_COMPARATOR; +static LLSharedGroupComparator SHARED_GROUP_COMPARATOR; + +LLGroupList::Params::Params() +: for_agent("for_agent", true) +{ +}  LLGroupList::LLGroupList(const Params& p)  :	LLFlatListViewEx(p) +    , mForAgent(p.for_agent)  	, mDirty(true) // to force initial update +    , mShowIcons(false) +    , mShowNone(true)  { -	// Listen for agent group changes. -	gAgent.addListener(this, "new group"); - -	mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");  	setCommitOnSelectionChange(true);  	// Set default sort order. -	setComparator(&GROUP_COMPARATOR); +    if (mForAgent) +    { +        setComparator(&GROUP_COMPARATOR); +    } +    else +    { +        // shared groups first +        setComparator(&SHARED_GROUP_COMPARATOR); +    } + +    if (mForAgent) +	{ +        enableForAgent(true); +    } +} + +LLGroupList::~LLGroupList() +{ +    if (mForAgent) gAgent.removeListener(this); +    if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); +} + +void LLGroupList::enableForAgent(bool show_icons) +{ +    mForAgent = true; + +    mShowIcons = mForAgent && gSavedSettings.getBOOL("GroupListShowIcons") && show_icons; + +    // Listen for agent group changes. +    gAgent.addListener(this, "new group");  	// Set up context menu.  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -94,12 +153,6 @@ LLGroupList::LLGroupList(const Params& p)  		mContextMenuHandle = context_menu->getHandle();  } -LLGroupList::~LLGroupList() -{ -	gAgent.removeListener(this); -	if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); -} -  // virtual  void LLGroupList::draw()  { @@ -114,12 +167,15 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); -	LLToggleableMenu* context_menu = mContextMenuHandle.get(); -	if (context_menu && size() > 0) -	{ -		context_menu->buildDrawLabels(); -		context_menu->updateParent(LLMenuGL::sMenuContainer); -		LLMenuGL::showPopup(this, context_menu, x, y); +    if (mForAgent) +    { +        LLToggleableMenu* context_menu = mContextMenuHandle.get(); +        if (context_menu && size() > 0) +        { +            context_menu->buildDrawLabels(); +            context_menu->updateParent(LLMenuGL::sMenuContainer); +            LLMenuGL::showPopup(this, context_menu, x, y); +        }  	}  	return handled; @@ -132,7 +188,7 @@ BOOL LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask)  	// Handle double click only for the selected item in the list, skip clicks on empty space.  	if (handled)  	{ -		if (mDoubleClickSignal) +		if (mDoubleClickSignal && getItemsRect().pointInRect(x, y))  		{  			(*mDoubleClickSignal)(this, x, y, mask);  		} @@ -164,34 +220,49 @@ static bool findInsensitive(std::string haystack, const std::string& needle_uppe  void LLGroupList::refresh()  { -	const LLUUID& 		highlight_id	= gAgent.getGroupID(); -	S32					count			= gAgent.mGroups.size(); -	LLUUID				id; -	bool				have_filter		= !mNameFilter.empty(); - -	clear(); - -	for(S32 i = 0; i < count; ++i) -	{ -		id = gAgent.mGroups.at(i).mID; -		const LLGroupData& group_data = gAgent.mGroups.at(i); -		if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) -			continue; -		addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM); -	} - -	// Sort the list. -	sort(); - -	// Add "none" to list at top if filter not set (what's the point of filtering "none"?). -	// but only if some real groups exists. EXT-4838 -	if (!have_filter && count > 0) -	{ -		std::string loc_none = LLTrans::getString("GroupsNone"); -		addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); -	} - -	selectItemByUUID(highlight_id); +    if (mForAgent) +    { +        const LLUUID& 		highlight_id	= gAgent.getGroupID(); +        S32					count			= gAgent.mGroups.size(); +        LLUUID				id; +        bool				have_filter		= !mNameFilter.empty(); + +        clear(); + +        for(S32 i = 0; i < count; ++i) +        { +            id = gAgent.mGroups.at(i).mID; +            const LLGroupData& group_data = gAgent.mGroups.at(i); +            if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) +                continue; +            addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile); +        } + +        // Sort the list. +        sort(); + +        // Add "none" to list at top if filter not set (what's the point of filtering "none"?). +        // but only if some real groups exists. EXT-4838 +        if (!have_filter && count > 0 && mShowNone) +        { +            std::string loc_none = LLTrans::getString("GroupsNone"); +            addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); +        } + +        selectItemByUUID(highlight_id); +    } +    else +    { +        clear(); + +        for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) +        { +            addNewItem(it->second, it->first, LLUUID::null, ADD_BOTTOM); +        } + +        // Sort the list. +        sort(); +    }  	setDirty(false);  	onCommit(); @@ -212,13 +283,19 @@ void LLGroupList::toggleIcons()  	}  } +void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list) +{ +    mGroups = group_list; +    setDirty(true); +} +  //////////////////////////////////////////////////////////////////////////  // PRIVATE Section  ////////////////////////////////////////////////////////////////////////// -void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos) +void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)  { -	LLGroupListItem* item = new LLGroupListItem(); +	LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons);  	item->setGroupID(id);  	item->setName(name, mNameFilter); @@ -227,7 +304,10 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL  	item->getChildView("info_btn")->setVisible( false);  	item->getChildView("profile_btn")->setVisible( false);  	item->setGroupIconVisible(mShowIcons); - +    if (!mShowIcons) +    { +        item->setVisibleInProfile(visible_in_profile); +    }  	addItem(item, id, pos);  //	setCommentVisible(false); @@ -243,6 +323,29 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD&  		return true;  	} +    if (event->desc() == "value_changed") +    { +        LLSD data = event->getValue(); +        if (data.has("group_id") && data.has("visible")) +        { +            LLUUID group_id = data["group_id"].asUUID(); +            bool visible = data["visible"].asBoolean(); + +            std::vector<LLPanel*> items; +            getItems(items); +            for (std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) +            { +                LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(*it); +                if (item && item->getGroupID() == group_id) +                { +                    item->setVisibleInProfile(visible); +                    break; +                } +            } +        } +        return true; +    } +  	return false;  } @@ -294,21 +397,25 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)  /*          LLGroupListItem implementation                              */  /************************************************************************/ -LLGroupListItem::LLGroupListItem() +LLGroupListItem::LLGroupListItem(bool for_agent, bool show_icons)  :	LLPanel(),  mGroupIcon(NULL),  mGroupNameBox(NULL),  mInfoBtn(NULL), -mGroupID(LLUUID::null) +mProfileBtn(NULL), +mVisibilityHideBtn(NULL), +mVisibilityShowBtn(NULL), +mGroupID(LLUUID::null), +mForAgent(for_agent)  { -	buildFromFile( "panel_group_list_item.xml"); - -	// Remember group icon width including its padding from the name text box, -	// so that we can hide and show the icon again later. -	if (!sIconWidth) -	{ -		sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft; -	} +    if (show_icons) +    { +        buildFromFile( "panel_group_list_item.xml"); +    } +    else +    { +        buildFromFile( "panel_group_list_item_short.xml"); +    }  }  LLGroupListItem::~LLGroupListItem() @@ -325,7 +432,25 @@ BOOL  LLGroupListItem::postBuild()  	mInfoBtn = getChild<LLButton>("info_btn");  	mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this)); -	childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this)); +    mProfileBtn = getChild<LLButton>("profile_btn"); +    mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); }); + +    mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn"); +    if (mVisibilityHideBtn) +    { +        mVisibilityHideBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(false); }); +    } +    mVisibilityShowBtn = findChild<LLButton>("visibility_show_btn"); +    if (mVisibilityShowBtn) +    { +        mVisibilityShowBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(true); }); +    } + +    // Remember group icon width including its padding from the name text box, +    // so that we can hide and show the icon again later. +    // Also note that panel_group_list_item and panel_group_list_item_short +    // have icons of different sizes so we need to figure it per file. +    mIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft;  	return TRUE;  } @@ -344,7 +469,16 @@ void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)  	if (mGroupID.notNull()) // don't show the info button for the "none" group  	{  		mInfoBtn->setVisible(true); -		getChildView("profile_btn")->setVisible( true); +        mProfileBtn->setVisible(true); +        if (mForAgent && mVisibilityHideBtn) +        { +            LLGroupData agent_gdatap; +            if (gAgent.getGroupData(mGroupID, agent_gdatap)) +            { +                mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile); +                mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile); +            } +        }  	}  	LLPanel::onMouseEnter(x, y, mask); @@ -354,7 +488,12 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)  {  	getChildView("hovered_icon")->setVisible( false);  	mInfoBtn->setVisible(false); -	getChildView("profile_btn")->setVisible( false); +    mProfileBtn->setVisible(false); +    if (mVisibilityHideBtn) +    { +        mVisibilityHideBtn->setVisible(false); +        mVisibilityShowBtn->setVisible(false); +    }  	LLPanel::onMouseLeave(x, y, mask);  } @@ -372,7 +511,17 @@ void LLGroupListItem::setGroupID(const LLUUID& group_id)  	mID = group_id;  	mGroupID = group_id; -	setActive(group_id == gAgent.getGroupID()); + +    if (mForAgent) +    { +        // Active group should be bold. +        setBold(group_id == gAgent.getGroupID()); +    } +    else +    { +        // Groups shared with the agent should be bold +        setBold(gAgent.isInGroup(group_id, true)); +    }  	LLGroupMgr::getInstance()->addObserver(this);  } @@ -393,24 +542,28 @@ void LLGroupListItem::setGroupIconVisible(bool visible)  	// Move the group name horizontally by icon size + its distance from the group name.  	LLRect name_rect = mGroupNameBox->getRect(); -	name_rect.mLeft += visible ? sIconWidth : -sIconWidth; +	name_rect.mLeft += visible ? mIconWidth : -mIconWidth;  	mGroupNameBox->setRect(name_rect);  } +void LLGroupListItem::setVisibleInProfile(bool visible) +{ +    mGroupNameBox->setColor(LLUIColorTable::instance().getColor((visible ? "GroupVisibleInProfile" : "GroupHiddenInProfile"), LLColor4::red).get()); +} +  //////////////////////////////////////////////////////////////////////////  // Private Section  ////////////////////////////////////////////////////////////////////////// -void LLGroupListItem::setActive(bool active) +void LLGroupListItem::setBold(bool bold)  {  	// *BUG: setName() overrides the style params. -	// Active group should be bold.  	LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc());  	// *NOTE dzaporozhan  	// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font   	// is predefined as bold (SansSerifSmallBold, for example) -	new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL); +	new_desc.setStyle(bold ? LLFontGL::BOLD : LLFontGL::NORMAL);  	LLFontGL* new_font = LLFontGL::getFont(new_desc);  	mGroupNameStyle.font = new_font; @@ -430,11 +583,25 @@ void LLGroupListItem::onProfileBtnClick()  	LLGroupActions::show(mGroupID);  } +void LLGroupListItem::onVisibilityBtnClick(bool new_visibility) +{ +    LLGroupData agent_gdatap; +    if (gAgent.getGroupData(mGroupID, agent_gdatap)) +    { +        gAgent.setUserGroupFlags(mGroupID, agent_gdatap.mAcceptNotices, new_visibility); +        setVisibleInProfile(new_visibility); +        mVisibilityHideBtn->setVisible(new_visibility); +        mVisibilityShowBtn->setVisible(!new_visibility); +    } +} +  void LLGroupListItem::changed(LLGroupChange gc)  {  	LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); -	if(group_data) -		setGroupIconID(group_data->mInsigniaID); +	if ((gc == GC_ALL || gc == GC_PROPERTIES) && group_data) +    { +        setGroupIconID(group_data->mInsigniaID); +    }  }  //EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 171b77fb00..5cbabb712f 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -50,12 +50,15 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener  public:  	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params>  	{ -		Params(){}; +        Optional<bool> for_agent; +        Params();  	};  	LLGroupList(const Params& p);  	virtual ~LLGroupList(); +    void enableForAgent(bool show_icons); +  	virtual void draw(); // from LLView  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView  	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView @@ -63,13 +66,16 @@ public:  	void setNameFilter(const std::string& filter);  	void toggleIcons();  	bool getIconsVisible() const { return mShowIcons; } +    void setIconsVisible(bool show_icons) { mShowIcons = show_icons; } +    void setShowNone(bool show_none) { mShowNone = show_none; } +    void setGroups(const std::map< std::string,LLUUID> group_list);  	LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); }  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); -	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM); +	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);  	bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes  	bool onContextMenuItemClick(const LLSD& userdata); @@ -80,6 +86,11 @@ private:  	bool mShowIcons;  	bool mDirty;  	std::string mNameFilter; + +    bool mForAgent; +    bool mShowNone; +    typedef std::map< std::string,LLUUID>	group_map_t; +    group_map_t 			mGroups;  };  class LLButton; @@ -90,7 +101,7 @@ class LLGroupListItem : public LLPanel  	, public LLGroupMgrObserver  {  public: -	LLGroupListItem(); +    LLGroupListItem(bool for_agent, bool show_icons);  	~LLGroupListItem();  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setValue(const LLSD& value); @@ -106,19 +117,26 @@ public:  	void setGroupIconVisible(bool visible);  	virtual void changed(LLGroupChange gc); + +    void setVisibleInProfile(bool visible);  private: -	void setActive(bool active); +	void setBold(bool bold);  	void onInfoBtnClick();  	void onProfileBtnClick(); +    void onVisibilityBtnClick(bool new_visibility);  	LLTextBox*	mGroupNameBox;  	LLUUID		mGroupID;  	LLGroupIconCtrl* mGroupIcon; -	LLButton*	mInfoBtn; +    LLButton*	mInfoBtn; +    LLButton*	mProfileBtn; +    LLButton*	mVisibilityHideBtn; +    LLButton*	mVisibilityShowBtn;  	std::string	mGroupName; +    bool        mForAgent;  	LLStyle::Params mGroupNameStyle; -	static S32	sIconWidth; // icon width + padding +	S32	mIconWidth;  };  #endif // LL_LLGROUPLIST_H diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp index 479e8f9abf..f382b5985f 100644 --- a/indra/newview/llinspect.cpp +++ b/indra/newview/llinspect.cpp @@ -147,3 +147,19 @@ bool LLInspect::childHasVisiblePopupMenu()  	}  	return false;  } + +void LLInspect::repositionInspector(const LLSD& data) +{ +	// Position the inspector relative to the mouse cursor +	// Similar to how tooltips are positioned +	// See LLToolTipMgr::createToolTip +	if (data.has("pos")) +	{ +		LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); +	} +	else +	{ +		LLUI::getInstance()->positionViewNearMouse(this); +	} +	applyRectControl(); +} diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h index 1f6aafc7bd..6909aa3f16 100644 --- a/indra/newview/llinspect.h +++ b/indra/newview/llinspect.h @@ -49,6 +49,8 @@ public:  	/// Inspectors close themselves when they lose focus  	/*virtual*/ void onFocusLost(); + +	void repositionInspector(const LLSD& data);  protected: diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 10814ac076..b11c440015 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -45,7 +45,6 @@  #include "llfloater.h"  #include "llfloaterreg.h"  #include "lltextbox.h" -#include "lltooltip.h"	// positionViewNearMouse()  #include "lltrans.h"  class LLFetchAvatarData; @@ -202,17 +201,7 @@ void LLInspectAvatar::onOpen(const LLSD& data)  	// Extract appropriate avatar id  	mAvatarID = data["avatar_id"]; -	// Position the inspector relative to the mouse cursor -	// Similar to how tooltips are positioned -	// See LLToolTipMgr::createToolTip -	if (data.has("pos")) -	{ -		LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); -	} -	else -	{ -		LLUI::getInstance()->positionViewNearMouse(this); -	} +	LLInspect::repositionInspector(data);  	// Generate link to avatar profile.  	LLTextBase* avatar_profile_link = getChild<LLTextBase>("avatar_profile_link"); @@ -348,7 +337,7 @@ void LLInspectAvatar::onClickMuteVolume()  	LLMuteList* mute_list = LLMuteList::getInstance();  	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); -	LLMute mute(mAvatarID, mAvatarName.getDisplayName(), LLMute::AGENT); +	LLMute mute(mAvatarID, mAvatarName.getUserName(), LLMute::AGENT);  	if (!is_muted)  	{  		mute_list->add(mute, LLMute::flagVoiceChat); diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp index fa8a53c546..0a30ab9217 100644 --- a/indra/newview/llinspectgroup.cpp +++ b/indra/newview/llinspectgroup.cpp @@ -38,7 +38,6 @@  #include "llfloater.h"  #include "llfloaterreg.h"  #include "llresmgr.h"	// getMonetaryString() -#include "lltooltip.h"	// positionViewNearMouse()  #include "lltrans.h"  #include "lluictrl.h"  #include "llgroupiconctrl.h" @@ -124,17 +123,7 @@ void LLInspectGroup::onOpen(const LLSD& data)  	setGroupID(data["group_id"]); -	// Position the inspector relative to the mouse cursor -	// Similar to how tooltips are positioned -	// See LLToolTipMgr::createToolTip -	if (data.has("pos")) -	{ -		LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); -	} -	else -	{ -		LLUI::getInstance()->positionViewNearMouse(this); -	} +	LLInspect::repositionInspector(data);  	// can't call from constructor as widgets are not built yet  	requestUpdate(); diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index cb7031971b..5329f10612 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -50,7 +50,6 @@  #include "lltextbox.h"			// for description truncation  #include "lltoggleablemenu.h"  #include "lltrans.h" -#include "llui.h"				// positionViewNearMouse()  #include "lluictrl.h"  class LLViewerObject; @@ -198,17 +197,8 @@ void LLInspectObject::onOpen(const LLSD& data)  	{  		mObjectFace = data["object_face"];  	} -	// Position the inspector relative to the mouse cursor -	// Similar to how tooltips are positioned -	// See LLToolTipMgr::createToolTip -	if (data.has("pos")) -	{ -		LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); -	} -	else -	{ -		LLUI::getInstance()->positionViewNearMouse(this); -	} + +	LLInspect::repositionInspector(data);  	// Promote hovered object to a complete selection, which will also force  	// a request for selected object data off the network diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index 272c8acbd5..77320510a6 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -111,17 +111,7 @@ void LLInspectRemoteObject::onOpen(const LLSD& data)  	// update the inspector with the current object state  	update(); -	// Position the inspector relative to the mouse cursor -	// Similar to how tooltips are positioned -	// See LLToolTipMgr::createToolTip -	if (data.has("pos")) -	{ -		LLUI::getInstance()->positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); -	} -	else -	{ -		LLUI::getInstance()->positionViewNearMouse(this); -	} +	LLInspect::repositionInspector(data);  }  void LLInspectRemoteObject::onClickMap() diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index d0034eff13..68801b0895 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -110,7 +110,7 @@ void LLInspectToast::onOpen(const LLSD& notification_id)  	panel_rect = panel->getRect();  	reshape(panel_rect.getWidth(), panel_rect.getHeight()); -	LLUI::getInstance()->positionViewNearMouse(this); +	LLInspect::repositionInspector(notification_id);  }  // virtual diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 03c6996de6..7abe48709b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -795,6 +795,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  			disabled_items.push_back(std::string("Copy"));  		} +        if (isAgentInventory()) +        { +            items.push_back(std::string("New folder from selected")); +            items.push_back(std::string("Subfolder Separator")); +            std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs(); +            uuid_vec_t ids; +            std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); +            if (!is_only_items_selected(ids) && !is_only_cats_selected(ids)) +            { +                disabled_items.push_back(std::string("New folder from selected")); +            } +        } +  		if (obj->getIsLinkType())  		{  			items.push_back(std::string("Find Original")); @@ -4291,7 +4304,16 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&  			items.push_back(std::string("Conference Chat Folder"));  			items.push_back(std::string("IM All Contacts In Folder"));  		} + +        if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren()) +        { +            items.push_back(std::string("Ungroup folder items")); +        }  	} +    else +    { +        disabled_items.push_back(std::string("New folder from selected")); +    }  #ifndef LL_RELEASE_FOR_DOWNLOAD  	if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index d239b23e83..27edc8148e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1868,6 +1868,86 @@ void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)  	}  } +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids) +{ +    for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) +    { +        LLInventoryItem* inv_item = gInventory.getItem(*it); +        if (inv_item) +        { +            change_item_parent(*it, new_cat_uuid); +        } +        else +        { +            LLInventoryCategory* inv_cat = gInventory.getCategory(*it); +            if (inv_cat && !LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) +            { +                gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false); +            } +        } +    } + +    LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory"); +    if (!floater_inventory) +    { +        LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; +        return; +    } +    LLSidepanelInventory *sidepanel_inventory =	LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); +    if (sidepanel_inventory) +    { +        if (sidepanel_inventory->getActivePanel()) +        { +            sidepanel_inventory->getActivePanel()->setSelection(new_cat_uuid, TAKE_FOCUS_YES); +            LLFolderViewItem* fv_folder = sidepanel_inventory->getActivePanel()->getItemByID(new_cat_uuid); +            if (fv_folder) +            { +                fv_folder->setOpen(TRUE); +            } +        } +    } +} + +bool is_only_cats_selected(const uuid_vec_t& selected_uuids) +{ +    for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) +    { +        LLInventoryCategory* inv_cat = gInventory.getCategory(*it); +        if (!inv_cat) +        { +            return false; +        } +    } +    return true; +} + +bool is_only_items_selected(const uuid_vec_t& selected_uuids) +{ +    for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it) +    { +        LLViewerInventoryItem* inv_item = gInventory.getItem(*it); +        if (!inv_item) +        { +            return false; +        } +    } +    return true; +} + + +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name) +{ +    LLInventoryObject* first_item = gInventory.getObject(*selected_uuids.begin()); +    if (!first_item) +    { +        return; +    } + +    inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids); +    gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); + +} +  ///----------------------------------------------------------------------------  /// LLInventoryCollectFunctor implementations  ///---------------------------------------------------------------------------- @@ -2522,6 +2602,81 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root      {          (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile();      } +    else if ("new_folder_from_selected" == action) +    { + +        LLInventoryObject* first_item = gInventory.getObject(*ids.begin()); +        if (!first_item) +        { +            return; +        } +        const LLUUID& parent_uuid = first_item->getParentUUID(); +        for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) +        { +            LLInventoryObject *item = gInventory.getObject(*it); +            if (!item || item->getParentUUID() != parent_uuid) +            { +                LLNotificationsUtil::add("SameFolderRequired"); +                return; +            } +        } +         +        LLSD args; +        args["DESC"] = LLTrans::getString("New Folder"); +  +        LLNotificationsUtil::add("CreateSubfolder", args, LLSD(), +            [ids](const LLSD& notification, const LLSD& response) +        { +            S32 opt = LLNotificationsUtil::getSelectedOption(notification, response); +            if (opt == 0) +            { +                std::string settings_name = response["message"].asString(); + +                LLInventoryObject::correctInventoryName(settings_name); +                if (settings_name.empty()) +                { +                    settings_name = LLTrans::getString("New Folder"); +                } +                move_items_to_new_subfolder(ids, settings_name); +            } +        }); +    } +    else if ("ungroup_folder_items" == action) +    { +        if (selected_uuid_set.size() == 1) +        { +            LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin()); +            if (!inv_cat || LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) +            { +                return; +            } +            const LLUUID &new_cat_uuid = inv_cat->getParentUUID(); +            LLInventoryModel::cat_array_t* cat_array; +            LLInventoryModel::item_array_t* item_array; +            gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array); +            LLInventoryModel::cat_array_t cats = *cat_array; +            LLInventoryModel::item_array_t items = *item_array; + +            for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) +            { +                LLViewerInventoryCategory* cat = *cat_iter; +                if (cat) +                { +                    gInventory.changeCategoryParent(cat, new_cat_uuid, false); +                } +            } +            for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) +            { +                LLViewerInventoryItem* item = *item_iter; +                if(item) +                { +                    gInventory.changeItemParent(item, new_cat_uuid, false); +                } +            } +            gInventory.removeCategory(inv_cat->getUUID()); +            gInventory.notifyObservers(); +        } +    }      else      {          std::set<LLFolderViewItem*>::iterator set_iter; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 8915bfa1e0..ba9f157e47 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -93,6 +93,10 @@ LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);  S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);  void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id); +void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name); +void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); +bool is_only_cats_selected(const uuid_vec_t& selected_uuids); +bool is_only_items_selected(const uuid_vec_t& selected_uuids);  /**                    Miscellaneous global functions   **                                                                            ** diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index 12bb609df8..de6a850b57 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -298,31 +298,41 @@ LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem  	applyXUILayout(icon_params, this);  	mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); -	if (mIconCtrl) -	{ -		addChild(mIconCtrl); -	} -	else +    if (!mIconCtrl)  	{  		LLIconCtrl::Params icon_params;  		icon_params.name = "item_icon";  		mIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);  	} +    if (mIconCtrl) +    { +        addChild(mIconCtrl); +    } +    else +    { +        LL_ERRS() << "Failed to create mIconCtrl" << LL_ENDL; +    } +  	LLTextBox::Params text_params(params.item_name);  	applyXUILayout(text_params, this);  	mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params); -	if (mTitleCtrl) +	if (!mTitleCtrl)  	{ -		addChild(mTitleCtrl); -	} -	else -	{ -		LLTextBox::Params text_aprams; +		LLTextBox::Params text_params;  		text_params.name = "item_title";  		mTitleCtrl = LLUICtrlFactory::create<LLTextBox>(text_params);  	} + +    if (mTitleCtrl) +    { +        addChild(mTitleCtrl); +    } +    else +    { +        LL_ERRS() << "Failed to create mTitleCtrl" << LL_ENDL; +    }  }  class WidgetVisibilityChanger diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 37500176ea..c101033a5d 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -222,8 +222,6 @@ LLInventoryModel::LLInventoryModel()  	mHttpOptions(),  	mHttpHeaders(),  	mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), -	mHttpPriorityFG(0), -	mHttpPriorityBG(0),  	mCategoryLock(),  	mItemLock(),  	mValidationInfo(new LLInventoryValidationInfo) @@ -2799,7 +2797,6 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,  	handle = LLCoreHttpUtil::requestPostWithLLSD(request,  												 mHttpPolicyClass, -												 (foreground ? mHttpPriorityFG : mHttpPriorityBG),  												 url,  												 body,  												 mHttpOptions, diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index eeec89bfb0..85343cf95c 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -617,8 +617,6 @@ private:  	LLCore::HttpOptions::ptr_t			mHttpOptions;  	LLCore::HttpHeaders::ptr_t			mHttpHeaders;  	LLCore::HttpRequest::policy_t		mHttpPolicyClass; -	LLCore::HttpRequest::priority_t		mHttpPriorityFG; -	LLCore::HttpRequest::priority_t		mHttpPriorityBG;  /**                    HTTP Transport   **                                                                            ** diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b102c7500..cd24b3ea43 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2010,7 +2010,43 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)  void LLAssetFilteredInventoryPanel::initFromParams(const Params& p)  { -    mAssetType = LLAssetType::lookup(p.filter_asset_type.getValue()); +    // Init asset types +    std::string types = p.filter_asset_types.getValue(); + +    typedef boost::tokenizer<boost::char_separator<char> > tokenizer; +    boost::char_separator<char> sep("|"); +    tokenizer tokens(types, sep); +    tokenizer::iterator token_iter = tokens.begin(); + +    memset(mAssetTypes, 0, LLAssetType::AT_COUNT * sizeof(bool)); +    while (token_iter != tokens.end()) +    { +        const std::string& token_str = *token_iter; +        LLAssetType::EType asset_type = LLAssetType::lookup(token_str); +        if (asset_type > LLAssetType::AT_NONE && asset_type < LLAssetType::AT_COUNT) +        { +            mAssetTypes[asset_type] = true; +        } +        ++token_iter; +    } + +    // Init drag types +    memset(mDragTypes, 0, EDragAndDropType::DAD_COUNT * sizeof(bool)); +    for (S32 i = 0; i < LLAssetType::AT_COUNT; i++) +    { +        if (mAssetTypes[i]) +        { +            EDragAndDropType drag_type = LLViewerAssetType::lookupDragAndDropType((LLAssetType::EType)i); +            if (drag_type != DAD_NONE) +            { +                mDragTypes[drag_type] = true; +            } +        } +    } +    // Always show AT_CATEGORY, but it shouldn't get into mDragTypes +    mAssetTypes[LLAssetType::AT_CATEGORY] = true; + +    // Init the panel      LLInventoryPanel::initFromParams(p);      U64 filter_cats = getFilter().getFilterCategoryTypes();      filter_cats &= ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS); @@ -2028,10 +2064,9 @@ BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, B      if (mAcceptsDragAndDrop)      { -        EDragAndDropType allow_type = LLViewerAssetType::lookupDragAndDropType(mAssetType);          // Don't allow DAD_CATEGORY here since it can contain other items besides required assets          // We should see everything we drop! -        if (allow_type == cargo_type) +        if (mDragTypes[cargo_type])          {              result = LLInventoryPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);          } @@ -2047,8 +2082,14 @@ bool LLAssetFilteredInventoryPanel::typedViewsFilter(const LLUUID& id, LLInvento      {          return false;      } +    LLAssetType::EType asset_type = objectp->getType(); -    if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY) +    if (asset_type < 0 || asset_type >= LLAssetType::AT_COUNT) +    { +        return false; +    } + +    if (!mAssetTypes[asset_type])      {          return false;      } @@ -2064,11 +2105,16 @@ void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, cons          return;      } -    if (model_item -        && model_item->getType() != mAssetType -        && model_item->getType() != LLAssetType::AT_CATEGORY) +    if (model_item)      { -        return; +        LLAssetType::EType asset_type = model_item->getType(); + +        if (asset_type < 0 +            || asset_type >= LLAssetType::AT_COUNT +            || !mAssetTypes[asset_type]) +        { +            return; +        }      }      LLInventoryPanel::itemChanged(id, mask, model_item); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 552c61b915..d5219a22e7 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -393,9 +393,9 @@ public:      struct Params          : public LLInitParam::Block<Params, LLInventoryPanel::Params>      { -        Mandatory<std::string>	filter_asset_type; +        Mandatory<std::string>	filter_asset_types; -        Params() : filter_asset_type("filter_asset_type") {} +        Params() : filter_asset_types("filter_asset_types") {}      };      void initFromParams(const Params& p); @@ -416,7 +416,8 @@ protected:      /*virtual*/ void				itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;  private: -    LLAssetType::EType mAssetType; +    bool mAssetTypes[LLAssetType::AT_COUNT]; +    bool mDragTypes[EDragAndDropType::DAD_COUNT];  };  #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 5a17332fde..257208470e 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -47,7 +47,6 @@  /* misc headers */  #include "llscrolllistctrl.h" -#include "llfilepicker.h"  #include "lllocaltextureobject.h"  #include "llviewertexturelist.h"  #include "llviewerobjectlist.h" @@ -62,6 +61,7 @@  #include "pipeline.h"  #include "llmaterialmgr.h"  #include "llimagedimensionsinfo.h" +#include "llinventoryicon.h"  #include "llviewercontrol.h"  #include "lltrans.h"  #include "llviewerdisplay.h" @@ -919,51 +919,49 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr()      mBitmapList.clear();  } -bool LLLocalBitmapMgr::addUnit() +bool LLLocalBitmapMgr::addUnit(const std::vector<std::string>& filenames)  { -	bool add_successful = false; - -	LLFilePicker& picker = LLFilePicker::instance(); -	if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE)) -	{ -		mTimer.stopTimer(); +    bool add_successful = false; +    std::vector<std::string>::const_iterator iter = filenames.begin(); +    while (iter != filenames.end()) +    { +        if (!iter->empty() && addUnit(*iter).notNull()) +        { +            add_successful = true; +        } +        iter++; +    } +    return add_successful; +} -		std::string filename = picker.getFirstFile(); -		while(!filename.empty()) -		{ -			if(!checkTextureDimensions(filename)) -			{ -				filename = picker.getNextFile(); -				continue; -			} +LLUUID LLLocalBitmapMgr::addUnit(const std::string& filename) +{ +    if (!checkTextureDimensions(filename)) +    { +        return LLUUID::null; +    } -			LLLocalBitmap* unit = new LLLocalBitmap(filename); +    LLLocalBitmap* unit = new LLLocalBitmap(filename); -			if (unit->getValid()) -			{ -				mBitmapList.push_back(unit); -				add_successful = true; -			} -			else -			{ -				LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" -					    << "Filename: " << filename << LL_ENDL; - -				LLSD notif_args; -				notif_args["FNAME"] = filename; -				LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); +    if (unit->getValid()) +    { +        mBitmapList.push_back(unit); +        return unit->getTrackingID(); +    } +    else +    { +        LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" +            << "Filename: " << filename << LL_ENDL; -				delete unit; -				unit = NULL; -			} +        LLSD notif_args; +        notif_args["FNAME"] = filename; +        LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); -			filename = picker.getNextFile(); -		} -		 -		mTimer.startTimer(); -	} +        delete unit; +        unit = NULL; +    } -	return add_successful; +    return LLUUID::null;  }  bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename) @@ -1071,7 +1069,9 @@ void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)  {  	if (ctrl)  	{ -		ctrl->clearRows(); +        std::string icon_name = LLInventoryIcon::getIconName( +            LLAssetType::AT_TEXTURE, +            LLInventoryType::IT_NONE);  		if (!mBitmapList.empty())  		{ @@ -1079,13 +1079,19 @@ void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl)  				 iter != mBitmapList.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(); +                element["columns"][0]["column"] = "icon"; +                element["columns"][0]["type"] = "icon"; +                element["columns"][0]["value"] = icon_name; + +                element["columns"][1]["column"] = "unit_name"; +                element["columns"][1]["type"] = "text"; +                element["columns"][1]["value"] = (*iter)->getShortName(); + +                LLSD data; +                data["id"] = (*iter)->getTrackingID(); +                data["type"] = (S32)LLAssetType::AT_TEXTURE; +                element["value"] = data;  				ctrl->addElement(element);  			} diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index d5ee7efdc6..bb026ed3aa 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -115,14 +115,15 @@ class LLLocalBitmapMgr : public LLSingleton<LLLocalBitmapMgr>  	LLSINGLETON(LLLocalBitmapMgr);  	~LLLocalBitmapMgr();  public: -	bool         addUnit(); +    bool         addUnit(const std::vector<std::string>& filenames); +    LLUUID       addUnit(const std::string& filename);  	void         delUnit(LLUUID tracking_id);  	bool 		checkTextureDimensions(std::string filename);  	LLUUID       getWorldID(LLUUID tracking_id);      bool         isLocal(LLUUID world_id);  	std::string  getFilename(LLUUID tracking_id); - +      	void         feedScrollList(LLScrollListCtrl* ctrl);  	void         doUpdates();  	void         setNeedsRebake(); diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp new file mode 100644 index 0000000000..5373400e9d --- /dev/null +++ b/indra/newview/lllocalgltfmaterials.cpp @@ -0,0 +1,523 @@ +/**  + * @file lllocalrendermaterials.cpp + * @brief Local GLTF materials source + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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 "lllocalgltfmaterials.h" + +/* boost: will not compile unless equivalent is undef'd, beware. */ +#include "fix_macros.h" +#include <boost/filesystem.hpp> + +/* time headers */ +#include <time.h> +#include <ctime> + +/* misc headers */ +#include "llgltfmateriallist.h" +#include "llimage.h" +#include "llinventoryicon.h" +#include "llmaterialmgr.h" +#include "llnotificationsutil.h" +#include "llscrolllistctrl.h" +#include "lltinygltfhelper.h" +#include "llviewertexture.h" +#include "tinygltf/tiny_gltf.h" + +/*=======================================*/ +/*  Formal declarations, constants, etc. */ +/*=======================================*/  + +static const F32 LL_LOCAL_TIMER_HEARTBEAT   = 3.0; +static const S32 LL_LOCAL_UPDATE_RETRIES    = 5; + +/*=======================================*/ +/*  LLLocalGLTFMaterial: unit class            */ +/*=======================================*/  +LLLocalGLTFMaterial::LLLocalGLTFMaterial(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 == "gltf") +	{  +		mExtension = ET_MATERIAL_GLTF; +	} +	else if (temp_exten == "glb") +	{ +		mExtension = ET_MATERIAL_GLB; +	} +	else +	{ +		LL_WARNS() << "File of no valid extension given, local material creation aborted." << "\n" +			    << "Filename: " << mFilename << LL_ENDL; +		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(); +} + +LLLocalGLTFMaterial::~LLLocalGLTFMaterial() +{ +	// delete self from material list +    gGLTFMaterialList.removeMaterial(mWorldID); +} + +/* accessors */ +std::string LLLocalGLTFMaterial::getFilename() +{ +	return mFilename; +} + +std::string LLLocalGLTFMaterial::getShortName() +{ +	return mShortName; +} + +LLUUID LLLocalGLTFMaterial::getTrackingID() +{ +	return mTrackingID; +} + +LLUUID LLLocalGLTFMaterial::getWorldID() +{ +	return mWorldID; +} + +bool LLLocalGLTFMaterial::getValid() +{ +	return mValid; +} + +/* update functions */ +bool LLLocalGLTFMaterial::updateSelf() +{ +	bool updated = false; +	 +	if (mLinkStatus == LS_ON) +	{ +		// verifying that the file exists +		if (gDirUtilp->fileExists(mFilename)) +		{ +			// verifying that the file has indeed been modified + +#ifndef LL_WINDOWS +			const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename)); +#else +			const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(utf8str_to_utf16str(mFilename))); +#endif +			LLSD new_last_modified = asctime(localtime(&temp_time)); + +			if (mLastModified.asString() != new_last_modified.asString()) +			{ +				LLPointer<LLGLTFMaterial> raw_material = new LLGLTFMaterial(); +				if (loadMaterial(raw_material)) +				{ +					// decode is successful, we can safely proceed. +                    if (mWorldID.isNull()) +                    { +                        mWorldID.generate(); +                    } +					mLastModified = new_last_modified; + +                    // will replace material if it already exists +                    gGLTFMaterialList.addMaterial(mWorldID, raw_material); + +					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 material while writing to it +				else +				{ +					if (mUpdateRetries) +					{ +						mUpdateRetries--; +					} +					else +					{ +						LL_WARNS() << "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." << LL_ENDL; + +						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 +		{ +			LL_WARNS() << "During the update process, the following file was not found." << "\n"  +			        << "Filename: " << mFilename << "\n" +				    << "Disabling further update attempts for this file." << LL_ENDL; + +			LLSD notif_args; +			notif_args["FNAME"] = mFilename; +			LLNotificationsUtil::add("LocalBitmapsUpdateFileNotFound", notif_args); + +			mLinkStatus = LS_BROKEN; +		} +	} + +	return updated; +} + +bool LLLocalGLTFMaterial::loadMaterial(LLPointer<LLGLTFMaterial> mat) +{ +    bool decode_successful = false; + +    switch (mExtension) +    { +    case ET_MATERIAL_GLTF: +    case ET_MATERIAL_GLB: +    { +            tinygltf::TinyGLTF loader; +            std::string        error_msg; +            std::string        warn_msg; + +            tinygltf::Model model_in; + +            std::string filename_lc = mFilename; +            LLStringUtil::toLower(filename_lc); + +            // Load a tinygltf model fom a file. Assumes that the input filename has already been +            // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. +            if (std::string::npos == filename_lc.rfind(".gltf")) +            {  // file is binary +                decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc); +            } +            else +            {  // file is ascii +                decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc); +            } + +            if (!decode_successful) +            { +                LL_WARNS() << "Cannot Upload Material, error: " << error_msg +                    << ", warning:" << warn_msg +                    << " file: " << mFilename +                    << LL_ENDL; +                break; +            } + +            if (model_in.materials.empty()) +            { +                // materials are missing +                LL_WARNS() << "Cannot Upload Material, Material missing, " << mFilename << LL_ENDL; +                decode_successful = false; +                break; +            } + +            // sets everything, but textures will have inaccurate ids +            LLTinyGLTFHelper::setFromModel(mat, model_in); + +            std::string folder = gDirUtilp->getDirName(filename_lc); +            tinygltf::Material material_in = model_in.materials[0]; + +            // get albedo texture +            LLPointer<LLImageRaw> albedo_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); +            // get normal map +            LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index); +            // get metallic-roughness texture +            LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); +            // get emissive texture +            LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index); +            // get occlusion map if needed +            LLPointer<LLImageRaw> occlusion_img; +            if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) +            { +                occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index); +            } + +            // todo: pass it into local bitmaps? +            LLTinyGLTFHelper::initFetchedTextures(material_in, +                albedo_img, normal_img, mr_img, emissive_img, occlusion_img, +                mAlbedoFetched, mNormalFetched, mMRFetched, mEmissiveFetched); + +            if (mAlbedoFetched) +            { +                mat->mAlbedoId = mAlbedoFetched->getID(); +            } +            if (mNormalFetched) +            { +                mat->mNormalId = mNormalFetched->getID(); +            } +            if (mMRFetched) +            { +                mat->mMetallicRoughnessId = mMRFetched->getID(); +            } +            if (mEmissiveFetched) +            { +                mat->mEmissiveId = mEmissiveFetched->getID(); +            } + +            break; +        } + +        default: +        { +            // separating this into -several- LL_WARNS() 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. + +            LL_WARNS() << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL; +            LL_WARNS() << "Filename: " << mFilename << LL_ENDL; +            LL_WARNS() << "Disabling further update attempts for this file." << LL_ENDL; +            mLinkStatus = LS_BROKEN; +        } +    } + +    return decode_successful; +} + + +/*=======================================*/ +/*  LLLocalGLTFMaterialTimer: timer class      */ +/*=======================================*/ +LLLocalGLTFMaterialTimer::LLLocalGLTFMaterialTimer() : LLEventTimer(LL_LOCAL_TIMER_HEARTBEAT) +{ +} + +LLLocalGLTFMaterialTimer::~LLLocalGLTFMaterialTimer() +{ +} + +void LLLocalGLTFMaterialTimer::startTimer() +{ +    mEventTimer.start(); +} + +void LLLocalGLTFMaterialTimer::stopTimer() +{ +    mEventTimer.stop(); +} + +bool LLLocalGLTFMaterialTimer::isRunning() +{ +    return mEventTimer.getStarted(); +} + +BOOL LLLocalGLTFMaterialTimer::tick() +{ +    // todo: do on idle? No point in timer  +    LLLocalGLTFMaterialMgr::getInstance()->doUpdates(); +    return FALSE; +} + +/*=======================================*/ +/*  LLLocalGLTFMaterialMgr: manager class      */ +/*=======================================*/ +LLLocalGLTFMaterialMgr::LLLocalGLTFMaterialMgr() +{ +} + +LLLocalGLTFMaterialMgr::~LLLocalGLTFMaterialMgr() +{ +    std::for_each(mMaterialList.begin(), mMaterialList.end(), DeletePointer()); +    mMaterialList.clear(); +} + +bool LLLocalGLTFMaterialMgr::addUnit(const std::vector<std::string>& filenames) +{ +    bool add_successful = false; +    std::vector<std::string>::const_iterator iter = filenames.begin(); +    while (iter != filenames.end()) +    { +        if (!iter->empty() && addUnit(*iter).notNull()) +        { +            add_successful = true; +        } +        iter++; +    } +    return add_successful; +} + +LLUUID LLLocalGLTFMaterialMgr::addUnit(const std::string& filename) +{ +    LLLocalGLTFMaterial* unit = new LLLocalGLTFMaterial(filename); + +    if (unit->getValid()) +    { +        mMaterialList.push_back(unit); +        return unit->getTrackingID(); +    } +    else +    { +        LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" +            << "Filename: " << filename << LL_ENDL; + +        LLSD notif_args; +        notif_args["FNAME"] = filename; +        LLNotificationsUtil::add("LocalGLTFVerifyFail", notif_args); + +        delete unit; +        unit = NULL; +    } + +    return LLUUID::null; +} + +void LLLocalGLTFMaterialMgr::delUnit(LLUUID tracking_id) +{ +    if (!mMaterialList.empty()) +    { +        std::vector<LLLocalGLTFMaterial*> to_delete; +        for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++) +        {   /* finding which ones we want deleted and making a separate list */ +            LLLocalGLTFMaterial* unit = *iter; +            if (unit->getTrackingID() == tracking_id) +            { +                to_delete.push_back(unit); +            } +        } + +        for (std::vector<LLLocalGLTFMaterial*>::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. */ +            LLLocalGLTFMaterial* unit = *del_iter; +            mMaterialList.remove(unit); +            delete unit; +            unit = NULL; +        } +    } +} + +LLUUID LLLocalGLTFMaterialMgr::getWorldID(LLUUID tracking_id) +{ +    LLUUID world_id = LLUUID::null; + +    for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++) +    { +        LLLocalGLTFMaterial* unit = *iter; +        if (unit->getTrackingID() == tracking_id) +        { +            world_id = unit->getWorldID(); +        } +    } + +    return world_id; +} + +bool LLLocalGLTFMaterialMgr::isLocal(const LLUUID world_id) +{ +    for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++) +    { +        LLLocalGLTFMaterial* unit = *iter; +        if (unit->getWorldID() == world_id) +        { +            return true; +        } +    } +    return false; +} + +std::string LLLocalGLTFMaterialMgr::getFilename(LLUUID tracking_id) +{ +    std::string filename = ""; + +    for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++) +    { +        LLLocalGLTFMaterial* unit = *iter; +        if (unit->getTrackingID() == tracking_id) +        { +            filename = unit->getFilename(); +        } +    } + +    return filename; +} + +// probably shouldn't be here, but at the moment this mirrors lllocalbitmaps +void LLLocalGLTFMaterialMgr::feedScrollList(LLScrollListCtrl* ctrl) +{ +    if (ctrl) +    { +        if (!mMaterialList.empty()) +        { +            std::string icon_name = LLInventoryIcon::getIconName( +                LLAssetType::AT_MATERIAL, +                LLInventoryType::IT_NONE); + +            for (local_list_iter iter = mMaterialList.begin(); +                iter != mMaterialList.end(); iter++) +            { +                LLSD element; + +                element["columns"][0]["column"] = "icon"; +                element["columns"][0]["type"] = "icon"; +                element["columns"][0]["value"] = icon_name; + +                element["columns"][1]["column"] = "unit_name"; +                element["columns"][1]["type"] = "text"; +                element["columns"][1]["value"] = (*iter)->getShortName(); + +                LLSD data; +                data["id"] = (*iter)->getTrackingID(); +                data["type"] = (S32)LLAssetType::AT_MATERIAL; +                element["value"] = data; + +                ctrl->addElement(element); +            } +        } +    } + +} + +void LLLocalGLTFMaterialMgr::doUpdates() +{ +    // preventing theoretical overlap in cases with huge number of loaded images. +    mTimer.stopTimer(); + +    for (local_list_iter iter = mMaterialList.begin(); iter != mMaterialList.end(); iter++) +    { +        (*iter)->updateSelf(); +    } + +    mTimer.startTimer(); +} + diff --git a/indra/newview/lllocalgltfmaterials.h b/indra/newview/lllocalgltfmaterials.h new file mode 100644 index 0000000000..1bca06ba2a --- /dev/null +++ b/indra/newview/lllocalgltfmaterials.h @@ -0,0 +1,124 @@ +/**  + * @file lllocalrendermaterials.h + * @brief Local GLTF materials header + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LOCALGLTFMATERIALS_H +#define LL_LOCALGLTFMATERIALS_H + +#include "lleventtimer.h" +#include "llpointer.h" + +class LLScrollListCtrl; +class LLGLTFMaterial; +class LLViewerObject; +class LLViewerFetchedTexture; + +class LLLocalGLTFMaterial +{ +public: /* main */ +    LLLocalGLTFMaterial(std::string filename); +    ~LLLocalGLTFMaterial(); + +public: /* accessors */ +    std::string	getFilename(); +    std::string	getShortName(); +    LLUUID		getTrackingID(); +    LLUUID		getWorldID(); +    bool		getValid(); + +public: +    bool updateSelf(); + +private: +    bool loadMaterial(LLPointer<LLGLTFMaterial> raw); + +private: /* private enums */ +    enum ELinkStatus +    { +        LS_ON, +        LS_BROKEN, +    }; + +    enum EExtension +    { +        ET_MATERIAL_GLTF, +        ET_MATERIAL_GLB, +    }; + +private: /* members */ +    std::string mFilename; +    std::string mShortName; +    LLUUID      mTrackingID; +    LLUUID      mWorldID; +    bool        mValid; +    LLSD        mLastModified; +    EExtension  mExtension; +    ELinkStatus mLinkStatus; +    S32         mUpdateRetries; + +    // material needs to maintain textures +    LLPointer<LLViewerFetchedTexture> mAlbedoFetched; +    LLPointer<LLViewerFetchedTexture> mNormalFetched; +    LLPointer<LLViewerFetchedTexture> mMRFetched; +    LLPointer<LLViewerFetchedTexture> mEmissiveFetched; +}; + +class LLLocalGLTFMaterialTimer : public LLEventTimer +{ +public: +    LLLocalGLTFMaterialTimer(); +    ~LLLocalGLTFMaterialTimer(); + +public: +    void startTimer(); +    void stopTimer(); +    bool isRunning(); +    BOOL tick(); +}; + +class LLLocalGLTFMaterialMgr : public LLSingleton<LLLocalGLTFMaterialMgr> +{ +    LLSINGLETON(LLLocalGLTFMaterialMgr); +    ~LLLocalGLTFMaterialMgr(); +public: +    bool         addUnit(const std::vector<std::string>& filenames); +    LLUUID       addUnit(const std::string& filename); +    void         delUnit(LLUUID tracking_id); + +    LLUUID       getWorldID(LLUUID tracking_id); +    bool         isLocal(LLUUID world_id); +    std::string  getFilename(LLUUID tracking_id); + +    void         feedScrollList(LLScrollListCtrl* ctrl); +    void         doUpdates(); + +private: +    std::list<LLLocalGLTFMaterial*>    mMaterialList; +    LLLocalGLTFMaterialTimer           mTimer; +    typedef std::list<LLLocalGLTFMaterial*>::iterator local_list_iter; +}; + +#endif // LL_LOCALGLTFMATERIALS_H + diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 57cd74e0f2..f05f0344bd 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -42,6 +42,7 @@  #include "llselectmgr.h"  #include "llstatusbar.h"	// can_afford_transaction()  #include "llviewerinventory.h" +#include "llinventory.h"  #include "llviewerregion.h"  #include "llvovolume.h"  #include "roles_constants.h" @@ -54,6 +55,7 @@  #include "llfloaterperms.h"  #include "tinygltf/tiny_gltf.h" +#include "lltinygltfhelper.h"  #include <strstream> @@ -62,6 +64,7 @@ const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal";  const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness";  const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive"; +  class LLMaterialEditorCopiedCallback : public LLInventoryCallback  {  public: @@ -164,6 +167,15 @@ void LLMaterialEditor::onClickCloseBtn(bool app_quitting)      }  } +void LLMaterialEditor::onClose(bool app_quitting) +{ +    // todo: will only revert whatever was recently selected, +    // Later should work based of tools floater +    LLSelectMgr::getInstance()->selectionRevertGLTFMaterials(); +     +    LLPreview::onClose(app_quitting); +} +  LLUUID LLMaterialEditor::getAlbedoId()  {      return mAlbedoTextureCtrl->getValue().asUUID(); @@ -648,6 +660,61 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)      return false;  } +/** + * Build a description of the material we just imported. + * Currently this means a list of the textures present but we + * may eventually want to make it more complete - will be guided + * by what the content creators say they need. + */ +const std::string LLMaterialEditor::buildMaterialDescription() +{ +    std::ostringstream desc; +    desc << LLTrans::getString("Material Texture Name Header"); + +    // add the texture names for each just so long as the material +    // we loaded has an entry for it (i think testing the texture  +    // control UUI for NULL is a valid metric for if it was loaded +    // or not but I suspect this code will change a lot so may need +    // to revisit +    if (!mAlbedoTextureCtrl->getValue().asUUID().isNull()) +    { +        desc << mAlbedoName; +        desc << ", "; +    } +    if (!mMetallicTextureCtrl->getValue().asUUID().isNull()) +    { +        desc << mMetallicRoughnessName; +        desc << ", "; +    } +    if (!mEmissiveTextureCtrl->getValue().asUUID().isNull()) +    { +        desc << mEmissiveName; +        desc << ", "; +    } +    if (!mNormalTextureCtrl->getValue().asUUID().isNull()) +    { +        desc << mNormalName; +    } + +    // trim last char if it's a ',' in case there is no normal texture +    // present and the code above inserts one +    // (no need to check for string length - always has initial string) +    std::string::iterator iter = desc.str().end() - 1; +    if (*iter == ',') +    { +        desc.str().erase(iter); +    } + +    // sanitize the material description so that it's compatible with the inventory +    // note: split this up because clang doesn't like operating directly on the +    // str() - error: lvalue reference to type 'basic_string<...>' cannot bind to a +    // temporary of type 'basic_string<...>' +    std::string inv_desc = desc.str(); +    LLInventoryObject::correctInventoryName(inv_desc); + +    return inv_desc; +} +  bool LLMaterialEditor::saveIfNeeded()  {      if (mUploadingTexturesCount > 0) @@ -693,7 +760,7 @@ bool LLMaterialEditor::saveIfNeeded()          LLTransactionID tid;          tid.generate();     // timestamp-based randomization + uniquification          LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); -        std::string res_desc = "Saved Material"; +        std::string res_desc = buildMaterialDescription();          U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner();          LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);          const U8 subtype = NO_INV_SUBTYPE;  // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? @@ -952,18 +1019,15 @@ void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD&  class LLMaterialFilePicker : public LLFilePickerThread  {  public: -    LLMaterialFilePicker(LLMaterialEditor* me); +    LLMaterialFilePicker();      virtual void notify(const std::vector<std::string>& filenames); -    void loadMaterial(const std::string& filename);      static void	textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata); -private: -    LLMaterialEditor* mME; +  }; -LLMaterialFilePicker::LLMaterialFilePicker(LLMaterialEditor* me) +LLMaterialFilePicker::LLMaterialFilePicker()      : LLFilePickerThread(LLFilePicker::FFLOAD_MATERIAL)  { -    mME = me;  }  void LLMaterialFilePicker::notify(const std::vector<std::string>& filenames) @@ -976,82 +1040,20 @@ void LLMaterialFilePicker::notify(const std::vector<std::string>& filenames)      if (filenames.size() > 0)      { -        loadMaterial(filenames[0]); -    } -} - -const tinygltf::Image* get_image_from_texture_index(const tinygltf::Model& model, S32 texture_index) -{ -    if (texture_index >= 0) -    { -        S32 source_idx = model.textures[texture_index].source; -        if (source_idx >= 0) +        LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor"); +        if (me)          { -            return &(model.images[source_idx]); +            me->loadMaterialFromFile(filenames[0]);          }      } - -    return nullptr;  } -static LLImageRaw* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name) -{ -    const tinygltf::Image* image = get_image_from_texture_index(model, texture_index); -    LLImageRaw* rawImage = nullptr; - -    if (image != nullptr &&  -        image->bits == 8 && -        !image->image.empty() && -        image->component <= 4) -    { -        name = image->name; -        rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); -        rawImage->verticalFlip(); -    } - -    return rawImage; -} - -static void strip_alpha_channel(LLPointer<LLImageRaw>& img) -{ -    if (img->getComponents() == 4) -    { -        LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3); -        tmp->copyUnscaled4onto3(img); -        img = tmp; -    } -} - -// copy red channel from src_img to dst_img -// PRECONDITIONS: -// dst_img must be 3 component -// src_img and dst_image must have the same dimensions -static void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img) -{ -    llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight()); -    llassert(dst_img->getComponents() == 3); - -    U32 pixel_count = dst_img->getWidth() * dst_img->getHeight(); -    U8* src = src_img->getData(); -    U8* dst = dst_img->getData(); -    S8 src_components = src_img->getComponents(); - -    for (U32 i = 0; i < pixel_count; ++i) -    { -        dst[i * 3] = src[i * src_components]; -    } -} - -static void pack_textures(tinygltf::Model& model, tinygltf::Material& material,  +static void pack_textures(      LLPointer<LLImageRaw>& albedo_img,      LLPointer<LLImageRaw>& normal_img,      LLPointer<LLImageRaw>& mr_img,      LLPointer<LLImageRaw>& emissive_img,      LLPointer<LLImageRaw>& occlusion_img, -    LLPointer<LLViewerFetchedTexture>& albedo_tex, -    LLPointer<LLViewerFetchedTexture>& normal_tex, -    LLPointer<LLViewerFetchedTexture>& mr_tex, -    LLPointer<LLViewerFetchedTexture>& emissive_tex,      LLPointer<LLImageJ2C>& albedo_j2c,      LLPointer<LLImageJ2C>& normal_j2c,      LLPointer<LLImageJ2C>& mr_j2c, @@ -1059,76 +1061,31 @@ static void pack_textures(tinygltf::Model& model, tinygltf::Material& material,  {      if (albedo_img)      { -        albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true);          albedo_j2c = LLViewerTextureList::convertToUploadFile(albedo_img);      }      if (normal_img)      { -        strip_alpha_channel(normal_img); -        normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true);          normal_j2c = LLViewerTextureList::convertToUploadFile(normal_img);      }      if (mr_img)      { -        strip_alpha_channel(mr_img); - -        if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) -        { -            // occlusion is a distinct texture from pbrMetallicRoughness -            // pack into mr red channel -            int occlusion_idx = material.occlusionTexture.index; -            int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; -            if (occlusion_idx != mr_idx) -            { -                //scale occlusion image to match resolution of mr image -                occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); -              -                copy_red_channel(occlusion_img, mr_img); -            } -        } -    } -    else if (occlusion_img) -    { -        //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over -        mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3); -        mr_img->clear(255, 255, 255); -        copy_red_channel(occlusion_img, mr_img); - -    } - -    if (mr_img) -    { -        mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true);          mr_j2c = LLViewerTextureList::convertToUploadFile(mr_img);      }      if (emissive_img)      { -        strip_alpha_channel(emissive_img); -        emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true);          emissive_j2c = LLViewerTextureList::convertToUploadFile(emissive_img);      }  } -static LLColor4 get_color(const std::vector<double>& in) -{ -    LLColor4 out; -    for (S32 i = 0; i < llmin((S32) in.size(), 4); ++i) -    { -        out.mV[i] = in[i]; -    } - -    return out; -} -  void LLMaterialFilePicker::textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata)  {  } -void LLMaterialFilePicker::loadMaterial(const std::string& filename) +void LLMaterialEditor::loadMaterialFromFile(const std::string& filename)  {      tinygltf::TinyGLTF loader;      std::string        error_msg; @@ -1174,91 +1131,91 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename)      model_out.materials.resize(1);      // get albedo texture -    LLPointer<LLImageRaw> albedo_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, mME->mAlbedoName); +    LLPointer<LLImageRaw> albedo_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, mAlbedoName);      // get normal map -    LLPointer<LLImageRaw> normal_img = get_texture(folder, model_in, material_in.normalTexture.index, mME->mNormalName); +    LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index, mNormalName);      // get metallic-roughness texture -    LLPointer<LLImageRaw> mr_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, mME->mMetallicRoughnessName); +    LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, mMetallicRoughnessName);      // get emissive texture -    LLPointer<LLImageRaw> emissive_img = get_texture(folder, model_in, material_in.emissiveTexture.index, mME->mEmissiveName); +    LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index, mEmissiveName);      // get occlusion map if needed      LLPointer<LLImageRaw> occlusion_img;      if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index)      {          std::string tmp; -        occlusion_img = get_texture(folder, model_in, material_in.occlusionTexture.index, tmp); +        occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index, tmp);      } -    pack_textures(model_in, material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img, -        mME->mAlbedoFetched, mME->mNormalFetched, mME->mMetallicRoughnessFetched, mME->mEmissiveFetched, -        mME->mAlbedoJ2C, mME->mNormalJ2C, mME->mMetallicRoughnessJ2C, mME->mEmissiveJ2C); +    LLTinyGLTFHelper::initFetchedTextures(material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img, +        mAlbedoFetched, mNormalFetched, mMetallicRoughnessFetched, mEmissiveFetched); +    pack_textures(albedo_img, normal_img, mr_img, emissive_img, occlusion_img, +        mAlbedoJ2C, mNormalJ2C, mMetallicRoughnessJ2C, mEmissiveJ2C);      LLUUID albedo_id; -    if (mME->mAlbedoFetched.notNull()) +    if (mAlbedoFetched.notNull())      { -        mME->mAlbedoFetched->forceToSaveRawImage(0, F32_MAX); -        albedo_id = mME->mAlbedoFetched->getID(); +        mAlbedoFetched->forceToSaveRawImage(0, F32_MAX); +        albedo_id = mAlbedoFetched->getID(); -        if (mME->mAlbedoName.empty()) +        if (mAlbedoName.empty())          { -            mME->mAlbedoName = MATERIAL_ALBEDO_DEFAULT_NAME; +            mAlbedoName = MATERIAL_ALBEDO_DEFAULT_NAME;          }      }      LLUUID normal_id; -    if (mME->mNormalFetched.notNull()) +    if (mNormalFetched.notNull())      { -        mME->mNormalFetched->forceToSaveRawImage(0, F32_MAX); -        normal_id = mME->mNormalFetched->getID(); +        mNormalFetched->forceToSaveRawImage(0, F32_MAX); +        normal_id = mNormalFetched->getID(); -        if (mME->mNormalName.empty()) +        if (mNormalName.empty())          { -            mME->mNormalName = MATERIAL_NORMAL_DEFAULT_NAME; +            mNormalName = MATERIAL_NORMAL_DEFAULT_NAME;          }      }      LLUUID mr_id; -    if (mME->mMetallicRoughnessFetched.notNull()) +    if (mMetallicRoughnessFetched.notNull())      { -        mME->mMetallicRoughnessFetched->forceToSaveRawImage(0, F32_MAX); -        mr_id = mME->mMetallicRoughnessFetched->getID(); +        mMetallicRoughnessFetched->forceToSaveRawImage(0, F32_MAX); +        mr_id = mMetallicRoughnessFetched->getID(); -        if (mME->mMetallicRoughnessName.empty()) +        if (mMetallicRoughnessName.empty())          { -            mME->mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME; +            mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME;          }      }      LLUUID emissive_id; -    if (mME->mEmissiveFetched.notNull()) +    if (mEmissiveFetched.notNull())      { -        mME->mEmissiveFetched->forceToSaveRawImage(0, F32_MAX); -        emissive_id = mME->mEmissiveFetched->getID(); +        mEmissiveFetched->forceToSaveRawImage(0, F32_MAX); +        emissive_id = mEmissiveFetched->getID(); -        if (mME->mEmissiveName.empty()) +        if (mEmissiveName.empty())          { -            mME->mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME; +            mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME;          }      } -    mME->setAlbedoId(albedo_id); -    mME->setAlbedoUploadId(albedo_id); -    mME->setMetallicRoughnessId(mr_id); -    mME->setMetallicRoughnessUploadId(mr_id); -    mME->setEmissiveId(emissive_id); -    mME->setEmissiveUploadId(emissive_id); -    mME->setNormalId(normal_id); -    mME->setNormalUploadId(normal_id); +    setAlbedoId(albedo_id); +    setAlbedoUploadId(albedo_id); +    setMetallicRoughnessId(mr_id); +    setMetallicRoughnessUploadId(mr_id); +    setEmissiveId(emissive_id); +    setEmissiveUploadId(emissive_id); +    setNormalId(normal_id); +    setNormalUploadId(normal_id); -    mME->setFromGltfModel(model_in); +    setFromGltfModel(model_in); -    std::string new_material = LLTrans::getString("New Material"); -    mME->setMaterialName(new_material); +    setFromGltfMetaData(filename_lc, model_in); -    mME->setHasUnsavedChanges(true); -    mME->openFloater(); +    setHasUnsavedChanges(true); +    openFloater(); -    mME->applyToSelection(); +    applyToSelection();  }  bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_textures) @@ -1324,8 +1281,8 @@ bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_texture          setAlphaMode(material_in.alphaMode);          setAlphaCutoff(material_in.alphaCutoff); -        setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor)); -        setEmissiveColor(get_color(material_in.emissiveFactor)); +        setAlbedoColor(LLTinyGLTFHelper::getColor(material_in.pbrMetallicRoughness.baseColorFactor)); +        setEmissiveColor(LLTinyGLTFHelper::getColor(material_in.emissiveFactor));          setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor);          setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor); @@ -1336,39 +1293,253 @@ bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_texture      return true;  } +/** + * Build a texture name from the contents of the (in tinyGLFT parlance)  + * Image URI. This often is filepath to the original image on the users' + *  local file system. + */ +const std::string LLMaterialEditor::getImageNameFromUri(std::string image_uri, const std::string texture_type) +{ +    // getBaseFileName() works differently on each platform and file patchs  +    // can contain both types of delimiter so unify them then extract the  +    // base name (no path or extension) +    std::replace(image_uri.begin(), image_uri.end(), '\\', gDirUtilp->getDirDelimiter()[0]); +    std::replace(image_uri.begin(), image_uri.end(), '/', gDirUtilp->getDirDelimiter()[0]); +    const bool strip_extension = true; +    std::string stripped_uri = gDirUtilp->getBaseFileName(image_uri, strip_extension); + +    // sometimes they can be really long and unwieldy - 64 chars is enough for anyone :)  +    const int max_texture_name_length = 64; +    if (stripped_uri.length() > max_texture_name_length) +    { +        stripped_uri = stripped_uri.substr(0, max_texture_name_length - 1); +    } + +    // We intend to append the type of texture (albedo, emissive etc.) to the  +    // name of the texture but sometimes the creator already did that.  To try +    // to avoid repeats (not perfect), we look for the texture type in the name +    // and if we find it, do not append the type, later on. One way this fails +    // (and it's fine for now) is I see some texture/image uris have a name like +    // "metallic roughness" and of course, that doesn't match our predefined +    // name "metallicroughness" - consider fix later.. +    bool name_includes_type = false; +    std::string stripped_uri_lower = stripped_uri; +    LLStringUtil::toLower(stripped_uri_lower); +    stripped_uri_lower.erase(std::remove_if(stripped_uri_lower.begin(), stripped_uri_lower.end(), isspace), stripped_uri_lower.end()); +    std::string texture_type_lower = texture_type; +    LLStringUtil::toLower(texture_type_lower); +    texture_type_lower.erase(std::remove_if(texture_type_lower.begin(), texture_type_lower.end(), isspace), texture_type_lower.end()); +    if (stripped_uri_lower.find(texture_type_lower) != std::string::npos) +    { +        name_includes_type = true; +    } + +    // uri doesn't include the type at all +    if (name_includes_type == false) +    { +        // uri doesn't include the type and the uri is not empty +        // so we can include everything +        if (stripped_uri.length() > 0) +        { +            // example "DamagedHelmet: base layer (Albedo)" +            return STRINGIZE( +                mMaterialNameShort << +                ": " << +                stripped_uri << +                " (" << +                texture_type << +                ")" +            ); +        } +        else +        // uri doesn't include the type (because the uri is empty) +        // so we must reorganize the string a bit to include the name +        // and an explicit name type +        { +            // example "DamagedHelmet: (Emissive)" +            return STRINGIZE( +                mMaterialNameShort << +                " (" << +                texture_type << +                ")" +            ); +        } +    } +    else +    // uri includes the type so just use it directly with the +    // name of the material +    { +        return STRINGIZE( +            // example: AlienBust: normal_layer +            mMaterialNameShort << +            ": " << +            stripped_uri +        ); +    } +} + +/** + * Update the metadata for the material based on what we find in the loaded + * file (along with some assumptions and interpretations...). Fields include + * the name of the material, a material description and the names of the  + * composite textures. + */ +void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, tinygltf::Model& model) +{ +    // Use the name (without any path/extension) of the file that was  +    // uploaded as the base of the material name. Then if the name of the  +    // scene is present and not blank, append that and use the result as +    // the name of the material. This is a first pass at creating a  +    // naming scheme that is useful to real content creators and hopefully +    // avoid 500 materials in your inventory called "scene" or "Default" +    const bool strip_extension = true; +    std::string base_filename = gDirUtilp->getBaseFileName(filename, strip_extension); + +    // Extract the name of the scene. Note it is often blank or some very +    // generic name like "Scene" or "Default" so using this in the name +    // is less useful than you might imagine. +    std::string scene_name; +    if (model.scenes.size() > 0) +    { +        tinygltf::Scene& scene_in = model.scenes[0]; +        if (scene_in.name.length()) +        { +            scene_name = scene_in.name; +        } +        else +        { +            // scene name is empty so no point using it +        } +    } +    else +    { +        // scene name isn't present so no point using it +    } + +    // If we have a valid scene name, use it to build the short and  +    // long versions of the material name. The long version is used  +    // as you might expect, for the material name. The short version is +    // used as part of the image/texture name - the theory is that will  +    // allow content creators to track the material and the corresponding +    // textures +    if (scene_name.length()) +    { +        mMaterialNameShort = base_filename; + +        mMaterialName = STRINGIZE( +            base_filename <<  +            " " <<  +            "(" <<  +            scene_name <<  +            ")" +        ); +    } +    else +    // otherwise, just use the trimmed filename as is +    { +        mMaterialNameShort = base_filename; +        mMaterialName = base_filename; +    } + +    // sanitize the material name so that it's compatible with the inventory +    LLInventoryObject::correctInventoryName(mMaterialName); +    LLInventoryObject::correctInventoryName(mMaterialNameShort); + +    // We also set the title of the floater to match the  +    // name of the material +    setTitle(mMaterialName); + +    /** +     * Extract / derive the names of each composite texture. For each, the  +     * index in the first material (we only support 1 material currently) is +     * used to to determine which of the "Images" is used. If the index is -1 +     * then that texture type is not present in the material (Seems to be  +     * quite common that a material is missing 1 or more types of texture) +     */ +    if (model.materials.size() > 0) +    { +        const tinygltf::Material& first_material = model.materials[0]; + +        mAlbedoName = MATERIAL_ALBEDO_DEFAULT_NAME; +        // note: unlike the other textures, albedo doesn't have its own entry  +        // in the tinyGLTF Material struct. Rather, it is taken from a  +        // sub-texture in the pbrMetallicRoughness member +        int index = first_material.pbrMetallicRoughness.baseColorTexture.index; +        if (index > -1 && index < model.images.size()) +        { +            // sanitize the name we decide to use for each texture +            std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_ALBEDO_DEFAULT_NAME); +            LLInventoryObject::correctInventoryName(texture_name); +            mAlbedoName = texture_name; +        } + +        mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME; +        index = first_material.emissiveTexture.index; +        if (index > -1 && index < model.images.size()) +        { +            std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_EMISSIVE_DEFAULT_NAME); +            LLInventoryObject::correctInventoryName(texture_name); +            mEmissiveName = texture_name; +        } + +        mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME; +        index = first_material.pbrMetallicRoughness.metallicRoughnessTexture.index; +        if (index > -1 && index < model.images.size()) +        { +            std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_METALLIC_DEFAULT_NAME); +            LLInventoryObject::correctInventoryName(texture_name); +            mMetallicRoughnessName = texture_name; +        } + +        mNormalName = MATERIAL_NORMAL_DEFAULT_NAME; +        index = first_material.normalTexture.index; +        if (index > -1 && index < model.images.size()) +        { +            std::string texture_name = getImageNameFromUri(model.images[index].uri, MATERIAL_NORMAL_DEFAULT_NAME); +            LLInventoryObject::correctInventoryName(texture_name); +            mNormalName = texture_name; +        } +    } +} +  void LLMaterialEditor::importMaterial()  { -    (new LLMaterialFilePicker(this))->getFile(); +    (new LLMaterialFilePicker())->getFile();  } -void LLMaterialEditor::applyToSelection() +class LLRemderMaterialFunctor : public LLSelectedTEFunctor  { -    // Todo: fix this, this is a hack, not a proper live preview -    LLViewerObject* objectp = LLSelectMgr::instance().getSelection()->getFirstObject(); -    if (objectp && objectp->getVolume() && objectp->permModify()) +public: +    LLRemderMaterialFunctor(LLGLTFMaterial *mat, const LLUUID &id) +        : mMat(mat), mMatId(id)      { -        LLGLTFMaterial* mat = new LLGLTFMaterial(); -        getGLTFMaterial(mat); -        LLVOVolume* vobjp = (LLVOVolume*)objectp; -        for (int i = 0; i < vobjp->getNumTEs(); ++i) -        { -            // this is here just to prevent material from immediately resetting -            if (mAssetID.notNull()) -            { -                vobjp->setRenderMaterialID(i, mAssetID); -            } -            else -            { -                const LLUUID placeholder("984e183e-7811-4b05-a502-d79c6f978a98"); -                vobjp->setRenderMaterialID(i, placeholder); -            } +    } -            vobjp->getTE(i)->setGLTFMaterial(mat); -            vobjp->updateTEMaterialTextures(i); +    virtual bool apply(LLViewerObject* objectp, S32 te) +    { +        if (objectp && objectp->permModify() && objectp->getVolume()) +        { +            LLVOVolume* vobjp = (LLVOVolume*)objectp; +            vobjp->setRenderMaterialID(te, mMatId); +            vobjp->getTE(te)->setGLTFMaterial(mMat); +            vobjp->updateTEMaterialTextures(te);          } - -        vobjp->markForUpdate(TRUE); +        return true;      } +private: +    LLPointer<LLGLTFMaterial> mMat; +    LLUUID mMatId; +}; + +void LLMaterialEditor::applyToSelection() +{ +    LLPointer<LLGLTFMaterial> mat = new LLGLTFMaterial(); +    getGLTFMaterial(mat); +    const LLUUID placeholder("984e183e-7811-4b05-a502-d79c6f978a98"); +    LLUUID asset_id = mAssetID.notNull() ? mAssetID : placeholder; +    LLRemderMaterialFunctor mat_func(mat, asset_id); +    LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); +    selected_objects->applyToTEs(&mat_func);  }  void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat) @@ -1434,6 +1605,7 @@ void LLMaterialEditor::loadAsset()              if (mAssetID.isNull())              {                  mAssetStatus = PREVIEW_ASSET_LOADED; +                loadDefaults();                  setHasUnsavedChanges(false);              }              else @@ -1734,3 +1906,9 @@ S32 LLMaterialEditor::saveTextures()      return work_count;  } +void LLMaterialEditor::loadDefaults() +{ +    tinygltf::Model model_in; +    model_in.materials.resize(1); +    setFromGltfModel(model_in, true); +} diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 3da59c7f93..cc72193a0e 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -47,8 +47,10 @@ public:      bool setFromGltfModel(tinygltf::Model& model, bool set_textures = false); +    void setFromGltfMetaData(const std::string& filename, tinygltf::Model& model); +      // open a file dialog and select a gltf/glb file for import -    void importMaterial(); +    static void importMaterial();      // for live preview, apply current material to currently selected object      void applyToSelection(); @@ -58,6 +60,7 @@ public:      void setFromGLTFMaterial(LLGLTFMaterial* mat);      void loadAsset() override; +    void loadMaterialFromFile(const std::string& filename);      static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); @@ -103,6 +106,8 @@ public:  	BOOL postBuild() override;      void onClickCloseBtn(bool app_quitting = false) override; +    void onClose(bool app_quitting) override; +      LLUUID getAlbedoId();      void setAlbedoId(const LLUUID& id);      void setAlbedoUploadId(const LLUUID& id); @@ -156,6 +161,8 @@ public:      void onCommitEmissiveTexture(LLUICtrl* ctrl, const LLSD& data);      void onCommitNormalTexture(LLUICtrl* ctrl, const LLSD& data); +    // initialize the UI from a default GLTF material +    void loadDefaults();  private:      friend class LLMaterialFilePicker; @@ -192,9 +199,17 @@ private:      LLPointer<LLImageJ2C> mMetallicRoughnessJ2C;      LLPointer<LLImageJ2C> mEmissiveJ2C; +    // utility function for converting image uri into a texture name +    const std::string getImageNameFromUri(std::string image_uri, const std::string texture_type); + +    // utility function for building a description of the imported material +    // based on what we know about it. +    const std::string buildMaterialDescription(); +      bool mHasUnsavedChanges;      S32 mUploadingTexturesCount;      S32 mExpectedUploadCost; +    std::string mMaterialNameShort;      std::string mMaterialName;  }; diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 11aa607393..27a9758ec3 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -133,8 +133,7 @@ LLMaterialMgr::LLMaterialMgr():  	mHttpRequest(),  	mHttpHeaders(),  	mHttpOptions(), -	mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), -	mHttpPriority(0) +	mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID)  {  	LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); @@ -699,7 +698,7 @@ void LLMaterialMgr::processGetQueue()  			<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;  		LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,  -				mHttpPolicy, mHttpPriority, capURL,  +				mHttpPolicy, capURL,   				postData, mHttpOptions, mHttpHeaders, handler);  		if (handle == LLCORE_HTTP_HANDLE_INVALID) @@ -985,7 +984,7 @@ void LLMaterialMgr::processPutQueue()  										));  			LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD( -				mHttpRequest, mHttpPolicy, mHttpPriority, capURL, +				mHttpRequest, mHttpPolicy, capURL,  				putData, mHttpOptions, mHttpHeaders, handler);  			if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 843dc66fbc..f76cc27db1 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -141,7 +141,6 @@ private:  	LLCore::HttpHeaders::ptr_t		mHttpHeaders;  	LLCore::HttpOptions::ptr_t		mHttpOptions;  	LLCore::HttpRequest::policy_t	mHttpPolicy; -	LLCore::HttpRequest::priority_t	mHttpPriority;  	U32 getMaxEntries(const LLViewerRegion* regionp);  }; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index bc45eb6d3a..142977e939 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -355,7 +355,7 @@ void LLMediaDataClient::serviceQueue()  		// and make the post          LLCore::HttpHandler::ptr_t handler = request->createHandler(); -        LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0, +        LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy,              url, sd_payload, mHttpOpts, mHttpHeaders, handler);          if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d28e929b48..6fa71e130e 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -823,8 +823,7 @@ LLMeshRepoThread::LLMeshRepoThread()    mHttpLargeOptions(),    mHttpHeaders(),    mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), -  mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), -  mHttpPriority(0) +  mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID)  {  	LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); @@ -1268,7 +1267,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,  	if (len < LARGE_MESH_FETCH_THRESHOLD)  	{  		handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass, -                                                    mHttpPriority,                                                      url,                                                      (disable_range_req ? size_t(0) : offset),                                                      (disable_range_req ? size_t(0) : len), @@ -1283,7 +1281,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,  	else  	{  		handle = mHttpRequest->requestGetByteRange(mHttpLargePolicyClass, -												   mHttpPriority,  												   url,  												   (disable_range_req ? size_t(0) : offset),  												   (disable_range_req ? size_t(0) : len), @@ -2130,7 +2127,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,  	mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);  	mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);  	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS); -	mHttpPriority = 0;  }  LLMeshUploadThread::~LLMeshUploadThread() @@ -2649,7 +2645,6 @@ void LLMeshUploadThread::doWholeModelUpload()  		LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,  																		mHttpPolicyClass, -																		mHttpPriority,  																		mWholeModelUploadURL,  																		body,  																		mHttpOptions, @@ -2700,7 +2695,6 @@ void LLMeshUploadThread::requestWholeModelFee()  	dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));  	LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,  																	mHttpPolicyClass, -																	mHttpPriority,  																	mWholeModelFeeCapability,  																	mModelData,  																	mHttpOptions, diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 1989350303..5459bbb4af 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -321,7 +321,6 @@ public:  	LLCore::HttpHeaders::ptr_t			mHttpHeaders;  	LLCore::HttpRequest::policy_t		mHttpPolicyClass;  	LLCore::HttpRequest::policy_t		mHttpLargePolicyClass; -	LLCore::HttpRequest::priority_t		mHttpPriority;  	typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;  	http_request_set					mHttpRequestSet;			// Outstanding HTTP requests @@ -489,7 +488,6 @@ private:  	LLCore::HttpOptions::ptr_t			mHttpOptions;  	LLCore::HttpHeaders::ptr_t			mHttpHeaders;  	LLCore::HttpRequest::policy_t		mHttpPolicyClass; -	LLCore::HttpRequest::priority_t		mHttpPriority;  };  // Params related to streaming cost, render cost, and scene complexity tracking. diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index e67bd6468e..c3fbada9db 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -838,8 +838,10 @@ void LLModelPreview::clearIncompatible(S32 lod)      // at this point we don't care about sub-models,      // different amount of sub-models means face count mismatch, not incompatibility      U32 lod_size = countRootModels(mModel[lod]); +    bool replaced_base_model = (lod == LLModel::LOD_HIGH);      for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) -    { //clear out any entries that aren't compatible with this model +    { +        // Clear out any entries that aren't compatible with this model          if (i != lod)          {              if (countRootModels(mModel[i]) != lod_size) @@ -853,9 +855,47 @@ void LLModelPreview::clearIncompatible(S32 lod)                      mBaseModel = mModel[lod];                      mBaseScene = mScene[lod];                      mVertexBuffer[5].clear(); +                    replaced_base_model = true; +                } +            } +        } +    } + +    if (replaced_base_model && !mGenLOD) +    { +        // In case base was replaced, we might need to restart generation + +        // Check if already started +        bool subscribe_for_generation = mLodsQuery.empty(); +         +        // Remove previously scheduled work +        mLodsQuery.clear(); + +        LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; +        if (!fmp) return; + +        // Schedule new work +        for (S32 i = LLModel::LOD_HIGH; i >= 0; --i) +        { +            if (mModel[i].empty()) +            { +                // Base model was replaced, regenerate this lod if applicable +                LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[i]); +                if (!lod_combo) return; + +                S32 lod_mode = lod_combo->getCurrentIndex(); +                if (lod_mode != LOD_FROM_FILE) +                { +                    mLodsQuery.push_back(i);                  }              }          } + +        // Subscribe if we have pending work and not subscribed yet +        if (!mLodsQuery.empty() && subscribe_for_generation) +        { +            doOnIdleRepeating(lodQueryCallback); +        }      }  } @@ -1243,8 +1283,9 @@ void LLModelPreview::restoreNormals()  // Runs per object, but likely it is a better way to run per model+submodels  // returns a ratio of base model indices to resulting indices  // returns -1 in case of failure -F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode)  { +    // I. Weld faces together      // Figure out buffer size      S32 size_indices = 0;      S32 size_vertices = 0; @@ -1279,20 +1320,21 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe      {          const LLVolumeFace &face = base_model->getVolumeFace(face_idx); -        // vertices +        // Vertices          S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a);          LLVector4a::memcpyNonAliased16((F32*)(combined_positions + combined_positions_shift), (F32*)face.mPositions, copy_bytes); -        // normals +        // Normals          LLVector4a::memcpyNonAliased16((F32*)(combined_normals + combined_positions_shift), (F32*)face.mNormals, copy_bytes); -        // tex coords +        // Tex coords          copy_bytes = face.mNumVertices * sizeof(LLVector2);          memcpy((void*)(combined_tex_coords + combined_positions_shift), (void*)face.mTexCoords, copy_bytes);          combined_positions_shift += face.mNumVertices; -        // indices, sadly can't do dumb memcpy for indices, need to adjust each value +        // Indices +        // Sadly can't do dumb memcpy for indices, need to adjust each value          for (S32 i = 0; i < face.mNumIndices; ++i)          {              U16 idx = face.mIndices[i]; @@ -1303,10 +1345,42 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe          indices_idx_shift += face.mNumVertices;      } -    // Now that we have buffers, optimize +    // II. Generate a shadow buffer if nessesary. +    // Welds together vertices if possible + +    U32* shadow_indices = NULL; +    // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 +    // won't do anything new, model was remaped on a per face basis. +    // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless +    // since 'simplifySloppy' ignores all topology, including normals and uvs. +    // Note: simplifySloppy can affect UVs significantly. +    if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) +    { +        // strip normals, reflections should restore relatively correctly +        shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); +        LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, combined_tex_coords, size_vertices); +    } +    if (simplification_mode == MESH_OPTIMIZER_NO_UVS) +    { +        // strip uvs, can heavily affect textures +        shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32)); +        LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, NULL, size_vertices); +    } + +    U32* source_indices = NULL; +    if (shadow_indices) +    { +        source_indices = shadow_indices; +    } +    else +    { +        source_indices = combined_indices; +    } + +    // III. Simplify      S32 target_indices = 0;      F32 result_error = 0; // how far from original the model is, 1 == 100% -    S32 new_indices = 0; +    S32 size_new_indices = 0;      if (indices_decimator > 0)      { @@ -1316,38 +1390,43 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe      {          target_indices = 3;      } -    new_indices = LLMeshOptimizer::simplifyU32( + +    size_new_indices = LLMeshOptimizer::simplifyU32(          output_indices, -        combined_indices, +        source_indices,          size_indices,          combined_positions,          size_vertices,          LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],          target_indices,          error_threshold, -        sloppy, +        simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY,          &result_error); -      if (result_error < 0)      {          LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel              << " target Indices: " << target_indices -            << " new Indices: " << new_indices +            << " new Indices: " << size_new_indices              << " original count: " << size_indices << LL_ENDL;      } -    if (new_indices < 3) +    // free unused buffers +    ll_aligned_free_32(combined_indices); +    ll_aligned_free_32(shadow_indices); +    combined_indices = NULL; +    shadow_indices = NULL; + +    if (size_new_indices < 3)      {          // Model should have at least one visible triangle          ll_aligned_free<64>(combined_positions);          ll_aligned_free_32(output_indices); -        ll_aligned_free_32(combined_indices);          return -1;      } -    // repack back into individual faces +    // IV. Repack back into individual faces      LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size);      LLVector4a* buffer_normals = buffer_positions + size_vertices; @@ -1378,7 +1457,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe          }          // Copy relevant indices and vertices -        for (S32 i = 0; i < new_indices; ++i) +        for (S32 i = 0; i < size_new_indices; ++i)          {              U32 idx = output_indices[i]; @@ -1401,19 +1480,19 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe                          LL_WARNS() << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for"                              << " model " << target_model->mLabel                              << " target Indices: " << target_indices -                            << " new Indices: " << new_indices +                            << " new Indices: " << size_new_indices                              << " original count: " << size_indices                              << " error treshold: " << error_threshold                              << LL_ENDL;                          // U16 vertices overflow shouldn't happen, but just in case -                        new_indices = 0; +                        size_new_indices = 0;                          valid_faces = 0;                          for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx)                          { -                            genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false); +                            genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, simplification_mode);                              const LLVolumeFace &face = target_model->getVolumeFace(face_idx); -                            new_indices += face.mNumIndices; +                            size_new_indices += face.mNumIndices;                              if (face.mNumIndices >= 3)                              {                                  valid_faces++; @@ -1421,7 +1500,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe                          }                          if (valid_faces)                          { -                            return (F32)size_indices / (F32)new_indices; +                            return (F32)size_indices / (F32)size_new_indices;                          }                          else                          { @@ -1491,18 +1570,17 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe      ll_aligned_free<64>(buffer_positions);      ll_aligned_free_32(output_indices);      ll_aligned_free_16(buffer_indices); -    ll_aligned_free_32(combined_indices); -    if (new_indices < 3 || valid_faces == 0) +    if (size_new_indices < 3 || valid_faces == 0)      {          // Model should have at least one visible triangle          return -1;      } -    return (F32)size_indices / (F32)new_indices; +    return (F32)size_indices / (F32)size_new_indices;  } -F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, bool sloppy) +F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode)  {      const LLVolumeFace &face = base_model->getVolumeFace(face_idx);      S32 size_indices = face.mNumIndices; @@ -1510,14 +1588,40 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target      {          return -1;      } -    // todo: do not allocate per each face, add one large buffer somewhere -    // faces have limited amount of indices +      S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF; -    U16* output = (U16*)ll_aligned_malloc_16(size); +    U16* output_indices = (U16*)ll_aligned_malloc_16(size); + +    U16* shadow_indices = NULL; +    // if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32 +    // won't do anything new, model was remaped on a per face basis. +    // Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless +    // since 'simplifySloppy' ignores all topology, including normals and uvs. +    if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS) +    { +        U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); +        LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, face.mTexCoords, face.mNumVertices); +    } +    if (simplification_mode == MESH_OPTIMIZER_NO_UVS) +    { +        U16* shadow_indices = (U16*)ll_aligned_malloc_16(size); +        LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, NULL, face.mNumVertices); +    } +    // Don't run ShadowIndexBuffer for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless + +    U16* source_indices = NULL; +    if (shadow_indices) +    { +        source_indices = shadow_indices; +    } +    else +    { +        source_indices = face.mIndices; +    }      S32 target_indices = 0;      F32 result_error = 0; // how far from original the model is, 1 == 100% -    S32 new_indices = 0; +    S32 size_new_indices = 0;      if (indices_decimator > 0)      { @@ -1527,25 +1631,25 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target      {          target_indices = 3;      } -    new_indices = LLMeshOptimizer::simplify( -        output, -        face.mIndices, + +    size_new_indices = LLMeshOptimizer::simplify( +        output_indices, +        source_indices,          size_indices,          face.mPositions,          face.mNumVertices,          LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],          target_indices,          error_threshold, -        sloppy, +        simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY,          &result_error); -      if (result_error < 0)      {          LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx              << " of model " << target_model->mLabel              << " target Indices: " << target_indices -            << " new Indices: " << new_indices +            << " new Indices: " << size_new_indices              << " original count: " << size_indices              << " error treshold: " << error_threshold              << LL_ENDL; @@ -1556,10 +1660,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target      // Copy old values      new_face = face; - -    if (new_indices < 3) +    if (size_new_indices < 3)      { -        if (!sloppy) +        if (simplification_mode != MESH_OPTIMIZER_NO_TOPOLOGY)          {              // meshopt_optimizeSloppy() can optimize triangles away even if target_indices is > 2,              // but optimize() isn't supposed to @@ -1583,23 +1686,24 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target      else      {          // Assign new values -        new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output -        S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF; -        LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output, idx_size); +        new_face.resizeIndices(size_new_indices); // will wipe out mIndices, so new_face can't substitute output +        S32 idx_size = (size_new_indices * sizeof(U16) + 0xF) & ~0xF; +        LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output_indices, idx_size); -        // clear unused values +        // Clear unused values          new_face.optimize();      } -    ll_aligned_free_16(output); +    ll_aligned_free_16(output_indices); +    ll_aligned_free_16(shadow_indices); -    if (new_indices < 3) +    if (size_new_indices < 3)      {          // At least one triangle is needed          return -1;      } -    return (F32)size_indices / (F32)new_indices; +    return (F32)size_indices / (F32)size_new_indices;  }  void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation, bool enforce_tri_limit) @@ -1733,16 +1837,19 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d              // Ideally this should run not per model,              // but combine all submodels with origin model as well -            if (model_meshopt_mode == MESH_OPTIMIZER_COMBINE) +            if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE)              { -                // Run meshoptimizer for each model/object, up to 8 faces in one model. - -                // Ideally this should run not per model, -                // but combine all submodels with origin model as well -                F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); -                if (res < 0) +                // Run meshoptimizer for each face +                for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)                  { -                    target_model->copyVolumeFaces(base); +                    F32 res = genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); +                    if (res < 0) +                    { +                        // Mesh optimizer failed and returned an invalid model +                        const LLVolumeFace &face = base->getVolumeFace(face_idx); +                        LLVolumeFace &new_face = target_model->getVolumeFace(face_idx); +                        new_face = face; +                    }                  }              } @@ -1751,19 +1858,29 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                  // Run meshoptimizer for each face                  for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)                  { -                    if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0) +                    if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY) < 0)                      {                          // Sloppy failed and returned an invalid model -                        genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); +                        genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);                      }                  }              }              if (model_meshopt_mode == MESH_OPTIMIZER_AUTO)              { -                // Switches between 'combine' method and 'sloppy' based on combine's result. -                F32 allowed_ratio_drift = 2.f; -                F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); +                // Remove progressively more data if we can't reach the target. +                F32 allowed_ratio_drift = 1.8f; +                F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL); + +                if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) +                { +                    precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_NORMALS); +                } + +                if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) +                { +                    precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS); +                }                  if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))                  { @@ -1771,10 +1888,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                      // Sloppy variant can fail entirely and has issues with precision,                      // so code needs to do multiple attempts with different decimators.                      // Todo: this is a bit of a mess, needs to be refined and improved +                      F32 last_working_decimator = 0.f;                      F32 last_working_ratio = F32_MAX; -                    F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); +                    F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);                      if (sloppy_ratio > 0)                      { @@ -1797,13 +1915,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                          // side due to overal lack of precision, and we don't need an ideal result, which                          // likely does not exist, just a better one, so a partial correction is enough.                          F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2; -                        sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); +                        sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);                      }                      if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio)                      {                          // Compensation didn't work, return back to previous decimator -                        sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); +                        sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);                      }                      if (sloppy_ratio < 0) @@ -1836,7 +1954,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                                  && sloppy_decimator > precise_ratio                                  && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case                              { -                                sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); +                                sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);                                  sloppy_decimator = sloppy_decimator / sloppy_decimation_step;                              }                          } @@ -1856,7 +1974,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                          else                          {                              // Fallback to normal method -                            precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); +                            precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);                          }                          LL_INFOS() << "Model " << target_model->getName() @@ -3767,7 +3885,7 @@ bool LLModelPreview::lodQueryCallback()              }              // return false to continue cycle -            return false; +            return preview->mLodsQuery.empty();          }      }      // nothing to process diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 9e32215e6a..215f44357f 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -125,7 +125,7 @@ public:      {          LOD_FROM_FILE = 0,          MESH_OPTIMIZER_AUTO, // automatically selects method based on model or face -        MESH_OPTIMIZER_COMBINE, // combines faces into a single model, simplifies, then splits back into faces +        MESH_OPTIMIZER_PRECISE, // combines faces into a single model, simplifies, then splits back into faces          MESH_OPTIMIZER_SLOPPY, // uses sloppy method, works per face          USE_LOD_ABOVE,      } eLoDMode; @@ -225,13 +225,21 @@ private:      // Count amount of original models, excluding sub-models      static U32 countRootModels(LLModelLoader::model_list models); +    typedef enum +    { +        MESH_OPTIMIZER_FULL, +        MESH_OPTIMIZER_NO_NORMALS, +        MESH_OPTIMIZER_NO_UVS, +        MESH_OPTIMIZER_NO_TOPOLOGY, +    } eSimplificationMode; +      // Merges faces into single mesh, simplifies using mesh optimizer,      // then splits back into faces.      // Returns reached simplification ratio. -1 in case of a failure. -    F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, bool sloppy); +    F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode);      // Simplifies specified face using mesh optimizer.      // Returns reached simplification ratio. -1 in case of a failure. -    F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, bool sloppy); +    F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode);  protected:      friend class LLModelLoader; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 4febb72c6c..d11b3b57f3 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1177,7 +1177,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)  	{  		return;  	} -    (new LLFilePickerReplyThread(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false))->getFile(); +    LLFilePickerReplyThread::startPicker(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false);  }  void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filenames, LLUUID outfit_id) @@ -1374,6 +1374,7 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id)                  texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLOutfitGallery::onTexturePickerCommit, this, _1, _2));                  texture_floaterp->setOnUpdateImageStatsCallback(boost::bind(&LLOutfitGallery::onTexturePickerUpdateImageStats, this, _1));                  texture_floaterp->setLocalTextureEnabled(FALSE); +                texture_floaterp->setBakeTextureEnabled(FALSE);                  texture_floaterp->setCanApply(false, true);              } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 37ed4bc74c..9a030f1d7d 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1,25 +1,25 @@ -/**  +/**   * @file llpanelavatar.cpp   * @brief LLPanelAvatar and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ @@ -28,173 +28,127 @@  #include "llpanelavatar.h"  #include "llagent.h" -#include "llavataractions.h" -#include "llcallingcard.h" -#include "llcombobox.h" -#include "lldateutil.h"			// ageFromDate() -#include "llimview.h" -#include "llmenubutton.h" -#include "llnotificationsutil.h" -#include "llslurl.h" -#include "lltexteditor.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" +#include "llloadingindicator.h"  #include "lltooldraganddrop.h" -#include "llscrollcontainer.h" -#include "llavatariconctrl.h" -#include "llfloaterreg.h" -#include "llnotificationsutil.h" -#include "llviewermenu.h" // is_agent_mappable -#include "llvoiceclient.h" -#include "lltextbox.h" -#include "lltrans.h" - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLDropTarget -// -// This handy class is a simple way to drop something on another -// view. It handles drop events, always setting itself to the size of -// its parent. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLDropTarget : public LLView -{ -public: -	struct Params : public LLInitParam::Block<Params, LLView::Params> -	{ -		Optional<LLUUID> agent_id; -		Params() -		:	agent_id("agent_id") -		{ -			changeDefault(mouse_opaque, false); -			changeDefault(follows.flags, FOLLOWS_ALL); -		} -	}; - -	LLDropTarget(const Params&); -	~LLDropTarget(); - -	void doDrop(EDragAndDropType cargo_type, void* cargo_data); - -	// -	// LLView functionality -	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -								   EDragAndDropType cargo_type, -								   void* cargo_data, -								   EAcceptance* accept, -								   std::string& tooltip_msg); -	void setAgentID(const LLUUID &agent_id)		{ mAgentID = agent_id; } -protected: -	LLUUID mAgentID; -}; - -LLDropTarget::LLDropTarget(const LLDropTarget::Params& p)  -:	LLView(p), -	mAgentID(p.agent_id) -{} -LLDropTarget::~LLDropTarget() +////////////////////////////////////////////////////////////////////////// +// LLProfileDropTarget + +LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p) +:   LLView(p), +    mAgentID(p.agent_id)  {} -void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) +void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)  { -	LL_INFOS() << "LLDropTarget::doDrop()" << LL_ENDL; +    LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL;  } -BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -									 EDragAndDropType cargo_type, -									 void* cargo_data, -									 EAcceptance* accept, -									 std::string& tooltip_msg) +BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +                                     EDragAndDropType cargo_type, +                                     void* cargo_data, +                                     EAcceptance* accept, +                                     std::string& tooltip_msg)  { -	if(getParent()) -	{ -		LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, -												 cargo_type, cargo_data, accept); +    if (getParent()) +    { +        LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, +                                                 cargo_type, cargo_data, accept); -		return TRUE; -	} +        return TRUE; +    } -	return FALSE; +    return FALSE;  } -static LLDefaultChildRegistry::Register<LLDropTarget> r("drop_target"); +static LLDefaultChildRegistry::Register<LLProfileDropTarget> r("profile_drop_target");  ////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// +// LLPanelProfileTab  LLPanelProfileTab::LLPanelProfileTab()  : LLPanel()  , mAvatarId(LLUUID::null) +, mLoadingState(PROFILE_INIT) +, mSelfProfile(false)  {  }  LLPanelProfileTab::~LLPanelProfileTab()  { -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); -	}  } -void LLPanelProfileTab::setAvatarId(const LLUUID& id) +void LLPanelProfileTab::setAvatarId(const LLUUID& avatar_id)  { -	if(id.notNull()) -	{ -		if(getAvatarId().notNull()) -		{ -			LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this); -		} -		mAvatarId = id; -		LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this); -	} +    if (avatar_id.notNull()) +    { +        mAvatarId = avatar_id; +        mSelfProfile = (getAvatarId() == gAgentID); +    }  }  void LLPanelProfileTab::onOpen(const LLSD& key)  { -	// Don't reset panel if we are opening it for same avatar. -	if(getAvatarId() != key.asUUID()) -	{ -		resetControls(); -		resetData(); - -		scrollToTop(); -	} - -	// Update data even if we are viewing same avatar profile as some data might been changed. -	setAvatarId(key.asUUID()); -	updateData(); -	updateButtons(); +    // Update data even if we are viewing same avatar profile as some data might been changed. +    setAvatarId(key.asUUID()); + +    setApplyProgress(true); +} + +void LLPanelProfileTab::setLoaded() +{ +    setApplyProgress(false); + +    mLoadingState = PROFILE_LOADED; +} + +void LLPanelProfileTab::setApplyProgress(bool started) +{ +    LLLoadingIndicator* indicator = findChild<LLLoadingIndicator>("progress_indicator"); + +    if (indicator) +    { +        indicator->setVisible(started); + +        if (started) +        { +            indicator->start(); +        } +        else +        { +            indicator->stop(); +        } +    } + +    LLPanel* panel = findChild<LLPanel>("indicator_stack"); +    if (panel) +    { +        panel->setVisible(started); +    }  } -void LLPanelProfileTab::scrollToTop() +LLPanelProfilePropertiesProcessorTab::LLPanelProfilePropertiesProcessorTab() +    : LLPanelProfileTab()  { -	LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll"); -	if (scrollContainer) -		scrollContainer->goToTop();  } -void LLPanelProfileTab::onMapButtonClick() +LLPanelProfilePropertiesProcessorTab::~LLPanelProfilePropertiesProcessorTab()  { -	LLAvatarActions::showOnMap(getAvatarId()); +    if (getAvatarId().notNull()) +    { +        LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); +    }  } -void LLPanelProfileTab::updateButtons() +void LLPanelProfilePropertiesProcessorTab::setAvatarId(const LLUUID & avatar_id)  { -	bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); -	 -	if(LLAvatarActions::isFriend(getAvatarId())) -	{ -		getChildView("teleport")->setEnabled(is_buddy_online); -	} -	else -	{ -		getChildView("teleport")->setEnabled(true); -	} - -	bool enable_map_btn = (is_buddy_online && -			       is_agent_mappable(getAvatarId())) -		|| gAgent.isGodlike(); -	getChildView("show_on_map_btn")->setEnabled(enable_map_btn); +    if (avatar_id.notNull()) +    { +        if (getAvatarId().notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); +        } +        LLPanelProfileTab::setAvatarId(avatar_id); +        LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); +    }  } diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index e33a850cfa..f182660c8e 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -1,25 +1,25 @@ -/**  +/**   * @file llpanelavatar.h - * @brief LLPanelAvatar and related class definitions + * @brief Legacy profile panel base class   * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2019&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  + * Copyright (C) 2019, 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$   */ @@ -29,80 +29,141 @@  #include "llpanel.h"  #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llvoiceclient.h"  #include "llavatarnamecache.h"  class LLComboBox;  class LLLineEditor; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLProfileDropTarget +// +// This handy class is a simple way to drop something on another +// view. It handles drop events, always setting itself to the size of +// its parent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLProfileDropTarget : public LLView +{ +public: +    struct Params : public LLInitParam::Block<Params, LLView::Params> +    { +        Optional<LLUUID> agent_id; +        Params() +        :   agent_id("agent_id") +        { +            changeDefault(mouse_opaque, false); +            changeDefault(follows.flags, FOLLOWS_ALL); +        } +    }; + +    LLProfileDropTarget(const Params&); +    ~LLProfileDropTarget() {} + +    void doDrop(EDragAndDropType cargo_type, void* cargo_data); + +    // +    // LLView functionality +    virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +                                   EDragAndDropType cargo_type, +                                   void* cargo_data, +                                   EAcceptance* accept, +                                   std::string& tooltip_msg); + +    void setAgentID(const LLUUID &agent_id)     { mAgentID = agent_id; } + +protected: +    LLUUID mAgentID; +}; + +  /**  * Base class for any Profile View.  */  class LLPanelProfileTab -	: public LLPanel -	, public LLAvatarPropertiesObserver +    : public LLPanel  {  public: -	/** -	 * Sets avatar ID, sets panel as observer of avatar related info replies from server. -	 */ -	virtual void setAvatarId(const LLUUID& id); - -	/** -	 * Returns avatar ID. -	 */ -	virtual const LLUUID& getAvatarId() { return mAvatarId; } - -	/** -	 * Sends update data request to server. -	 */ -	virtual void updateData() = 0; - -	/** -	 * Clears panel data if viewing avatar info for first time and sends update data request. -	 */ -	virtual void onOpen(const LLSD& key); - -	/** -	 * Profile tabs should close any opened panels here. -	 * -	 * Called from LLPanelProfile::onOpen() before opening new profile. -	 * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel -	 * before new profile is displayed, otherwise new profile will  -	 * be hidden behind picture info panel. -	 */ -	virtual void onClosePanel() {} - -	/** -	 * Resets controls visibility, state, etc. -	 */ -	virtual void resetControls(){}; - -	/** -	 * Clears all data received from server. -	 */ -	virtual void resetData(){}; - -	/*virtual*/ ~LLPanelProfileTab(); +    /** +     * Sets avatar ID, sets panel as observer of avatar related info replies from server. +     */ +    virtual void setAvatarId(const LLUUID& avatar_id); + +    /** +     * Returns avatar ID. +     */ +    virtual const LLUUID& getAvatarId() { return mAvatarId; } + +    /** +     * Sends update data request to server. +     */ +    virtual void updateData() {}; + +    /** +     * Clears panel data if viewing avatar info for first time and sends update data request. +     */ +    virtual void onOpen(const LLSD& key); + +    /** +     * Clears all data received from server. +     */ +    virtual void resetData(){}; + +    /*virtual*/ ~LLPanelProfileTab();  protected: -	LLPanelProfileTab(); +    LLPanelProfileTab(); + +    enum ELoadingState +    { +        PROFILE_INIT, +        PROFILE_LOADING, +        PROFILE_LOADED, +    }; + + +    // mLoading: false: Initial state, can request +    //           true:  Data requested, skip duplicate requests (happens due to LLUI's habit of repeated callbacks) +    // mLoaded:  false: Initial state, show loading indicator +    //           true:  Data recieved, which comes in a single message, hide indicator +    ELoadingState getLoadingState() { return mLoadingState; } +    virtual void setLoaded(); +    void setApplyProgress(bool started); + +    const bool getSelfProfile() const { return mSelfProfile; } -	/** -	 * Scrolls panel to top when viewing avatar info for first time. -	 */ -	void scrollToTop(); +public: +    void setIsLoading() { mLoadingState = PROFILE_LOADING; } +    void resetLoading() { mLoadingState = PROFILE_INIT; } -	virtual void onMapButtonClick(); +    bool getStarted() { return mLoadingState != PROFILE_INIT; } +    bool getIsLoaded() { return mLoadingState == PROFILE_LOADED; } -	virtual void updateButtons(); +    virtual bool hasUnsavedChanges() { return false; } +    virtual void commitUnsavedChanges() {}  private: -	LLUUID mAvatarId; +    LLUUID  mAvatarId; +    ELoadingState    mLoadingState; +    bool    mSelfProfile; +}; + +class LLPanelProfilePropertiesProcessorTab +    : public LLPanelProfileTab +    , public LLAvatarPropertiesObserver +{ +public: +    LLPanelProfilePropertiesProcessorTab(); +    ~LLPanelProfilePropertiesProcessorTab(); + +    /*virtual*/ void setAvatarId(const LLUUID& avatar_id); + +    /** +     * Processes data received from server via LLAvatarPropertiesObserver. +     */ +    virtual void processProperties(void* data, EAvatarProcessorType type) = 0;  };  #endif // LL_LLPANELAVATAR_H diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 3322e8a3df..3a4fc613b7 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -232,7 +232,7 @@ void LLPanelBlockedList::onFilterEdit(const std::string& search_string)  void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  {  	if (names.empty() || ids.empty()) return; -	LLMute mute(ids[0], names[0].getAccountName(), LLMute::AGENT); +    LLMute mute(ids[0], names[0].getUserName(), LLMute::AGENT);  	LLMuteList::getInstance()->add(mute);  	showPanelAndSelect(mute.mID);  } diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index c0342eef4e..183000ceac 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1,10 +1,10 @@  /**    * @file llpanelclassified.cpp - * @brief LLPanelClassified class implementation + * @brief LLPanelClassifiedInfo class implementation   * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $LicenseInfo:firstyear=2021&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2021, 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 @@ -34,33 +34,21 @@  #include "lldispatcher.h"  #include "llfloaterreg.h" -#include "llnotifications.h" -#include "llnotificationsutil.h"  #include "llparcel.h"  #include "llagent.h"  #include "llclassifiedflags.h" -#include "llcommandhandler.h" // for classified HTML detail page click tracking  #include "lliconctrl.h" -#include "lllineeditor.h" -#include "llcombobox.h"  #include "lltexturectrl.h" -#include "lltexteditor.h" -#include "llviewerparcelmgr.h"  #include "llfloaterworldmap.h"  #include "llviewergenericmessage.h"	// send_generic_message  #include "llviewerregion.h" -#include "llviewertexture.h" -#include "lltrans.h"  #include "llscrollcontainer.h" -#include "llstatusbar.h" -#include "llviewertexture.h"  #include "llcorehttputil.h" -const S32 MINIMUM_PRICE_FOR_LISTING = 50;	// L$ -  //static  LLPanelClassifiedInfo::panel_list_t LLPanelClassifiedInfo::sAllPanels; +static LLPanelInjector<LLPanelClassifiedInfo> t_panel_panel_classified_info("panel_classified_info");  // "classifiedclickthrough"  // strings[0] = classified_id @@ -118,17 +106,8 @@ LLPanelClassifiedInfo::~LLPanelClassifiedInfo()  	sAllPanels.remove(this);  } -// static -LLPanelClassifiedInfo* LLPanelClassifiedInfo::create() -{ -	LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo(); -	panel->buildFromFile("panel_classified_info.xml"); -	return panel; -} -  BOOL LLPanelClassifiedInfo::postBuild()  { -	childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this));  	childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this));  	childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this)); @@ -144,16 +123,6 @@ BOOL LLPanelClassifiedInfo::postBuild()  	return TRUE;  } -void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("back_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedInfo::setEditClassifiedCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("edit_btn")->setClickedCallback(cb); -} -  void LLPanelClassifiedInfo::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)  {  	LLPanel::reshape(width, height, called_from_parent); @@ -286,6 +255,8 @@ void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType t  			getChild<LLUICtrl>("creation_date")->setValue(date_str);  			setInfoLoaded(true); + +			LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);  		}  	}  } @@ -590,588 +561,4 @@ void LLPanelClassifiedInfo::onTeleportClick()  	}  } -void LLPanelClassifiedInfo::onExit() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -	gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -static const S32 CB_ITEM_MATURE = 0; -static const S32 CB_ITEM_PG	   = 1; - -LLPanelClassifiedEdit::LLPanelClassifiedEdit() - : LLPanelClassifiedInfo() - , mIsNew(false) - , mIsNewWithErrors(false) - , mCanClose(false) - , mPublishFloater(NULL) -{ -} - -LLPanelClassifiedEdit::~LLPanelClassifiedEdit() -{ -} - -//static -LLPanelClassifiedEdit* LLPanelClassifiedEdit::create() -{ -	LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit(); -	panel->buildFromFile("panel_edit_classified.xml"); -	return panel; -} - -BOOL LLPanelClassifiedEdit::postBuild() -{ -	LLPanelClassifiedInfo::postBuild(); - -	LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon"); -	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon)); -	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon)); -	edit_icon->setVisible(false); - -	LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name"); -	line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - -	LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc"); -	text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - -	LLComboBox* combobox = getChild<LLComboBox>( "category"); -	LLClassifiedInfo::cat_map::iterator iter; -	for (iter = LLClassifiedInfo::sCategories.begin(); -		iter != LLClassifiedInfo::sCategories.end(); -		iter++) -	{ -		combobox->add(LLTrans::getString(iter->second)); -	} - -	combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); - -	childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); -	childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); -	childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); - -	childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this)); -	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this)); - -	mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onTextureSelected, this)); - -	return TRUE; -} - -void LLPanelClassifiedEdit::fillIn(const LLSD& key) -{ -	setAvatarId(gAgent.getID()); - -	if(key.isUndefined()) -	{ -		setPosGlobal(gAgent.getPositionGlobal()); - -		LLUUID snapshot_id = LLUUID::null; -		std::string desc; -		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - -		if(parcel) -		{ -			desc = parcel->getDesc(); -			snapshot_id = parcel->getSnapshotID(); -		} - -		std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); -		LLViewerRegion* region = gAgent.getRegion(); -		if (region) -		{ -			region_name = region->getName(); -		} - -		getChild<LLUICtrl>("classified_name")->setValue(makeClassifiedName()); -		getChild<LLUICtrl>("classified_desc")->setValue(desc); -		setSnapshotId(snapshot_id); -		setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); -		// server will set valid parcel id -		setParcelId(LLUUID::null); -	} -	else -	{ -		setClassifiedId(key["classified_id"]); -		setClassifiedName(key["name"]); -		setDescription(key["desc"]); -		setSnapshotId(key["snapshot_id"]); -		setCategory((U32)key["category"].asInteger()); -		setContentType((U32)key["content_type"].asInteger()); -		setClassifiedLocation(key["location_text"]); -		getChild<LLUICtrl>("auto_renew")->setValue(key["auto_renew"]); -		getChild<LLUICtrl>("price_for_listing")->setValue(key["price_for_listing"].asInteger()); -	} -} - -void LLPanelClassifiedEdit::onOpen(const LLSD& key) -{ -	mIsNew = key.isUndefined(); -	 -	scrollToTop(); - -	// classified is not created yet -	bool is_new = isNew() || isNewWithErrors(); - -	if(is_new) -	{ -		resetData(); -		resetControls(); - -		fillIn(key); - -		if(isNew()) -		{ -			LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); -		} -	} -	else -	{ -		LLPanelClassifiedInfo::onOpen(key); -	} - -	std::string save_btn_label = is_new ? getString("publish_label") : getString("save_label"); -	getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", save_btn_label); - -	enableVerbs(is_new); -	enableEditing(is_new); -	showEditing(!is_new); -	resetDirty(); -	setInfoLoaded(false); -} - -void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_CLASSIFIED_INFO == type) -	{ -		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -		if(c_info && getClassifiedId() == c_info->classified_id) -		{ -			// see LLPanelClassifiedEdit::sendUpdate() for notes -			mIsNewWithErrors = false; -			// for just created classified - panel will probably be closed when we get here. -			if(!getVisible()) -			{ -				return; -			} - -			enableEditing(true); - -			setClassifiedName(c_info->name); -			setDescription(c_info->description); -			setSnapshotId(c_info->snapshot_id); -			setParcelId(c_info->parcel_id); -			setPosGlobal(c_info->pos_global); - -			setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); -			// *HACK see LLPanelClassifiedEdit::sendUpdate() -			setCategory(c_info->category - 1); - -			bool mature = is_cf_mature(c_info->flags); -			bool auto_renew = is_cf_auto_renew(c_info->flags); - -			setContentType(mature ? CB_ITEM_MATURE : CB_ITEM_PG); -			getChild<LLUICtrl>("auto_renew")->setValue(auto_renew); -			getChild<LLUICtrl>("price_for_listing")->setValue(c_info->price_for_listing); -			getChildView("price_for_listing")->setEnabled(isNew()); - -			resetDirty(); -			setInfoLoaded(true); -			enableVerbs(false); - -			// for just created classified - in case user opened edit panel before processProperties() callback  -			getChild<LLUICtrl>("save_changes_btn")->setLabelArg("[LABEL]", getString("save_label")); -		} -	} -} - -BOOL LLPanelClassifiedEdit::isDirty() const -{ -	if(mIsNew)  -	{ -		return TRUE; -	} - -	BOOL dirty = false; - -	dirty |= LLPanelClassifiedInfo::isDirty(); -	dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty(); -	dirty |= getChild<LLUICtrl>("classified_name")->isDirty(); -	dirty |= getChild<LLUICtrl>("classified_desc")->isDirty(); -	dirty |= getChild<LLUICtrl>("category")->isDirty(); -	dirty |= getChild<LLUICtrl>("content_type")->isDirty(); -	dirty |= getChild<LLUICtrl>("auto_renew")->isDirty(); -	dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty(); - -	return dirty; -} - -void LLPanelClassifiedEdit::resetDirty() -{ -	LLPanelClassifiedInfo::resetDirty(); -	getChild<LLUICtrl>("classified_snapshot")->resetDirty(); -	getChild<LLUICtrl>("classified_name")->resetDirty(); - -	LLTextEditor* desc = getChild<LLTextEditor>("classified_desc"); -	// call blockUndo() to really reset dirty(and make isDirty work as intended) -	desc->blockUndo(); -	desc->resetDirty(); - -	getChild<LLUICtrl>("category")->resetDirty(); -	getChild<LLUICtrl>("content_type")->resetDirty(); -	getChild<LLUICtrl>("auto_renew")->resetDirty(); -	getChild<LLUICtrl>("price_for_listing")->resetDirty(); -} - -void LLPanelClassifiedEdit::setSaveCallback(const commit_signal_t::slot_type& cb) -{ -	mSaveButtonClickedSignal.connect(cb); -} - -void LLPanelClassifiedEdit::setCancelCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -void LLPanelClassifiedEdit::resetControls() -{ -	LLPanelClassifiedInfo::resetControls(); - -	getChild<LLComboBox>("category")->setCurrentByIndex(0); -	getChild<LLComboBox>("content_type")->setCurrentByIndex(0); -	getChild<LLUICtrl>("auto_renew")->setValue(false); -	getChild<LLUICtrl>("price_for_listing")->setValue(MINIMUM_PRICE_FOR_LISTING); -	getChildView("price_for_listing")->setEnabled(TRUE); -} - -bool LLPanelClassifiedEdit::canClose() -{ -	return mCanClose; -} - -void LLPanelClassifiedEdit::draw() -{ -	LLPanel::draw(); - -	// Need to re-stretch on every draw because LLTextureCtrl::onSelectCallback -	// does not trigger callbacks when user navigates through images. -	stretchSnapshot(); -} - -void LLPanelClassifiedEdit::stretchSnapshot() -{ -	LLPanelClassifiedInfo::stretchSnapshot(); - -	getChild<LLUICtrl>("edit_icon")->setShape(mSnapshotCtrl->getRect()); -} - -U32 LLPanelClassifiedEdit::getContentType() -{ -	LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); -	return ct_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setContentType(U32 content_type) -{ -	LLComboBox* ct_cb = getChild<LLComboBox>("content_type"); -	ct_cb->setCurrentByIndex(content_type); -	ct_cb->resetDirty(); -} - -bool LLPanelClassifiedEdit::getAutoRenew() -{ -	return getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); -} - -void LLPanelClassifiedEdit::sendUpdate() -{ -	LLAvatarClassifiedInfo c_data; - -	if(getClassifiedId().isNull()) -	{ -		setClassifiedId(LLUUID::generateNewID()); -	} - -	c_data.agent_id = gAgent.getID(); -	c_data.classified_id = getClassifiedId(); -	// *HACK  -	// Categories on server start with 1 while combo-box index starts with 0 -	c_data.category = getCategory() + 1; -	c_data.name = getClassifiedName(); -	c_data.description = getDescription(); -	c_data.parcel_id = getParcelId(); -	c_data.snapshot_id = getSnapshotId(); -	c_data.pos_global = getPosGlobal(); -	c_data.flags = getFlags(); -	c_data.price_for_listing = getPriceForListing(); - -	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); -	 -	if(isNew()) -	{ -		// Lets assume there will be some error. -		// Successful sendClassifiedInfoUpdate will trigger processProperties and -		// let us know there was no error. -		mIsNewWithErrors = true; -	} -} - -U32 LLPanelClassifiedEdit::getCategory() -{ -	LLComboBox* cat_cb = getChild<LLComboBox>("category"); -	return cat_cb->getCurrentIndex(); -} - -void LLPanelClassifiedEdit::setCategory(U32 category) -{ -	LLComboBox* cat_cb = getChild<LLComboBox>("category"); -	cat_cb->setCurrentByIndex(category); -	cat_cb->resetDirty(); -} - -U8 LLPanelClassifiedEdit::getFlags() -{ -	bool auto_renew = getChild<LLUICtrl>("auto_renew")->getValue().asBoolean(); - -	LLComboBox* content_cb = getChild<LLComboBox>("content_type"); -	bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE; -	 -	return pack_classified_flags_request(auto_renew, false, mature, false); -} - -void LLPanelClassifiedEdit::enableVerbs(bool enable) -{ -	getChildView("save_changes_btn")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::enableEditing(bool enable) -{ -	getChildView("classified_snapshot")->setEnabled(enable); -	getChildView("classified_name")->setEnabled(enable); -	getChildView("classified_desc")->setEnabled(enable); -	getChildView("set_to_curr_location_btn")->setEnabled(enable); -	getChildView("category")->setEnabled(enable); -	getChildView("content_type")->setEnabled(enable); -	getChildView("price_for_listing")->setEnabled(enable); -	getChildView("auto_renew")->setEnabled(enable); -} - -void LLPanelClassifiedEdit::showEditing(bool show) -{ -	getChildView("price_for_listing_label")->setVisible( show); -	getChildView("price_for_listing")->setVisible( show); -} - -std::string LLPanelClassifiedEdit::makeClassifiedName() -{ -	std::string name; - -	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); -	if(parcel) -	{ -		name = parcel->getName(); -	} - -	if(!name.empty()) -	{ -		return name; -	} - -	LLViewerRegion* region = gAgent.getRegion(); -	if(region) -	{ -		name = region->getName(); -	} - -	return name; -} - -S32 LLPanelClassifiedEdit::getPriceForListing() -{ -	return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPanelClassifiedEdit::setPriceForListing(S32 price) -{ -	getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -void LLPanelClassifiedEdit::onSetLocationClick() -{ -	setPosGlobal(gAgent.getPositionGlobal()); -	setParcelId(LLUUID::null); - -	std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); -	LLViewerRegion* region = gAgent.getRegion(); -	if (region) -	{ -		region_name = region->getName(); -	} - -	setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); - -	// mark classified as dirty -	setValue(LLSD()); - -	onChange(); -} - -void LLPanelClassifiedEdit::onChange() -{ -	enableVerbs(isDirty()); -} - -void LLPanelClassifiedEdit::onSaveClick() -{ -	mCanClose = false; - -	if(!isValidName()) -	{ -		notifyInvalidName(); -		return; -	} -	if(isNew() || isNewWithErrors()) -	{ -		if(gStatusBar->getBalance() < getPriceForListing()) -		{ -			LLNotificationsUtil::add("ClassifiedInsufficientFunds"); -			return; -		} - -		mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( -			"publish_classified", LLSD()); - -		if(!mPublishFloater) -		{ -			mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( -				"publish_classified", LLSD()); - -			mPublishFloater->setPublishClickedCallback(boost::bind -				(&LLPanelClassifiedEdit::onPublishFloaterPublishClicked, this)); -		} - -		// set spinner value before it has focus or value wont be set -		mPublishFloater->setPrice(getPriceForListing()); -		mPublishFloater->openFloater(mPublishFloater->getKey()); -		mPublishFloater->center(); -	} -	else -	{ -		doSave(); -	} -} - -void LLPanelClassifiedEdit::doSave() -{ -	mCanClose = true; -	sendUpdate(); -	resetDirty(); - -	mSaveButtonClickedSignal(this, LLSD()); -} - -void LLPanelClassifiedEdit::onPublishFloaterPublishClicked() -{ -	setPriceForListing(mPublishFloater->getPrice()); - -	doSave(); -} - -std::string LLPanelClassifiedEdit::getLocationNotice() -{ -	static std::string location_notice = getString("location_notice"); -	return location_notice; -} - -bool LLPanelClassifiedEdit::isValidName() -{ -	std::string name = getClassifiedName(); -	if (name.empty()) -	{ -		return false; -	} -	if (!isalnum(name[0])) -	{ -		return false; -	} - -	return true; -} - -void LLPanelClassifiedEdit::notifyInvalidName() -{ -	std::string name = getClassifiedName(); -	if (name.empty()) -	{ -		LLNotificationsUtil::add("BlankClassifiedName"); -	} -	else if (!isalnum(name[0])) -	{ -		LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); -	} -} - -void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) -{ -	ctrl->setVisible(TRUE); -} - -void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) -{ -	ctrl->setVisible(FALSE); -} - -void LLPanelClassifiedEdit::onTextureSelected() -{ -	setSnapshotId(mSnapshotCtrl->getValue().asUUID()); -	onChange(); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) - : LLFloater(key) -{ -} - -LLPublishClassifiedFloater::~LLPublishClassifiedFloater() -{ -} - -BOOL LLPublishClassifiedFloater::postBuild() -{ -	LLFloater::postBuild(); - -	childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); -	childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); - -	return TRUE; -} - -void LLPublishClassifiedFloater::setPrice(S32 price) -{ -	getChild<LLUICtrl>("price_for_listing")->setValue(price); -} - -S32 LLPublishClassifiedFloater::getPrice() -{ -	return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); -} - -void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("publish_btn")->setClickedCallback(cb); -} - -void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) -{ -	getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} -  //EOF diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index b292782615..471becd0f7 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -1,10 +1,10 @@  /**    * @file llpanelclassified.h - * @brief LLPanelClassified class definition + * @brief LLPanelClassifiedInfo class definition   * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $LicenseInfo:firstyear=2021&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2021, 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 @@ -35,39 +35,16 @@  #include "llfloater.h"  #include "llpanel.h"  #include "llrect.h" -#include "lluuid.h" -#include "v3dmath.h" -#include "llcoros.h" -#include "lleventcoro.h"  class LLScrollContainer;  class LLTextureCtrl; -class LLUICtrl; - -class LLPublishClassifiedFloater : public LLFloater -{ -public: -	LLPublishClassifiedFloater(const LLSD& key); -	virtual ~LLPublishClassifiedFloater(); - -	/*virtual*/ BOOL postBuild(); - -	void setPrice(S32 price); -	S32 getPrice(); - -	void setPublishClickedCallback(const commit_signal_t::slot_type& cb); -	void setCancelClickedCallback(const commit_signal_t::slot_type& cb); - -private: -};  class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver  {  	LOG_CLASS(LLPanelClassifiedInfo);  public: -	static LLPanelClassifiedInfo* create(); - +	LLPanelClassifiedInfo();  	virtual ~LLPanelClassifiedInfo();  	/*virtual*/ void onOpen(const LLSD& key); @@ -135,18 +112,12 @@ public:  			const LLVector3d& global_pos,  			const std::string& sim_name); -	void setExitCallback(const commit_callback_t& cb); - -	void setEditClassifiedCallback(const commit_callback_t& cb); -  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  	/*virtual*/ void draw();  protected: -	LLPanelClassifiedInfo(); -  	virtual void resetData();  	virtual void resetControls(); @@ -165,7 +136,6 @@ protected:  	void onMapClick();  	void onTeleportClick(); -	void onExit();  	bool mSnapshotStreched;  	LLRect mSnapshotRect; @@ -202,100 +172,4 @@ private:  	static panel_list_t sAllPanels;  }; -class LLPanelClassifiedEdit : public LLPanelClassifiedInfo -{ -	LOG_CLASS(LLPanelClassifiedEdit); -public: - -	static LLPanelClassifiedEdit* create(); - -	virtual ~LLPanelClassifiedEdit(); - -	/*virtual*/ BOOL postBuild(); - -	void fillIn(const LLSD& key); - -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	/*virtual*/ BOOL isDirty() const; - -	/*virtual*/ void resetDirty(); - -	void setSaveCallback(const commit_signal_t::slot_type& cb); - -	void setCancelCallback(const commit_signal_t::slot_type& cb); - -	/*virtual*/ void resetControls(); - -	bool isNew() { return mIsNew; } - -	bool isNewWithErrors() { return mIsNewWithErrors; } - -	bool canClose(); - -	void draw(); - -	void stretchSnapshot(); - -	U32 getCategory(); - -	void setCategory(U32 category); - -	U32 getContentType(); - -	void setContentType(U32 content_type); - -	bool getAutoRenew(); - -	S32 getPriceForListing(); - -protected: - -	LLPanelClassifiedEdit(); - -	void sendUpdate(); - -	void enableVerbs(bool enable); - -	void enableEditing(bool enable); - -	void showEditing(bool show); - -	std::string makeClassifiedName(); - -	void setPriceForListing(S32 price); - -	U8 getFlags(); - -	std::string getLocationNotice(); - -	bool isValidName(); - -	void notifyInvalidName(); - -	void onSetLocationClick(); -	void onChange(); -	void onSaveClick(); - -	void doSave(); - -	void onPublishFloaterPublishClicked(); - -	void onTexturePickerMouseEnter(LLUICtrl* ctrl); -	void onTexturePickerMouseLeave(LLUICtrl* ctrl); - -	void onTextureSelected(); - -private: -	bool mIsNew; -	bool mIsNewWithErrors; -	bool mCanClose; - -	LLPublishClassifiedFloater* mPublishFloater; - -	commit_signal_t mSaveButtonClickedSignal; -}; -  #endif // LL_LLPANELCLASSIFIED_H diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index be11a4a9f3..6e897e2c7e 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1308,7 +1308,8 @@ void LLPanelEditWearable::changeCamera(U8 subpart)          gMorphView->setCameraOffset( subpart_entry->mCameraOffset );          if (gSavedSettings.getBOOL("AppearanceCameraMovement"))          { -                gMorphView->updateCamera(); +            gAgentCamera.setFocusOnAvatar(FALSE, FALSE); +            gMorphView->updateCamera();          }  } diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h index 9d5afd1a6a..11111f2a2e 100644 --- a/indra/newview/llpanelexperiences.h +++ b/indra/newview/llpanelexperiences.h @@ -29,7 +29,6 @@  #include "llaccordionctrltab.h"  #include "llflatlistview.h" -#include "llpanelavatar.h"  class LLExperienceItem;  class LLPanelProfile;  diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index ad3742157f..865529eb8f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -38,6 +38,7 @@  #include "llfontgl.h"  // project includes +#include "llagent.h"  #include "llagentdata.h"  #include "llbutton.h"  #include "llcheckboxctrl.h" @@ -45,9 +46,13 @@  #include "llcombobox.h"  #include "lldrawpoolbump.h"  #include "llface.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" // gInventory +#include "llinventorymodelbackgroundfetch.h"  #include "lllineeditor.h"  #include "llmaterialmgr.h"  #include "llmediaentry.h" +#include "llmenubutton.h"  #include "llnotificationsutil.h"  #include "llradiogroup.h"  #include "llresmgr.h" @@ -57,6 +62,8 @@  #include "lltexturectrl.h"  #include "lltextureentry.h"  #include "lltooldraganddrop.h" +#include "lltoolface.h" +#include "lltoolmgr.h"  #include "lltrans.h"  #include "llui.h"  #include "llviewercontrol.h" @@ -69,6 +76,18 @@  #include "llpluginclassmedia.h"  #include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI + + +#include "llagent.h" +#include "llfilesystem.h" +#include "llviewerassetupload.h" +#include "llviewermenufile.h" +#include "llsd.h" +#include "llsdutil.h" +#include "llsdserialize.h" +#include "llinventorymodel.h" + +  //  // Constant definitions for comboboxes  // Must match the commbobox definitions in panel_tools_texture.xml @@ -159,7 +178,6 @@ BOOL	LLPanelFace::postBuild()  	childSetAction("button align",&LLPanelFace::onClickAutoFix,this);  	childSetAction("button align textures", &LLPanelFace::onAlignTexture, this); -	childSetAction("button save material", &LLPanelFace::onSaveMaterial, this);  	LLTextureCtrl*	mTextureCtrl;  	LLTextureCtrl*	mShinyTextureCtrl; @@ -302,6 +320,8 @@ BOOL	LLPanelFace::postBuild()  		mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);  	} +    mMenuClipboardColor = getChild<LLMenuButton>("clipboard_color_params_btn"); +    mMenuClipboardTexture = getChild<LLMenuButton>("clipboard_texture_params_btn");  	clearCtrls(); @@ -312,7 +332,9 @@ LLPanelFace::LLPanelFace()  :	LLPanel(),  	mIsAlpha(false)  { -	USE_TEXTURE = LLTrans::getString("use_texture"); +    USE_TEXTURE = LLTrans::getString("use_texture"); +    mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2)); +    mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2));  } @@ -322,6 +344,13 @@ LLPanelFace::~LLPanelFace()  } +void LLPanelFace::draw() +{ +    updateCopyTexButton(); + +    LLPanel::draw(); +} +  void LLPanelFace::sendTexture()  {  	LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("texture control"); @@ -1414,12 +1443,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)              // enable this UI box if a single face is selected.              BOOL is_single_face = !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected(); -            childSetEnabled("button save material", static_cast<bool>(is_single_face));              childSetEnabled("materialID", static_cast<bool>(is_single_face));   // doesn't work - why? -            // TODO: 2022-04 conflicts with media button placement. hide the button if applying media -            // i.e.  childSetVisible("button save material", !applying_media); -              if (material && editable)  			{  				LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL; @@ -1519,6 +1544,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)  				}  			}  		} +        S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +        BOOL single_volume = (selected_count == 1); +        mMenuClipboardColor->setEnabled(editable && single_volume);  		// Set variable values for numeric expressions  		LLCalc* calcp = LLCalc::getInstance(); @@ -1581,6 +1609,17 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)  } +void LLPanelFace::updateCopyTexButton() +{ +    LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +    mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()  +                                                    && !objectp->isPermanentEnforced() && !objectp->isInventoryPending()  +                                                    && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)); +    std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options"); +    mMenuClipboardTexture->setToolTip(tooltip); + +} +  void LLPanelFace::refresh()  {  	LL_DEBUGS("Materials") << LL_ENDL; @@ -2562,205 +2601,808 @@ void LLPanelFace::onAlignTexture(void* userdata)      self->alignTestureLayer();  } -#include "llagent.h" -#include "llfilesystem.h" -#include "llviewerassetupload.h" -#include "llviewermenufile.h" -#include "llsd.h" -#include "llsdutil.h" -#include "llsdserialize.h" -#include "llinventorymodel.h" +enum EPasteMode +{ +    PASTE_COLOR, +    PASTE_TEXTURE +}; -void LLPanelFace::onSaveMaterial(void* userdata) +struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor  { -    // DRTVWR-559, Q&D material picker - save to inventory goes here -    LL_DEBUGS("Material") << "saving render material to inventory" << LL_ENDL; +    LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) : +        mPanelFace(panel), mMode(mode) {} -    std::string name = "New Material"; +    virtual bool apply(LLViewerObject* objectp, S32 te) +    { +        switch (mMode) +        { +        case PASTE_COLOR: +            mPanelFace->onPasteColor(objectp, te); +            break; +        case PASTE_TEXTURE: +            mPanelFace->onPasteTexture(objectp, te); +            break; +        } +        return true; +    } +private: +    LLPanelFace *mPanelFace; +    EPasteMode mMode; +}; -	LLSD material_data = llsd::map( -		"version", "1", -		"material", LLSD::emptyMap() -	); +struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor +{ +    LLPanelFaceUpdateFunctor(bool update_media) : mUpdateMedia(update_media) {} +    virtual bool apply(LLViewerObject* object) +    { +        object->sendTEUpdate(); +        if (mUpdateMedia) +        { +            LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object); +            if (vo && vo->hasMedia()) +            { +                vo->sendMediaDataUpdate(); +            } +        } +        return true; +    } +private: +    bool mUpdateMedia; +}; -    // gen a new uuid for this asset -    LLTransactionID tid; -    tid.generate();     // timestamp-based randomization + uniquification -    LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); +struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor +{ +    virtual bool apply(LLViewerObject* objectp, S32 te) +    { +        if (objectp && objectp->getTE(te)) +        { +            LLTextureEntry* tep = objectp->getTE(te); +            const LLMediaEntry *media_data = tep->getMediaData(); +            if (media_data) +            { +                if (media_data->getCurrentURL().empty() && media_data->getAutoPlay()) +                { +                    viewer_media_t media_impl = +                        LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID()); +                    if (media_impl) +                    { +                        media_impl->navigateHome(); +                    } +                } +            } +        } +        return true; +    } +}; -    material_data["material"] = renderMaterialToLLSD(new_asset_id, userdata); -    std::stringstream output; -    LLSDSerialize::toNotation(material_data, output); +void LLPanelFace::onCopyColor() +{ +    LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); +    S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +    if (!objectp || !node +        || objectp->getPCode() != LL_PCODE_VOLUME +        || !objectp->permModify() +        || objectp->isPermanentEnforced() +        || selected_count > 1) +    { +        return; +    } -    //S32 expected_upload_cost = 0;// LLAgentBenefitsMgr::current().getTextureUploadCost(); -     -    std::string res_name = name; -    std::string res_desc = "Saved Material"; -    //LLFolderType::EType folder_type = LLFolderType::FT_MATERIAL; -    //LLInventoryType::EType inv_type = LLInventoryType::IT_MATERIAL; -    U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner(); +    if (mClipboardParams.has("color")) +    { +        mClipboardParams["color"].clear(); +    } +    else +    { +        mClipboardParams["color"] = LLSD::emptyArray(); +    } -    LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); -    const U8 subtype = NO_INV_SUBTYPE;  // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? +    std::map<LLUUID, LLUUID> asset_item_map; -    create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, res_name, res_desc, -        LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm, -        new LLBoostFuncInventoryCallback([output=output.str()](LLUUID const & inv_item_id){ -            // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() -            LLResourceUploadInfo::ptr_t uploadInfo = -                std::make_shared<LLBufferedAssetUploadInfo>( -                    inv_item_id, -                    LLAssetType::AT_SETTINGS, // TODO switch to AT_MATERIAL -                    output, -                    [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) { -                        LL_INFOS("Material") << "inventory item uploaded.  item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL; -                        LLSD params = llsd::map("ASSET_ID", new_asset_id); -                        LLNotificationsUtil::add("MaterialCreated", params); -                    }); +    // a way to resolve situations where source and target have different amount of faces +    S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); +    mClipboardParams["color_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); +    for (S32 te = 0; te < num_tes; ++te) +    { +        if (node->isTESelected(te)) +        { +            LLTextureEntry* tep = objectp->getTE(te); +            if (tep) +            { +                LLSD te_data; -            const LLViewerRegion* region = gAgent.getRegion(); -            if (region) +                // asLLSD() includes media +                te_data["te"] = tep->asLLSD(); // Note: includes a lot more than just color/alpha/glow + +                mClipboardParams["color"].append(te_data); +            } +        } +    } +} + +void LLPanelFace::onPasteColor() +{ +    if (!mClipboardParams.has("color")) +    { +        return; +    } + +    LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); +    S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +    if (!objectp || !node +        || objectp->getPCode() != LL_PCODE_VOLUME +        || !objectp->permModify() +        || objectp->isPermanentEnforced() +        || selected_count > 1) +    { +        // not supposed to happen +        LL_WARNS() << "Failed to paste color due to missing or wrong selection" << LL_ENDL; +        return; +    } + +    bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); +    LLSD &clipboard = mClipboardParams["color"]; // array +    S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); +    S32 compare_tes = num_tes; + +    if (face_selection_mode) +    { +        compare_tes = 0; +        for (S32 te = 0; te < num_tes; ++te) +        { +            if (node->isTESelected(te))              { -                 std::string agent_url(region->getCapability("UpdateSettingsAgentInventory")); -                 if (agent_url.empty()) -                 { -                     LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL; -                 } -                 LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo); +                compare_tes++;              } -        }) -    ); +        } +    } + +    // we can copy if single face was copied in edit face mode or if face count matches +    if (!((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) +        && compare_tes != clipboard.size()) +    { +        LLSD notif_args; +        if (face_selection_mode) +        { +            static std::string reason = getString("paste_error_face_selection_mismatch"); +            notif_args["REASON"] = reason; +        } +        else +        { +            static std::string reason = getString("paste_error_object_face_count_mismatch"); +            notif_args["REASON"] = reason; +        } +        LLNotificationsUtil::add("FacePasteFailed", notif_args); +        return; +    } + +    LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); + +    LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR); +    selected_objects->applyToTEs(&paste_func); +    LLPanelFaceUpdateFunctor sendfunc(false); +    selected_objects->applyToObjects(&sendfunc);  } -// Fill an LLSD with data describing the current face's texture settings -// TODO 2022-05 FUBAR there are both colliding and different data in LLPanelFace vs the TE.  Also, neither one has the diffuse tex settings. -//               -LLSD LLPanelFace::renderMaterialToLLSD(LLUUID uuid, void* userdata) +void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te)  { -    llassert(userdata != nullptr); +    LLSD te_data; +    LLSD &clipboard = mClipboardParams["color"]; // array +    if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean()) +    { +        te_data = *(clipboard.beginArray()); +    } +    else if (clipboard[te]) +    { +        te_data = clipboard[te]; +    } +    else +    { +        return; +    } -    LLSD sd; +    LLTextureEntry* tep = objectp->getTE(te); +    if (tep) +    { +        if (te_data.has("te")) +        { +            // Color / Alpha +            if (te_data["te"].has("colors")) +            { +                LLColor4 color = tep->getColor(); -    sd.insert("RenderMaterialUUID",    LLSD(uuid)); +                LLColor4 clip_color; +                clip_color.setValue(te_data["te"]["colors"]); -    // now pull same data from the selected TE (same but different. W T F?)  -    LLMaterialPtr mat = nullptr; -    bool ident; // ? -    LLSelectedTEMaterial::getCurrent(mat, ident); +                // Color +                color.mV[VRED] = clip_color.mV[VRED]; +                color.mV[VGREEN] = clip_color.mV[VGREEN]; +                color.mV[VBLUE] = clip_color.mV[VBLUE]; -    if (mat) -    { -        sd.insert("teMaterialID", LLSD(mat->getMaterialID())); +                // Alpha +                color.mV[VALPHA] = clip_color.mV[VALPHA]; -        sd.insert("teNormalMap", LLSD(mat->getNormalID())); -        sd.insert("teNormalOffsetX", LLSD(mat->getNormalOffsetX())); -        sd.insert("teNormalOffsetY", LLSD(mat->getNormalOffsetY())); -        sd.insert("teNormalRepeatX", LLSD(mat->getNormalRepeatX())); -        sd.insert("teNormalRepeatY", LLSD(mat->getNormalRepeatY())); -        sd.insert("teNormalRotation", LLSD(mat->getNormalRotation())); +                objectp->setTEColor(te, color); +            } -        sd.insert("teSpecularMap", LLSD(mat->getSpecularID())); -        LLColor4U color = mat->getSpecularLightColor(); +            // Color/fullbright +            if (te_data["te"].has("fullbright")) +            { +                objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger()); +            } -        sd.insert("teSpecularColorR", LLSD(static_cast<S32>(color.mV[0]))); -        sd.insert("teSpecularColorG", LLSD(static_cast<S32>(color.mV[1]))); -        sd.insert("teSpecularColorB", LLSD(static_cast<S32>(color.mV[2]))); -        sd.insert("teSpecularColorA", LLSD(static_cast<S32>(color.mV[3]))); -        sd.insert("teSpecularExponent", LLSD(static_cast<S32>(mat->getSpecularLightExponent()))); -        sd.insert("teSpecularOffsetX", LLSD(mat->getSpecularOffsetX())); -        sd.insert("teSpecularOffsetY", LLSD(mat->getSpecularOffsetY())); -        sd.insert("teSpecularRepeatX", LLSD(mat->getSpecularRepeatX())); -        sd.insert("teSpecularRepeatY", LLSD(mat->getSpecularRepeatY())); -        sd.insert("teSpecularRotation", LLSD(mat->getSpecularRotation())); +            // Glow +            if (te_data["te"].has("glow")) +            { +                objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal()); +            } +        } +    } +} -        sd.insert("teAlphaMode", LLSD(static_cast<S32>(mat->getDiffuseAlphaMode()))); -        sd.insert("teAlphaCutoff", LLSD(static_cast<S32>(mat->getAlphaMaskCutoff()))); -        sd.insert("teEnvIntensity", LLSD(static_cast<S32>(mat->getEnvironmentIntensity()))); -        sd.insert("teShaderMask", LLSD(static_cast<S32>(mat->getShaderMask()))); +void LLPanelFace::onCopyTexture() +{ +    LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); +    S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +    if (!objectp || !node +        || objectp->getPCode() != LL_PCODE_VOLUME +        || !objectp->permModify() +        || objectp->isPermanentEnforced() +        || selected_count > 1) +    { +        return; +    } + +    if (mClipboardParams.has("texture")) +    { +        mClipboardParams["texture"].clear();      }      else      { -        // pull data from the LLPanelFace -        LLPanelFace* instance = static_cast<LLPanelFace*>(userdata); -        sd.insert("pfNormalMap",         LLSD(instance->getCurrentNormalMap())); -        sd.insert("pfSpecularMap",       LLSD(instance->getCurrentSpecularMap())); -        sd.insert("pfShininess",         LLSD(static_cast<S32>(instance->getCurrentShininess()))); -        sd.insert("pfBumpiness",         LLSD(static_cast<S32>(instance->getCurrentBumpiness()))); -        sd.insert("pfAlphaMode",         LLSD(static_cast<S32>(instance->getCurrentDiffuseAlphaMode()))); -        sd.insert("pfAlphaCutoff",       LLSD(static_cast<S32>(instance->getCurrentAlphaMaskCutoff()))); -        sd.insert("pfEnvIntensity",      LLSD(static_cast<S32>(instance->getCurrentEnvIntensity()))); -        sd.insert("pfGlossiness",        LLSD(static_cast<S32>(instance->getCurrentGlossiness()))); -        sd.insert("pfNormalRotation",    LLSD(instance->getCurrentBumpyRot())); -        sd.insert("pfNormalScaleU",      LLSD(instance->getCurrentBumpyScaleU())); -        sd.insert("pfNormalScaleV",      LLSD(instance->getCurrentBumpyScaleV())); -        sd.insert("pfNormalOffsetU",     LLSD(instance->getCurrentBumpyOffsetU())); -        sd.insert("pfNormalOffsetV",     LLSD(instance->getCurrentBumpyOffsetV())); -        sd.insert("pfSpecularRotation",  LLSD(instance->getCurrentShinyRot())); -        sd.insert("pfSpecularScaleU",    LLSD(instance->getCurrentShinyScaleU())); -        sd.insert("pfSpecularScaleV",    LLSD(instance->getCurrentShinyScaleV())); -        sd.insert("pfSpecularOffsetU",   LLSD(instance->getCurrentShinyOffsetU())); -        sd.insert("pfSpecularOffsetV",   LLSD(instance->getCurrentShinyOffsetV())); -        sd.insert("pfMaterialID",        LLSD(instance->getCurrentMaterialID())); +        mClipboardParams["texture"] = LLSD::emptyArray();      } -    return sd; +    std::map<LLUUID, LLUUID> asset_item_map; + +    // a way to resolve situations where source and target have different amount of faces +    S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); +    mClipboardParams["texture_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()); +    for (S32 te = 0; te < num_tes; ++te) +    { +        if (node->isTESelected(te)) +        { +            LLTextureEntry* tep = objectp->getTE(te); +            if (tep) +            { +                LLSD te_data; + +                // asLLSD() includes media +                te_data["te"] = tep->asLLSD(); +                te_data["te"]["shiny"] = tep->getShiny(); +                te_data["te"]["bumpmap"] = tep->getBumpmap(); +                te_data["te"]["bumpshiny"] = tep->getBumpShiny(); +                te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright(); + +                if (te_data["te"].has("imageid")) +                { +                    LLUUID item_id; +                    LLUUID id = te_data["te"]["imageid"].asUUID(); +                    bool from_library = get_is_predefined_texture(id); +                    bool full_perm = from_library; + +                    if (!full_perm +                        && objectp->permCopy() +                        && objectp->permTransfer() +                        && objectp->permModify()) +                    { +                        // If agent created this object and nothing is limiting permissions, mark as full perm +                        // If agent was granted permission to edit objects owned and created by somebody else, mark full perm +                        // This check is not perfect since we can't figure out whom textures belong to so this ended up restrictive +                        std::string creator_app_link; +                        LLUUID creator_id; +                        LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link); +                        full_perm = objectp->mOwnerID == creator_id; +                    } + +                    if (id.notNull() && !full_perm) +                    { +                        std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id); +                        if (iter != asset_item_map.end()) +                        { +                            item_id = iter->second; +                        } +                        else +                        { +                            // What this does is simply searches inventory for item with same asset id, +                            // as result it is Hightly unreliable, leaves little control to user, borderline hack +                            // but there are little options to preserve permissions - multiple inventory +                            // items might reference same asset and inventory search is expensive. +                            bool no_transfer = false; +                            if (objectp->getInventoryItemByAsset(id)) +                            { +                                no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm(); +                            } +                            item_id = get_copy_free_item_by_asset_id(id, no_transfer); +                            // record value to avoid repeating inventory search when possible +                            asset_item_map[id] = item_id; +                        } +                    } + +                    if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID())) +                    { +                        full_perm = true; +                        from_library = true; +                    } + +                    { +                        te_data["te"]["itemfullperm"] = full_perm; +                        te_data["te"]["fromlibrary"] = from_library;  + +                        // If full permission object, texture is free to copy, +                        // but otherwise we need to check inventory and extract permissions +                        // +                        // Normally we care only about restrictions for current user and objects +                        // don't inherit any 'next owner' permissions from texture, so there is +                        // no need to record item id if full_perm==true +                        if (!full_perm && !from_library && item_id.notNull()) +                        { +                            LLViewerInventoryItem* itemp = gInventory.getItem(item_id); +                            if (itemp) +                            { +                                LLPermissions item_permissions = itemp->getPermissions(); +                                if (item_permissions.allowOperationBy(PERM_COPY, +                                    gAgent.getID(), +                                    gAgent.getGroupID())) +                                { +                                    te_data["te"]["imageitemid"] = item_id; +                                    te_data["te"]["itemfullperm"] = itemp->getIsFullPerm(); +                                    if (!itemp->isFinished()) +                                    { +                                        // needed for dropTextureAllFaces +                                        LLInventoryModelBackgroundFetch::instance().start(item_id, false); +                                    } +                                } +                            } +                        } +                    } +                } + +                LLMaterialPtr material_ptr = tep->getMaterialParams(); +                if (!material_ptr.isNull()) +                { +                    LLSD mat_data; + +                    mat_data["NormMap"] = material_ptr->getNormalID(); +                    mat_data["SpecMap"] = material_ptr->getSpecularID(); + +                    mat_data["NormRepX"] = material_ptr->getNormalRepeatX(); +                    mat_data["NormRepY"] = material_ptr->getNormalRepeatY(); +                    mat_data["NormOffX"] = material_ptr->getNormalOffsetX(); +                    mat_data["NormOffY"] = material_ptr->getNormalOffsetY(); +                    mat_data["NormRot"] = material_ptr->getNormalRotation(); + +                    mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX(); +                    mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY(); +                    mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX(); +                    mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY(); +                    mat_data["SpecRot"] = material_ptr->getSpecularRotation(); + +                    mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue(); +                    mat_data["SpecExp"] = material_ptr->getSpecularLightExponent(); +                    mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity(); +                    mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff(); +                    mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode(); + +                    // Replace no-copy textures, destination texture will get used instead if available +                    if (mat_data.has("NormMap")) +                    { +                        LLUUID id = mat_data["NormMap"].asUUID(); +                        if (id.notNull() && !get_can_copy_texture(id)) +                        { +                            mat_data["NormMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); +                            mat_data["NormMapNoCopy"] = true; +                        } + +                    } +                    if (mat_data.has("SpecMap")) +                    { +                        LLUUID id = mat_data["SpecMap"].asUUID(); +                        if (id.notNull() && !get_can_copy_texture(id)) +                        { +                            mat_data["SpecMap"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); +                            mat_data["SpecMapNoCopy"] = true; +                        } + +                    } + +                    te_data["material"] = mat_data; +                } + +                mClipboardParams["texture"].append(te_data); +            } +        } +    }  } -// Take the individual texture settings from the material and apply to current face & TE -void LLPanelFace::applyMaterialUUID(LLUUID uuid, void* userdata) +void LLPanelFace::onPasteTexture()  { -    llassert(userdata != nullptr); -    //LLPanelFace* instance = static_cast<LLPanelFace*>(userdata); -     -    LLFileSystem material_file(uuid, LLAssetType::AT_MATERIAL, LLFileSystem::READ); -    S32 bufsize = material_file.getSize(); -    llassert(bufsize > 0); -    std::vector<U8> buffer(bufsize); -    material_file.read(&buffer[0], bufsize); -    std::istringstream input(std::string(buffer.begin(), buffer.end()));  // TODO - extend LLFileSystem to expose iostream interface -    LLSD matSD; +    if (!mClipboardParams.has("texture")) +    { +        return; +    } -    LLSDSerialize::fromNotation(matSD, input, bufsize); +    LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); +    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); +    S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +    if (!objectp || !node +        || objectp->getPCode() != LL_PCODE_VOLUME +        || !objectp->permModify() +        || objectp->isPermanentEnforced() +        || selected_count > 1) +    { +        // not supposed to happen +        LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL; +        return; +    } -    LL_INFOS() << "dump matSD: " << matSD << LL_ENDL; +    bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); +    LLSD &clipboard = mClipboardParams["texture"]; // array +    S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); +    S32 compare_tes = num_tes; -    // strip off the versioning wrapper for now -    matSD = matSD["material"]; +    if (face_selection_mode) +    { +        compare_tes = 0; +        for (S32 te = 0; te < num_tes; ++te) +        { +            if (node->isTESelected(te)) +            { +                compare_tes++; +            } +        } +    } -    // wrong, oops. llassert(uuid == matSD.get("RenderMaterialUUID").asUUID());      // if not, whoo boy +    // we can copy if single face was copied in edit face mode or if face count matches +    if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean())  +        && compare_tes != clipboard.size()) +    { +        LLSD notif_args; +        if (face_selection_mode) +        { +            static std::string reason = getString("paste_error_face_selection_mismatch"); +            notif_args["REASON"] = reason; +        } +        else +        { +            static std::string reason = getString("paste_error_object_face_count_mismatch"); +            notif_args["REASON"] = reason; +        } +        LLNotificationsUtil::add("FacePasteFailed", notif_args); +        return; +    } -    LLMaterialPtr mat = nullptr; -    bool ident; // ? -    LLSelectedTEMaterial::getCurrent(mat, ident); +    bool full_perm_object = true; +    LLSD::array_const_iterator iter = clipboard.beginArray(); +    LLSD::array_const_iterator end = clipboard.endArray(); +    for (; iter != end; ++iter) +    { +        const LLSD& te_data = *iter; +        if (te_data.has("te") && te_data["te"].has("imageid")) +        { +            bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); +            full_perm_object &= full_perm; +            if (!full_perm) +            { +                if (te_data["te"].has("imageitemid")) +                { +                    LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); +                    if (item_id.notNull()) +                    { +                        LLViewerInventoryItem* itemp = gInventory.getItem(item_id); +                        if (!itemp) +                        { +                            // image might be in object's inventory, but it can be not up to date +                            LLSD notif_args; +                            static std::string reason = getString("paste_error_inventory_not_found"); +                            notif_args["REASON"] = reason; +                            LLNotificationsUtil::add("FacePasteFailed", notif_args); +                            return; +                        } +                    } +                } +                else +                { +                    // Item was not found on 'copy' stage +                    // Since this happened at copy, might be better to either show this +                    // at copy stage or to drop clipboard here +                    LLSD notif_args; +                    static std::string reason = getString("paste_error_inventory_not_found"); +                    notif_args["REASON"] = reason; +                    LLNotificationsUtil::add("FacePasteFailed", notif_args); +                    return; +                } +            } +        } +    } -    mat->setMaterialID(matSD.get("teMaterialID").asUUID()); +    if (!full_perm_object) +    { +        LLNotificationsUtil::add("FacePasteTexturePermissions"); +    } -    mat->setNormalID(matSD.get("teNormalMap").asUUID()); -    mat->setNormalOffsetX(matSD.get("teNormalOffsetX").asReal()); -    mat->setNormalOffsetY(matSD.get("teNormalOffsetY").asReal()); -    mat->setNormalRepeatX(matSD.get("teNormalRepeatX").asReal()); -    mat->setNormalRepeatY(matSD.get("teNormalRepeatY").asReal()); -    mat->setNormalRotation(matSD.get("teNormalRotation").asReal()); +    LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); -    mat->setSpecularID(matSD.get("teSpecularMap").asUUID()); -    LLColor4U color; -    color.mV[0] = static_cast<U8>(matSD.get("teSecularColorR").asInteger()); -    color.mV[1] = static_cast<U8>(matSD.get("teSecularColorG").asInteger()); -    color.mV[2] = static_cast<U8>(matSD.get("teSecularColorB").asInteger()); -    color.mV[3] = static_cast<U8>(matSD.get("teSecularColorA").asInteger()); -    mat->setSpecularLightColor(color); -    mat->setSpecularLightExponent(static_cast<U8>(matSD.get("teSpecularExponent").asInteger())); -    mat->setSpecularOffsetX(matSD.get("teSpecularOffsetX").asReal()); -    mat->setSpecularOffsetY(matSD.get("teSpecularOffsetY").asReal()); -    mat->setSpecularRepeatX(matSD.get("teSpecularRepeatX").asReal()); -    mat->setSpecularRepeatY(matSD.get("teSpecularRepeatY").asReal()); -    mat->setSpecularRotation(matSD.get("teSpecularRotation").asReal()); +    LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE); +    selected_objects->applyToTEs(&paste_func); -    mat->setDiffuseAlphaMode(static_cast<U8>(matSD.get("teAlphaMode").asInteger())); -    mat->setAlphaMaskCutoff(static_cast<U8>(matSD.get("teAlphaCutoff").asInteger())); -    mat->setEnvironmentIntensity(static_cast<U8>(matSD.get("teEnvIntensity").asInteger())); -    //mat->setShaderMask(static_cast<U32>(matSD.get(teShaderMask").asInteger()); +    LLPanelFaceUpdateFunctor sendfunc(true); +    selected_objects->applyToObjects(&sendfunc); + +    LLPanelFaceNavigateHomeFunctor navigate_home_func; +    selected_objects->applyToTEs(&navigate_home_func); +} + +void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) +{ +    LLSD te_data; +    LLSD &clipboard = mClipboardParams["texture"]; // array +    if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) +    { +        te_data = *(clipboard.beginArray()); +    } +    else if (clipboard[te]) +    { +        te_data = clipboard[te]; +    } +    else +    { +        return; +    } + +    LLTextureEntry* tep = objectp->getTE(te); +    if (tep) +    { +        if (te_data.has("te")) +        { +            // Texture +            bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean(); +            bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean(); +            if (te_data["te"].has("imageid")) +            { +                const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id +                LLViewerInventoryItem* itemp_res = NULL; + +                if (te_data["te"].has("imageitemid")) +                { +                    LLUUID item_id = te_data["te"]["imageitemid"].asUUID(); +                    if (item_id.notNull()) +                    { +                        LLViewerInventoryItem* itemp = gInventory.getItem(item_id); +                        if (itemp && itemp->isFinished()) +                        { +                            // dropTextureAllFaces will fail if incomplete +                            itemp_res = itemp; +                        } +                        else +                        { +                            // Theoretically shouldn't happend, but if it does happen, we +                            // might need to add a notification to user that paste will fail +                            // since inventory isn't fully loaded +                            LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL; +                        } +                    } +                } +                // for case when item got removed from inventory after we pressed 'copy' +                // or texture got pasted into previous object +                if (!itemp_res && !full_perm) +                { +                    // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable. +                    LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL; +                    // Todo: fix this, we are often searching same texture multiple times (equal to number of faces) +                    // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work +                    LLViewerInventoryCategory::cat_array_t cats; +                    LLViewerInventoryItem::item_array_t items; +                    LLAssetIDMatches asset_id_matches(imageid); +                    gInventory.collectDescendentsIf(LLUUID::null, +                        cats, +                        items, +                        LLInventoryModel::INCLUDE_TRASH, +                        asset_id_matches); + +                    // Extremely unreliable and perfomance unfriendly. +                    // But we need this to check permissions and it is how texture control finds items +                    for (S32 i = 0; i < items.size(); i++) +                    { +                        LLViewerInventoryItem* itemp = items[i]; +                        if (itemp && itemp->isFinished()) +                        { +                            // dropTextureAllFaces will fail if incomplete +                            LLPermissions item_permissions = itemp->getPermissions(); +                            if (item_permissions.allowOperationBy(PERM_COPY, +                                gAgent.getID(), +                                gAgent.getGroupID())) +                            { +                                itemp_res = itemp; +                                break; // first match +                            } +                        } +                    } +                } + +                if (itemp_res) +                { +                    if (te == -1) // all faces +                    { +                        LLToolDragAndDrop::dropTextureAllFaces(objectp, +                            itemp_res, +                            from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, +                            LLUUID::null); +                    } +                    else // one face +                    { +                        LLToolDragAndDrop::dropTextureOneFace(objectp, +                            te, +                            itemp_res, +                            from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT, +                            LLUUID::null, +                            0); +                    } +                } +                // not an inventory item or no complete items +                else if (full_perm) +                { +                    // Either library, local or existed as fullperm when user made a copy +                    LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); +                    objectp->setTEImage(U8(te), image); +                } +            } + +            if (te_data["te"].has("bumpmap")) +            { +                objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger()); +            } +            if (te_data["te"].has("bumpshiny")) +            { +                objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger()); +            } +            if (te_data["te"].has("bumpfullbright")) +            { +                objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger()); +            } + +            // Texture map +            if (te_data["te"].has("scales") && te_data["te"].has("scalet")) +            { +                objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal()); +            } +            if (te_data["te"].has("offsets") && te_data["te"].has("offsett")) +            { +                objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal()); +            } +            if (te_data["te"].has("imagerot")) +            { +                objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal()); +            } + +            // Media +            if (te_data["te"].has("media_flags")) +            { +                U8 media_flags = te_data["te"]["media_flags"].asInteger(); +                objectp->setTEMediaFlags(te, media_flags); +                LLVOVolume *vo = dynamic_cast<LLVOVolume*>(objectp); +                if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY)) +                { +                    vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/); +                } +            } +            else +            { +                // Keep media flags on destination unchanged +            } +        } + +        if (te_data.has("material")) +        { +            LLUUID object_id = objectp->getID(); + +            LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); + +            // Normal +            // Replace placeholders with target's +            if (te_data["material"].has("NormMapNoCopy")) +            { +                LLMaterialPtr material = tep->getMaterialParams(); +                if (material.notNull()) +                { +                    LLUUID id = material->getNormalID(); +                    if (id.notNull()) +                    { +                        te_data["material"]["NormMap"] = id; +                    } +                } +            } +            LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id); +            LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id); +            LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id); +            LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id); +            LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id); +            LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id); + +            // Specular +                // Replace placeholders with target's +            if (te_data["material"].has("SpecMapNoCopy")) +            { +                LLMaterialPtr material = tep->getMaterialParams(); +                if (material.notNull()) +                { +                    LLUUID id = material->getSpecularID(); +                    if (id.notNull()) +                    { +                        te_data["material"]["SpecMap"] = id; +                    } +                } +            } +            LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id); +            LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id); +            LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id); +            LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id); +            LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id); +            LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id); +            LLColor4 spec_color(te_data["material"]["SpecColor"]); +            LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te); +            LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id); +            LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id); +            LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["SpecRot"].asInteger(), te, object_id); +            if (te_data.has("te") && te_data["te"].has("shiny")) +            { +                objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger()); +            } +        } +    } +} + +void LLPanelFace::menuDoToSelected(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste +    if (command == "color_paste") +    { +        onPasteColor(); +    } +    else if (command == "texture_paste") +    { +        onPasteTexture(); +    } +    // copy +    else if (command == "color_copy") +    { +        onCopyColor(); +    } +    else if (command == "texture_copy") +    { +        onCopyTexture(); +    } +} + +bool LLPanelFace::menuEnableItem(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste options +    if (command == "color_paste") +    { +        return mClipboardParams.has("color"); +    } +    else if (command == "texture_paste") +    { +        return mClipboardParams.has("texture"); +    } +    return false;  } @@ -3049,3 +3691,197 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic  	} max_diff_repeats_func;  	identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );  } + + +void LLPanelFace::onSaveMaterial(void* userdata) +{ +    // DRTVWR-559, Q&D material picker - save to inventory goes here +    LL_DEBUGS("Material") << "saving render material to inventory" << LL_ENDL; + +    std::string name = "New Material"; + +	LLSD material_data = llsd::map( +		"version", "1", +		"material", LLSD::emptyMap() +	); + +    // gen a new uuid for this asset +    LLTransactionID tid; +    tid.generate();     // timestamp-based randomization + uniquification +    LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + +    material_data["material"] = renderMaterialToLLSD(new_asset_id, userdata); +    std::stringstream output; +    LLSDSerialize::toNotation(material_data, output); + +    //S32 expected_upload_cost = 0;// LLAgentBenefitsMgr::current().getTextureUploadCost(); +     +    std::string res_name = name; +    std::string res_desc = "Saved Material"; +    //LLFolderType::EType folder_type = LLFolderType::FT_MATERIAL; +    //LLInventoryType::EType inv_type = LLInventoryType::IT_MATERIAL; +    U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner(); + +    LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); +    const U8 subtype = NO_INV_SUBTYPE;  // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? + +    create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, res_name, res_desc, +        LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm, +        new LLBoostFuncInventoryCallback([output=output.str()](LLUUID const & inv_item_id){ +            // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() +            LLResourceUploadInfo::ptr_t uploadInfo = +                std::make_shared<LLBufferedAssetUploadInfo>( +                    inv_item_id, +                    LLAssetType::AT_SETTINGS, // TODO switch to AT_MATERIAL +                    output, +                    [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) { +                        LL_INFOS("Material") << "inventory item uploaded.  item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL; +                        LLSD params = llsd::map("ASSET_ID", new_asset_id); +                        LLNotificationsUtil::add("MaterialCreated", params); +                    }); + +            const LLViewerRegion* region = gAgent.getRegion(); +            if (region) +            { +                 std::string agent_url(region->getCapability("UpdateSettingsAgentInventory")); +                 if (agent_url.empty()) +                 { +                     LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL; +                 } +                 LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo); +            } +        }) +    ); + +} + +// Fill an LLSD with data describing the current face's texture settings +// TODO 2022-05 FUBAR there are both colliding and different data in LLPanelFace vs the TE.  Also, neither one has the diffuse tex settings. +//               +LLSD LLPanelFace::renderMaterialToLLSD(LLUUID uuid, void* userdata) +{ +    llassert(userdata != nullptr); + +    LLSD sd; + +    sd.insert("RenderMaterialUUID",    LLSD(uuid)); + +    // now pull same data from the selected TE (same but different. W T F?)  +    LLMaterialPtr mat = nullptr; +    bool ident; // ? +    LLSelectedTEMaterial::getCurrent(mat, ident); + +    if (mat) +    { +        sd.insert("teMaterialID", LLSD(mat->getMaterialID())); + +        sd.insert("teNormalMap", LLSD(mat->getNormalID())); +        sd.insert("teNormalOffsetX", LLSD(mat->getNormalOffsetX())); +        sd.insert("teNormalOffsetY", LLSD(mat->getNormalOffsetY())); +        sd.insert("teNormalRepeatX", LLSD(mat->getNormalRepeatX())); +        sd.insert("teNormalRepeatY", LLSD(mat->getNormalRepeatY())); +        sd.insert("teNormalRotation", LLSD(mat->getNormalRotation())); + +        sd.insert("teSpecularMap", LLSD(mat->getSpecularID())); +        LLColor4U color = mat->getSpecularLightColor(); + +        sd.insert("teSpecularColorR", LLSD(static_cast<S32>(color.mV[0]))); +        sd.insert("teSpecularColorG", LLSD(static_cast<S32>(color.mV[1]))); +        sd.insert("teSpecularColorB", LLSD(static_cast<S32>(color.mV[2]))); +        sd.insert("teSpecularColorA", LLSD(static_cast<S32>(color.mV[3]))); +        sd.insert("teSpecularExponent", LLSD(static_cast<S32>(mat->getSpecularLightExponent()))); +        sd.insert("teSpecularOffsetX", LLSD(mat->getSpecularOffsetX())); +        sd.insert("teSpecularOffsetY", LLSD(mat->getSpecularOffsetY())); +        sd.insert("teSpecularRepeatX", LLSD(mat->getSpecularRepeatX())); +        sd.insert("teSpecularRepeatY", LLSD(mat->getSpecularRepeatY())); +        sd.insert("teSpecularRotation", LLSD(mat->getSpecularRotation())); + +        sd.insert("teAlphaMode", LLSD(static_cast<S32>(mat->getDiffuseAlphaMode()))); +        sd.insert("teAlphaCutoff", LLSD(static_cast<S32>(mat->getAlphaMaskCutoff()))); +        sd.insert("teEnvIntensity", LLSD(static_cast<S32>(mat->getEnvironmentIntensity()))); +        sd.insert("teShaderMask", LLSD(static_cast<S32>(mat->getShaderMask()))); +    } +    else +    { +        // pull data from the LLPanelFace +        LLPanelFace* instance = static_cast<LLPanelFace*>(userdata); +        sd.insert("pfNormalMap",         LLSD(instance->getCurrentNormalMap())); +        sd.insert("pfSpecularMap",       LLSD(instance->getCurrentSpecularMap())); +        sd.insert("pfShininess",         LLSD(static_cast<S32>(instance->getCurrentShininess()))); +        sd.insert("pfBumpiness",         LLSD(static_cast<S32>(instance->getCurrentBumpiness()))); +        sd.insert("pfAlphaMode",         LLSD(static_cast<S32>(instance->getCurrentDiffuseAlphaMode()))); +        sd.insert("pfAlphaCutoff",       LLSD(static_cast<S32>(instance->getCurrentAlphaMaskCutoff()))); +        sd.insert("pfEnvIntensity",      LLSD(static_cast<S32>(instance->getCurrentEnvIntensity()))); +        sd.insert("pfGlossiness",        LLSD(static_cast<S32>(instance->getCurrentGlossiness()))); +        sd.insert("pfNormalRotation",    LLSD(instance->getCurrentBumpyRot())); +        sd.insert("pfNormalScaleU",      LLSD(instance->getCurrentBumpyScaleU())); +        sd.insert("pfNormalScaleV",      LLSD(instance->getCurrentBumpyScaleV())); +        sd.insert("pfNormalOffsetU",     LLSD(instance->getCurrentBumpyOffsetU())); +        sd.insert("pfNormalOffsetV",     LLSD(instance->getCurrentBumpyOffsetV())); +        sd.insert("pfSpecularRotation",  LLSD(instance->getCurrentShinyRot())); +        sd.insert("pfSpecularScaleU",    LLSD(instance->getCurrentShinyScaleU())); +        sd.insert("pfSpecularScaleV",    LLSD(instance->getCurrentShinyScaleV())); +        sd.insert("pfSpecularOffsetU",   LLSD(instance->getCurrentShinyOffsetU())); +        sd.insert("pfSpecularOffsetV",   LLSD(instance->getCurrentShinyOffsetV())); +        sd.insert("pfMaterialID",        LLSD(instance->getCurrentMaterialID())); +    } + +    return sd; +} + +// Take the individual texture settings from the material and apply to current face & TE +void LLPanelFace::applyMaterialUUID(LLUUID uuid, void* userdata) +{ +    llassert(userdata != nullptr); +    //LLPanelFace* instance = static_cast<LLPanelFace*>(userdata); +     +    LLFileSystem material_file(uuid, LLAssetType::AT_MATERIAL, LLFileSystem::READ); +    S32 bufsize = material_file.getSize(); +    llassert(bufsize > 0); +    std::vector<U8> buffer(bufsize); +    material_file.read(&buffer[0], bufsize); +    std::istringstream input(std::string(buffer.begin(), buffer.end()));  // TODO - extend LLFileSystem to expose iostream interface +    LLSD matSD; + +    LLSDSerialize::fromNotation(matSD, input, bufsize); + +    LL_INFOS() << "dump matSD: " << matSD << LL_ENDL; + +    // strip off the versioning wrapper for now +    matSD = matSD["material"]; + +    // wrong, oops. llassert(uuid == matSD.get("RenderMaterialUUID").asUUID());      // if not, whoo boy + +    LLMaterialPtr mat = nullptr; +    bool ident; // ? +    LLSelectedTEMaterial::getCurrent(mat, ident); + +    mat->setMaterialID(matSD.get("teMaterialID").asUUID()); + +    mat->setNormalID(matSD.get("teNormalMap").asUUID()); +    mat->setNormalOffsetX(matSD.get("teNormalOffsetX").asReal()); +    mat->setNormalOffsetY(matSD.get("teNormalOffsetY").asReal()); +    mat->setNormalRepeatX(matSD.get("teNormalRepeatX").asReal()); +    mat->setNormalRepeatY(matSD.get("teNormalRepeatY").asReal()); +    mat->setNormalRotation(matSD.get("teNormalRotation").asReal()); + +    mat->setSpecularID(matSD.get("teSpecularMap").asUUID()); +    LLColor4U color; +    color.mV[0] = static_cast<U8>(matSD.get("teSecularColorR").asInteger()); +    color.mV[1] = static_cast<U8>(matSD.get("teSecularColorG").asInteger()); +    color.mV[2] = static_cast<U8>(matSD.get("teSecularColorB").asInteger()); +    color.mV[3] = static_cast<U8>(matSD.get("teSecularColorA").asInteger()); +    mat->setSpecularLightColor(color); +    mat->setSpecularLightExponent(static_cast<U8>(matSD.get("teSpecularExponent").asInteger())); +    mat->setSpecularOffsetX(matSD.get("teSpecularOffsetX").asReal()); +    mat->setSpecularOffsetY(matSD.get("teSpecularOffsetY").asReal()); +    mat->setSpecularRepeatX(matSD.get("teSpecularRepeatX").asReal()); +    mat->setSpecularRepeatY(matSD.get("teSpecularRepeatY").asReal()); +    mat->setSpecularRotation(matSD.get("teSpecularRotation").asReal()); + +    mat->setDiffuseAlphaMode(static_cast<U8>(matSD.get("teAlphaMode").asInteger())); +    mat->setAlphaMaskCutoff(static_cast<U8>(matSD.get("teAlphaCutoff").asInteger())); +    mat->setEnvironmentIntensity(static_cast<U8>(matSD.get("teEnvIntensity").asInteger())); +    //mat->setShaderMask(static_cast<U32>(matSD.get(teShaderMask").asInteger()); +} + diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index a8ecf8fdf2..08dc619402 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,6 +47,7 @@ class LLUICtrl;  class LLViewerObject;  class LLFloater;  class LLMaterialID; +class LLMenuButton;  // Represents an edit for use in replicating the op across one or more materials in the selection set.  // @@ -96,6 +97,8 @@ public:  	LLPanelFace();  	virtual ~LLPanelFace(); +    void draw(); +  	void			refresh();  	void			setMediaURL(const std::string& url);  	void			setMediaType(const std::string& mime_type); @@ -128,6 +131,8 @@ protected:  	void			sendMedia();      void            alignTestureLayer(); +    void            updateCopyTexButton(); +  	// this function is to return TRUE if the drag should succeed.  	static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); @@ -210,6 +215,18 @@ protected:      static LLSD     renderMaterialToLLSD(LLUUID uuid, void* userdata);      static void     applyMaterialUUID(LLUUID uuid, void*); +public: // needs to be accessible to selection manager +    void            onCopyColor(); // records all selected faces +    void            onPasteColor(); // to specific face +    void            onPasteColor(LLViewerObject* objectp, S32 te); // to specific face +    void            onCopyTexture(); +    void            onPasteTexture(); +    void            onPasteTexture(LLViewerObject* objectp, S32 te); + +protected: +    void            menuDoToSelected(const LLSD& userdata); +    bool            menuEnableItem(const LLSD& userdata); +  	static F32     valueGlow(LLViewerObject* object, S32 face); @@ -406,7 +423,10 @@ private:  	 * If agent selects texture which is not allowed to be applied for the currently selected object,  	 * all controls of the floater texture picker which allow to apply the texture will be disabled.  	 */ -	void onTextureSelectionChanged(LLInventoryItem* itemp); +    void onTextureSelectionChanged(LLInventoryItem* itemp); + +    LLMenuButton*   mMenuClipboardColor; +    LLMenuButton*   mMenuClipboardTexture;  	bool mIsAlpha; @@ -421,7 +441,9 @@ private:  	 * up-arrow on a spinner, and avoids running afoul of its throttle.  	 */  	bool mUpdateInFlight; -	bool mUpdatePending; +    bool mUpdatePending; + +    LLSD            mClipboardParams;  public:  	#if defined(DEF_GET_MAT_STATE) diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 389baa86cd..07a8641a92 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,6 +1,6 @@  /** - * @file llpanelavatar.cpp - * @brief LLPanelAvatar and related class implementations + * @file llpanelimcontrolpanel.cpp + * @brief LLPanelIMControlPanel and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index ce17da3076..c3334605ae 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -29,6 +29,7 @@  #include "llpanellandmarks.h"  #include "llbutton.h" +#include "llfloaterprofile.h"  #include "llfloaterreg.h"  #include "llnotificationsutil.h"  #include "llsdutil.h" @@ -1003,17 +1004,6 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	return can_be_modified;  } -void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params) -{ -	pick_panel->setVisible(FALSE); -	owner->removeChild(pick_panel); -	//we need remove  observer to  avoid  processParcelInfo in the future. -	LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this); - -	delete pick_panel; -	pick_panel = NULL; -} -  bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data , EAcceptance* accept)  {  	*accept = ACCEPT_NO; @@ -1080,49 +1070,21 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,  										   LLInventoryItem* inv_item,  										   const LLParcelData& parcel_data)  { -	LLPanelPickEdit* panel_pick = LLPanelPickEdit::create();  	LLVector3d landmark_global_pos;  	landmark->getGlobalPos(landmark_global_pos); -	// let's toggle pick panel into  panel places -	LLPanel* panel_places = NULL; -	LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("places"); -	if (floaterp) -	{ -		panel_places = floaterp->findChild<LLPanel>("main_panel"); -	} - -	if (!panel_places) -	{ -		llassert(NULL != panel_places); -		return; -	} -	panel_places->addChild(panel_pick); -	LLRect paren_rect(panel_places->getRect()); -	panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE); -	panel_pick->setRect(paren_rect); -	panel_pick->onOpen(LLSD()); -  	LLPickData data;  	data.pos_global = landmark_global_pos;  	data.name = inv_item->getName();  	data.desc = inv_item->getDescription();  	data.snapshot_id = parcel_data.snapshot_id;  	data.parcel_id = parcel_data.parcel_id; -	panel_pick->setPickData(&data); - -	LLSD params; -	params["parcel_id"] = parcel_data.parcel_id; -	/* set exit callback to get back onto panel places -	 in callback we will make cleaning up( delete pick_panel instance, -	 remove landmark panel from observer list -	*/ -	panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, -			panel_pick, panel_places,params)); -	panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, -		panel_pick, panel_places,params)); -	panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, -					panel_pick, panel_places,params)); + +    LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgentID))); +    if (profile_floater) +    { +        profile_floater->createPick(data); +    }  }  void LLLandmarksPanel::doCreatePick(LLLandmark* landmark, const LLUUID &item_id) diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index d7408269b5..16f3a5dc24 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -34,7 +34,6 @@  #include "llinventorymodel.h"  #include "lllandmarklist.h"  #include "llpanelplacestab.h" -#include "llpanelpick.h"  #include "llremoteparcelrequest.h"  class LLAccordionCtrlTab; @@ -136,7 +135,6 @@ private:  	 * For now it checks cut/rename/delete/paste actions.  	 */  	bool canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const; -	void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);  	/**  	 * Landmark actions callbacks. Fire when a landmark is loaded from the list. diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp deleted file mode 100644 index 55e4ffff5e..0000000000 --- a/indra/newview/llpanelme.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**  - * @file llpanelme.cpp - * @brief Side tray "Me" (My Profile) panel - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelme.h" - -// Viewer includes -#include "llpanelprofile.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llfirstuse.h" -#include "llfloaterreg.h" -#include "llhints.h" -#include "llviewercontrol.h" - -// Linden libraries -#include "llavatarnamecache.h"		// IDEVO -#include "lliconctrl.h" -#include "llnotifications.h" -#include "llnotificationsutil.h"	// IDEVO -#include "lltabcontainer.h" -#include "lltexturectrl.h" - -static LLPanelInjector<LLPanelMe> t_panel_me_profile("panel_me"); - -LLPanelMe::LLPanelMe(void)  - : LLPanelProfile() -{ -	setAvatarId(gAgent.getID()); -} - -BOOL LLPanelMe::postBuild() -{ -	LLPanelProfile::postBuild(); - -	return TRUE; -} - -void LLPanelMe::onOpen(const LLSD& key) -{ -	LLPanelProfile::onOpen(key); -} diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 64f1fc9b90..0bfc1297d3 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -46,6 +46,7 @@  #include "llcombobox.h"  #include "llfocusmgr.h"  #include "llmanipscale.h" +#include "llmenubutton.h"  #include "llpreviewscript.h"  #include "llresmgr.h"  #include "llselectmgr.h" @@ -117,8 +118,9 @@ BOOL	LLPanelObject::postBuild()  	// Phantom checkbox  	mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl");  	childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this); -        +  	// Position +	mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn");  	mLabelPosition = getChild<LLTextBox>("label position");  	mCtrlPosX = getChild<LLSpinCtrl>("Pos X");  	childSetCommitCallback("Pos X",onCommitPosition,this); @@ -128,6 +130,7 @@ BOOL	LLPanelObject::postBuild()  	childSetCommitCallback("Pos Z",onCommitPosition,this);  	// Scale +	mMenuClipboardSize = getChild<LLMenuButton>("clipboard_size_btn");  	mLabelSize = getChild<LLTextBox>("label size");  	mCtrlScaleX = getChild<LLSpinCtrl>("Scale X");  	childSetCommitCallback("Scale X",onCommitScale,this); @@ -141,6 +144,7 @@ BOOL	LLPanelObject::postBuild()  	childSetCommitCallback("Scale Z",onCommitScale,this);  	// Rotation +	mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn");  	mLabelRotation = getChild<LLTextBox>("label rotation");  	mCtrlRotX = getChild<LLSpinCtrl>("Rot X");  	childSetCommitCallback("Rot X",onCommitRotation,this); @@ -155,6 +159,8 @@ BOOL	LLPanelObject::postBuild()  	mComboBaseType = getChild<LLComboBox>("comboBaseType");  	childSetCommitCallback("comboBaseType",onCommitParametric,this); +	mMenuClipboardParams = getChild<LLMenuButton>("clipboard_obj_params_btn"); +  	// Cut  	mLabelCut = getChild<LLTextBox>("text cut");  	mSpinCutBegin = getChild<LLSpinCtrl>("cut begin"); @@ -285,8 +291,13 @@ LLPanelObject::LLPanelObject()  	mSelectedType(MI_BOX),  	mSculptTextureRevert(LLUUID::null),  	mSculptTypeRevert(0), +    mHasClipboardPos(false), +    mHasClipboardSize(false), +    mHasClipboardRot(false),  	mSizeChanged(FALSE)  { +    mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); +    mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2));  } @@ -373,7 +384,7 @@ void LLPanelObject::getState( )  		calcp->clearVar(LLCalc::Z_POS);  	} - +	mMenuClipboardPos->setEnabled(enable_move);  	mLabelPosition->setEnabled( enable_move );  	mCtrlPosX->setEnabled(enable_move);  	mCtrlPosY->setEnabled(enable_move); @@ -399,6 +410,7 @@ void LLPanelObject::getState( )  		calcp->setVar(LLCalc::Z_SCALE, 0.f);  	} +	mMenuClipboardSize->setEnabled(enable_scale);  	mLabelSize->setEnabled( enable_scale );  	mCtrlScaleX->setEnabled( enable_scale );  	mCtrlScaleY->setEnabled( enable_scale ); @@ -430,6 +442,7 @@ void LLPanelObject::getState( )  		calcp->clearVar(LLCalc::Z_ROT);  	} +	mMenuClipboardRot->setEnabled(enable_rotate);  	mLabelRotation->setEnabled( enable_rotate );  	mCtrlRotX->setEnabled( enable_rotate );  	mCtrlRotY->setEnabled( enable_rotate ); @@ -607,7 +620,7 @@ void LLPanelObject::getState( )  		}  		else  		{ -			LL_INFOS() << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; +			LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL;  			selected_item = MI_BOX;  		} @@ -933,6 +946,7 @@ void LLPanelObject::getState( )  	// Update field enablement  	mComboBaseType	->setEnabled( enabled ); +	mMenuClipboardParams->setEnabled(enabled);  	mLabelCut		->setEnabled( enabled );  	mSpinCutBegin	->setEnabled( enabled ); @@ -1093,7 +1107,8 @@ void LLPanelObject::getState( )  			}  			mComboBaseType->setEnabled(!isMesh); -			 +			mMenuClipboardParams->setEnabled(!isMesh); +  			if (mCtrlSculptType)  			{  				if (sculpt_stitching == LL_SCULPT_TYPE_NONE) @@ -1157,11 +1172,11 @@ void LLPanelObject::sendIsPhysical()  		LLSelectMgr::getInstance()->selectionUpdatePhysics(value);  		mIsPhysical = value; -		LL_INFOS() << "update physics sent" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL;  	}  	else  	{ -		LL_INFOS() << "update physics not changed" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL;  	}  } @@ -1173,11 +1188,11 @@ void LLPanelObject::sendIsTemporary()  		LLSelectMgr::getInstance()->selectionUpdateTemporary(value);  		mIsTemporary = value; -		LL_INFOS() << "update temporary sent" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL;  	}  	else  	{ -		LL_INFOS() << "update temporary not changed" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL;  	}  } @@ -1190,11 +1205,11 @@ void LLPanelObject::sendIsPhantom()  		LLSelectMgr::getInstance()->selectionUpdatePhantom(value);  		mIsPhantom = value; -		LL_INFOS() << "update phantom sent" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL;  	}  	else  	{ -		LL_INFOS() << "update phantom not changed" << LL_ENDL; +		LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL;  	}  } @@ -1304,7 +1319,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params)  		break;  	default: -		LL_WARNS() << "Unknown base type " << selected_type  +		LL_WARNS("FloaterTools") << "Unknown base type " << selected_type   			<< " in getVolumeParams()" << LL_ENDL;  		// assume a box  		selected_type = MI_BOX; @@ -1644,13 +1659,15 @@ void LLPanelObject::sendPosition(BOOL btn_down)  	LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());  	LLViewerRegion* regionp = mObject->getRegion(); -	// Clamp the Z height -	const F32 height = newpos.mV[VZ]; -	const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); -	const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); +	if (!regionp) return;  	if (!mObject->isAttachment())  	{ +        // Clamp the Z height +        const F32 height = newpos.mV[VZ]; +        const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); +        const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); +  		if ( height < min_height)  		{  			newpos.mV[VZ] = min_height; @@ -2011,3 +2028,283 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata)  	self->sendSculpt();  } + +void LLPanelObject::menuDoToSelected(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste +    if (command == "psr_paste") +    { +        onPastePos(); +        onPasteSize(); +        onPasteRot(); +    } +    else if (command == "pos_paste") +    { +        onPastePos(); +    } +    else if (command == "size_paste") +    { +        onPasteSize(); +    } +    else if (command == "rot_paste") +    { +        onPasteRot(); +    } +    else if (command == "params_paste") +    { +        onPasteParams(); +    } +    // copy +    else if (command == "psr_copy") +    { +        onCopyPos(); +        onCopySize(); +        onCopyRot(); +    } +    else if (command == "pos_copy") +    { +        onCopyPos(); +    } +    else if (command == "size_copy") +    { +        onCopySize(); +    } +    else if (command == "rot_copy") +    { +        onCopyRot(); +    } +    else if (command == "params_copy") +    { +        onCopyParams(); +    } +} + +bool LLPanelObject::menuEnableItem(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste options +    if (command == "psr_paste") +    { +        S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +        BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) +            && (selected_count == 1); + +        if (!single_volume) +        { +            return false; +        } + +        bool enable_move; +        bool enable_modify; + +        LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + +        return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot; +    } +    else if (command == "pos_paste") +    { +        // assumes that menu won't be active if there is no move permission +        return mHasClipboardPos; +    } +    else if (command == "size_paste") +    { +        return mHasClipboardSize; +    } +    else if (command == "rot_paste") +    { +        return mHasClipboardRot; +    } +    else if (command == "params_paste") +    { +        return mClipboardParams.isMap() && !mClipboardParams.emptyMap(); +    } +    // copy options +    else if (command == "psr_copy") +    { +        S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); +        BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) +            && (selected_count == 1); + +        if (!single_volume) +        { +            return false; +        } + +        bool enable_move; +        bool enable_modify; + +        LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); + +        // since we forbid seeing values we also should forbid copying them +        return enable_move && enable_modify; +    } +    return false; +} + +void LLPanelObject::onCopyPos() +{ +    mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); + +    std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]); +    LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + +    mHasClipboardPos = true; +} + +void LLPanelObject::onCopySize() +{ +    mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); + +    std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]); +    LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + +    mHasClipboardSize = true; +} + +void LLPanelObject::onCopyRot() +{ +    mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); + +    std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]); +    LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); + +    mHasClipboardRot = true; +} + +void LLPanelObject::onPastePos() +{ +    if (!mHasClipboardPos) return; +    if (mObject.isNull()) return; + +    LLViewerRegion* regionp = mObject->getRegion(); +    if (!regionp) return; + + +    // Clamp pos on non-attachments, just keep the prims within the region +    if (!mObject->isAttachment()) +    { +        F32 max_width = regionp->getWidth(); // meters +        mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, max_width); +        mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width); +        //height will get properly clamped by sendPosition +    } + +    mCtrlPosX->set( mClipboardPos.mV[VX] ); +    mCtrlPosY->set( mClipboardPos.mV[VY] ); +    mCtrlPosZ->set( mClipboardPos.mV[VZ] ); + +    sendPosition(FALSE); +} + +void LLPanelObject::onPasteSize() +{ +    if (!mHasClipboardSize) return; + +    mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); +    mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); +    mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + +    mCtrlScaleX->set(mClipboardSize.mV[VX]); +    mCtrlScaleY->set(mClipboardSize.mV[VY]); +    mCtrlScaleZ->set(mClipboardSize.mV[VZ]); + +    sendScale(FALSE); +} + +void LLPanelObject::onPasteRot() +{ +    if (!mHasClipboardRot) return; + +    mCtrlRotX->set(mClipboardRot.mV[VX]); +    mCtrlRotY->set(mClipboardRot.mV[VY]); +    mCtrlRotZ->set(mClipboardRot.mV[VZ]); + +    sendRotation(FALSE); +} + +void LLPanelObject::onCopyParams() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp || objectp->isMesh()) +    { +        return; +    } + +    mClipboardParams.clear(); + +    // Parametrics +    LLVolumeParams params; +    getVolumeParams(params); +    mClipboardParams["volume_params"] = params.asLLSD(); + +    // Sculpted Prim +    if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) +    { +        LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + +        LLUUID texture_id = sculpt_params->getSculptTexture(); +        if (get_can_copy_texture(texture_id)) +        { +            LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; +            mClipboardParams["sculpt"]["id"] = texture_id; +        } +        else +        { +            mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); +        } + +        mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); +    } +} + +void LLPanelObject::onPasteParams() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp) +    { +        return; +    } + +    // Sculpted Prim +    if (mClipboardParams.has("sculpt")) +    { +        LLSculptParams sculpt_params; +        LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID(); +        U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger(); +        sculpt_params.setSculptTexture(sculpt_id, sculpt_type); +        objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); +    } +    else +    { +        LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); +        if (sculpt_params) +        { +            objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); +        } +    } + +    // volume params +    // make sure updateVolume() won't affect flexible +    if (mClipboardParams.has("volume_params")) +    { +        LLVolumeParams params; +        params.fromLLSD(mClipboardParams["volume_params"]); +        LLVOVolume *volobjp = (LLVOVolume *)objectp; +        if (volobjp->isFlexible()) +        { +            if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE) +            { +                params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE); +            } +        } +        else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) +        { +            params.getPathParams().setCurveType(LL_PCODE_PATH_LINE); +        } + +        objectp->updateVolume(params); +    } +} diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 8829f493fa..515dd27c0a 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl;  class LLTextBox;  class LLUICtrl;  class LLButton; +class LLMenuButton;  class LLViewerObject;  class LLComboBox;  class LLColorSwatchCtrl; @@ -66,6 +67,14 @@ public:  	static void 	onCommitPhantom(		LLUICtrl* ctrl, void* userdata);  	static void 	onCommitPhysics(		LLUICtrl* ctrl, void* userdata); +    void            onCopyPos(); +    void            onPastePos(); +    void            onCopySize(); +    void            onPasteSize(); +    void            onCopyRot(); +    void            onPasteRot(); +    void            onCopyParams(); +    void            onPasteParams();  	static void 	onCommitParametric(LLUICtrl* ctrl, void* userdata); @@ -75,6 +84,9 @@ public:  	BOOL     		onDropSculpt(LLInventoryItem* item);  	static void     onCommitSculptType(    LLUICtrl *ctrl, void* userdata); +    void            menuDoToSelected(const LLSD& userdata); +    bool            menuEnableItem(const LLSD& userdata); +  protected:  	void			getState(); @@ -92,6 +104,7 @@ protected:  protected:  	// Per-object options  	LLComboBox*		mComboBaseType; +	LLMenuButton*	mMenuClipboardParams;  	LLTextBox*		mLabelCut;  	LLSpinCtrl*		mSpinCutBegin; @@ -131,17 +144,20 @@ protected:  	LLTextBox*		mLabelRevolutions;  	LLSpinCtrl*		mSpinRevolutions; +	LLMenuButton*   mMenuClipboardPos;  	LLTextBox*		mLabelPosition;  	LLSpinCtrl*		mCtrlPosX;  	LLSpinCtrl*		mCtrlPosY;  	LLSpinCtrl*		mCtrlPosZ; +	LLMenuButton*   mMenuClipboardSize;  	LLTextBox*		mLabelSize;  	LLSpinCtrl*		mCtrlScaleX;  	LLSpinCtrl*		mCtrlScaleY;  	LLSpinCtrl*		mCtrlScaleZ;  	BOOL			mSizeChanged; +	LLMenuButton*   mMenuClipboardRot;  	LLTextBox*		mLabelRotation;  	LLSpinCtrl*		mCtrlRotX;  	LLSpinCtrl*		mCtrlRotY; @@ -157,7 +173,7 @@ protected:  	LLComboBox      *mCtrlSculptType;  	LLCheckBoxCtrl  *mCtrlSculptMirror;  	LLCheckBoxCtrl  *mCtrlSculptInvert; -	 +  	LLVector3		mCurEulerDegrees;		// to avoid sending rotation when not changed  	BOOL			mIsPhysical;			// to avoid sending "physical" when not changed  	BOOL			mIsTemporary;			// to avoid sending "temporary" when not changed @@ -167,6 +183,15 @@ protected:  	LLUUID          mSculptTextureRevert;   // so we can revert the sculpt texture on cancel  	U8              mSculptTypeRevert;      // so we can revert the sculpt type on cancel +    LLVector3       mClipboardPos; +    LLVector3       mClipboardSize; +    LLVector3       mClipboardRot; +    LLSD            mClipboardParams; + +    bool            mHasClipboardPos; +    bool            mHasClipboardSize; +    bool            mHasClipboardRot; +  	LLPointer<LLViewerObject> mObject;  	LLPointer<LLViewerObject> mRootObject;  }; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 998cffef4a..2faa3a7137 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -618,7 +618,18 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const  	if (cat)  	{ -		mDisplayName.assign(cat->getName()); +        std::string name = cat->getName(); +        if (mChildren.size() > 0) +        { +            // Add item count +            // Normally we would be using getLabelSuffix for this +            // but object's inventory just uses displaynames +            LLStringUtil::format_map_t args; +            args["[ITEMS_COUNT]"] = llformat("%d", mChildren.size()); + +            name.append(" " + LLTrans::getString("InventoryItemsCount", args)); +        } +		mDisplayName.assign(name);  	}  	return mDisplayName; @@ -1578,6 +1589,8 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  		{  			createViewsForCategory(&contents, inventory_root, new_folder);  		} +        // Refresh for label to add item count +        new_folder->refresh();  	}  } diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp deleted file mode 100644 index 40326cfb39..0000000000 --- a/indra/newview/llpanelpick.cpp +++ /dev/null @@ -1,620 +0,0 @@ -/**  - * @file llpanelpick.cpp - * @brief LLPanelPick class implementation - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -// Display of a "Top Pick" used both for the global top picks in the  -// Find directory, and also for each individual user's picks in their -// profile. - -#include "llviewerprecompiledheaders.h" - -#include "llpanelpick.h" - -#include "message.h" - -#include "llparcel.h" - -#include "llbutton.h" -#include "llfloaterreg.h" -#include "lliconctrl.h" -#include "lllineeditor.h" -#include "llpanel.h" -#include "llscrollcontainer.h" -#include "lltexteditor.h" - -#include "llagent.h" -#include "llagentpicksinfo.h" -#include "llavatarpropertiesprocessor.h" -#include "llfloaterworldmap.h" -#include "lltexturectrl.h" -#include "lluiconstants.h" -#include "llviewerparcelmgr.h" -#include "llviewerregion.h" -#include "llworldmap.h" - - -#define XML_PANEL_EDIT_PICK "panel_edit_pick.xml" -#define XML_PANEL_PICK_INFO "panel_pick_info.xml" - -#define XML_NAME		"pick_name" -#define XML_DESC		"pick_desc" -#define XML_SNAPSHOT	"pick_snapshot" -#define XML_LOCATION	"pick_location" - -#define XML_BTN_ON_TXTR "edit_icon" -#define XML_BTN_SAVE "save_changes_btn" - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -//static -LLPanelPickInfo* LLPanelPickInfo::create() -{ -	LLPanelPickInfo* panel = new LLPanelPickInfo(); -	panel->buildFromFile(XML_PANEL_PICK_INFO); -	return panel; -} - -LLPanelPickInfo::LLPanelPickInfo() - : LLPanel() - , LLAvatarPropertiesObserver() - , LLRemoteParcelInfoObserver() - , mAvatarId(LLUUID::null) - , mSnapshotCtrl(NULL) - , mPickId(LLUUID::null) - , mParcelId(LLUUID::null) - , mRequestedId(LLUUID::null) - , mScrollingPanelMinHeight(0) - , mScrollingPanelWidth(0) - , mScrollingPanel(NULL) - , mScrollContainer(NULL) -{ -} - -LLPanelPickInfo::~LLPanelPickInfo() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); - -	if (mParcelId.notNull()) -	{ -		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); -	} -} - -void LLPanelPickInfo::onOpen(const LLSD& key) -{ -	LLUUID avatar_id = key["avatar_id"]; -	if(avatar_id.isNull()) -	{ -		return; -	} - -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver( -			getAvatarId(), this); -	} - -	setAvatarId(avatar_id); - -	resetData(); -	resetControls(); - -	setPickId(key["pick_id"]); -	setPickName(key["pick_name"]); -	setPickDesc(key["pick_desc"]); -	setSnapshotId(key["snapshot_id"]); - -	LLAvatarPropertiesProcessor::getInstance()->addObserver( -		getAvatarId(), this); -	LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest( -		getAvatarId(), getPickId()); -} - -BOOL LLPanelPickInfo::postBuild() -{ -	mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT); - -	childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this)); -	childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this)); -	childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this)); - -	mScrollingPanel = getChild<LLPanel>("scroll_content_panel"); -	mScrollContainer = getChild<LLScrollContainer>("profile_scroll"); - -	mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight(); -	mScrollingPanelWidth = mScrollingPanel->getRect().getWidth(); - -	LLTextEditor* text_desc = getChild<LLTextEditor>(XML_DESC); -	text_desc->setContentTrusted(false); - -	return TRUE; -} - -void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent) -{ -	LLPanel::reshape(width, height, called_from_parent); - -	if (!mScrollContainer || !mScrollingPanel) -		return; - -	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - -	S32 scroll_height = mScrollContainer->getRect().getHeight(); -	if (mScrollingPanelMinHeight >= scroll_height) -	{ -		mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight); -	} -	else -	{ -		mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height); -	} -} - -void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_PICK_INFO != type) -	{ -		return; -	} -	LLPickData* pick_info = static_cast<LLPickData*>(data); -	if(!pick_info  -		|| pick_info->creator_id != getAvatarId()  -		|| pick_info->pick_id != getPickId()) -	{ -		return; -	} - -	mParcelId = pick_info->parcel_id; -	setSnapshotId(pick_info->snapshot_id); -	setPickName(pick_info->name); -	setPickDesc(pick_info->desc); -	setPosGlobal(pick_info->pos_global); - -	// Send remote parcel info request to get parcel name and sim (region) name. -	sendParcelInfoRequest(); - -	// *NOTE dzaporozhan -	// We want to keep listening to APT_PICK_INFO because user may  -	// edit the Pick and we have to update Pick info panel. -	// revomeObserver is called from onClickBack -} - -void LLPanelPickInfo::sendParcelInfoRequest() -{ -	if (mParcelId != mRequestedId) -	{ -		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); -		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); - -		mRequestedId = mParcelId; -	} -} - -void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("back_btn")->setClickedCallback(cb); -} - -void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data) -{ -	setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, -		parcel_data.sim_name, getPosGlobal())); - -	// We have received parcel info for the requested ID so clear it now. -	mRequestedId.setNull(); - -	if (mParcelId.notNull()) -	{ -		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); -	} -} - -void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("edit_btn")->setClickedCallback(cb); -} - -// PROTECTED AREA - -void LLPanelPickInfo::resetControls() -{ -	if(getAvatarId() == gAgent.getID()) -	{ -		getChildView("edit_btn")->setEnabled(TRUE); -		getChildView("edit_btn")->setVisible( TRUE); -	} -	else -	{ -		getChildView("edit_btn")->setEnabled(FALSE); -		getChildView("edit_btn")->setVisible( FALSE); -	} -} - -void LLPanelPickInfo::resetData() -{ -	setPickName(LLStringUtil::null); -	setPickDesc(LLStringUtil::null); -	setPickLocation(LLStringUtil::null); -	setPickId(LLUUID::null); -	setSnapshotId(LLUUID::null); -	mPosGlobal.clearVec(); -	mParcelId.setNull(); -	mRequestedId.setNull(); -} - -// static -std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global) -{ -	std::string location_text; -	location_text.append(owner_name); -	if (!original_name.empty()) -	{ -		if (!location_text.empty()) location_text.append(", "); -		location_text.append(original_name); - -	} -	if (!sim_name.empty()) -	{ -		if (!location_text.empty()) location_text.append(", "); -		location_text.append(sim_name); -	} - -	if (!location_text.empty()) location_text.append(" "); - -	if (!pos_global.isNull()) -	{ -		S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; -		S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; -		S32 region_z = ll_round((F32)pos_global.mdV[VZ]); -		location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); -	} -	return location_text; -} - -void LLPanelPickInfo::setSnapshotId(const LLUUID& id)  -{  -	mSnapshotCtrl->setImageAssetID(id); -	mSnapshotCtrl->setValid(TRUE); -} - -void LLPanelPickInfo::setPickName(const std::string& name) -{ -	getChild<LLUICtrl>(XML_NAME)->setValue(name); -} - -void LLPanelPickInfo::setPickDesc(const std::string& desc) -{ -	getChild<LLUICtrl>(XML_DESC)->setValue(desc); -} - -void LLPanelPickInfo::setPickLocation(const std::string& location) -{ -	getChild<LLUICtrl>(XML_LOCATION)->setValue(location); -} - -void LLPanelPickInfo::onClickMap() -{ -	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); -	LLFloaterReg::showInstance("world_map", "center"); -} - -void LLPanelPickInfo::onClickTeleport() -{ -	if (!getPosGlobal().isExactlyZero()) -	{ -		gAgent.teleportViaLocation(getPosGlobal()); -		LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); -	} -} - -void LLPanelPickInfo::onClickBack() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -//static -LLPanelPickEdit* LLPanelPickEdit::create() -{ -	LLPanelPickEdit* panel = new LLPanelPickEdit(); -	panel->buildFromFile(XML_PANEL_EDIT_PICK); -	return panel; -} - -LLPanelPickEdit::LLPanelPickEdit() - : LLPanelPickInfo() - , mLocationChanged(false) - , mNeedData(true) - , mNewPick(false) -{ -} - -LLPanelPickEdit::~LLPanelPickEdit() -{ -} - -void LLPanelPickEdit::onOpen(const LLSD& key) -{ -	LLUUID pick_id = key["pick_id"]; -	mNeedData = true; - -	// creating new Pick -	if(pick_id.isNull()) -	{ -		mNewPick = true; - -		setAvatarId(gAgent.getID()); - -		resetData(); -		resetControls(); - -		setPosGlobal(gAgent.getPositionGlobal()); - -		LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; -		std::string pick_name, pick_desc, region_name; - -		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); -		if(parcel) -		{ -			parcel_id = parcel->getID(); -			pick_name = parcel->getName(); -			pick_desc = parcel->getDesc(); -			snapshot_id = parcel->getSnapshotID(); -		} - -		LLViewerRegion* region = gAgent.getRegion(); -		if(region) -		{ -			region_name = region->getName(); -		} - -		setParcelID(parcel_id); -		getChild<LLUICtrl>("pick_name")->setValue(pick_name.empty() ? region_name : pick_name); -		getChild<LLUICtrl>("pick_desc")->setValue(pick_desc); -		setSnapshotId(snapshot_id); -		setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal())); - -		enableSaveButton(true); -	} -	// editing existing pick -	else -	{ -		mNewPick = false; -		LLPanelPickInfo::onOpen(key); - -		enableSaveButton(false); -	} - -	resetDirty(); -} - -void LLPanelPickEdit::setPickData(const LLPickData* pick_data) -{ -	if(!pick_data) -	{ -		return; -	} - -	mNeedData = false; - -	setParcelID(pick_data->parcel_id); -	getChild<LLUICtrl>("pick_name")->setValue(pick_data->name); -	getChild<LLUICtrl>("pick_desc")->setValue(pick_data->desc); -	setSnapshotId(pick_data->snapshot_id); -	setPosGlobal(pick_data->pos_global); -	setPickLocation(createLocationText(LLStringUtil::null, pick_data->name, -			pick_data->sim_name, pick_data->pos_global)); -} - -BOOL LLPanelPickEdit::postBuild() -{ -	LLPanelPickInfo::postBuild(); - -	mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this)); - -	LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name"); -	line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL); - -	LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc"); -	text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1)); - -	childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this)); -	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this)); - -	initTexturePickerMouseEvents(); - -	return TRUE; -} - -void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("save_changes_btn")->setClickedCallback(cb); -} - -void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb) -{ -	getChild<LLButton>("cancel_btn")->setClickedCallback(cb); -} - -void LLPanelPickEdit::resetDirty() -{ -	LLPanelPickInfo::resetDirty(); - -	getChild<LLLineEditor>("pick_name")->resetDirty(); -	getChild<LLTextEditor>("pick_desc")->resetDirty(); -	mSnapshotCtrl->resetDirty(); -	mLocationChanged = false; -} - -BOOL LLPanelPickEdit::isDirty() const -{ -	if( mNewPick -		|| LLPanelPickInfo::isDirty() -		|| mLocationChanged -		|| mSnapshotCtrl->isDirty() -		|| getChild<LLLineEditor>("pick_name")->isDirty() -		|| getChild<LLTextEditor>("pick_desc")->isDirty()) -	{ -		return TRUE; -	} -	return FALSE; -} - -// PROTECTED AREA - -void LLPanelPickEdit::sendUpdate() -{ -	LLPickData pick_data; - -	// If we don't have a pick id yet, we'll need to generate one, -	// otherwise we'll keep overwriting pick_id 00000 in the database. -	if (getPickId().isNull())  -	{ -		getPickId().generate(); -	} - -	pick_data.agent_id = gAgent.getID(); -	pick_data.session_id = gAgent.getSessionID(); -	pick_data.pick_id = getPickId(); -	pick_data.creator_id = gAgent.getID();; - -	//legacy var  need to be deleted -	pick_data.top_pick = FALSE;  -	pick_data.parcel_id = mParcelId; -	pick_data.name = getChild<LLUICtrl>(XML_NAME)->getValue().asString(); -	pick_data.desc = getChild<LLUICtrl>(XML_DESC)->getValue().asString(); -	pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); -	pick_data.pos_global = getPosGlobal(); -	pick_data.sort_order = 0; -	pick_data.enabled = TRUE; - -	LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); - -	if(mNewPick) -	{ -		// Assume a successful create pick operation, make new number of picks -		// available immediately. Actual number of picks will be requested in  -		// LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. -		LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); -	} -} - -void LLPanelPickEdit::onSnapshotChanged() -{ -	enableSaveButton(true); -} - -void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl) -{ -	enableSaveButton(isDirty()); -} - -void LLPanelPickEdit::resetData() -{ -	LLPanelPickInfo::resetData(); -	mLocationChanged = false; -} - -void LLPanelPickEdit::enableSaveButton(bool enable) -{ -	getChildView(XML_BTN_SAVE)->setEnabled(enable); -} - -void LLPanelPickEdit::onClickSetLocation() -{ -	// Save location for later use. -	setPosGlobal(gAgent.getPositionGlobal()); - -	std::string parcel_name, region_name; - -	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); -	if (parcel) -	{ -		mParcelId = parcel->getID(); -		parcel_name = parcel->getName(); -	} - -	LLViewerRegion* region = gAgent.getRegion(); -	if(region) -	{ -		region_name = region->getName(); -	} - -	setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); - -	mLocationChanged = true; -	enableSaveButton(TRUE); -} - -void LLPanelPickEdit::onClickSave() -{ -	sendUpdate(); - -	mLocationChanged = false; - -	LLSD params; -	params["action"] = "save_new_pick"; -	notifyParent(params); -} - -std::string LLPanelPickEdit::getLocationNotice() -{ -	static std::string notice = getString("location_notice"); -	return notice; -} - -void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type) -{ -	if(mNeedData) -	{ -		LLPanelPickInfo::processProperties(data, type); -	} -} - -// PRIVATE AREA - -void LLPanelPickEdit::initTexturePickerMouseEvents() -{ -	text_icon = getChild<LLIconCtrl>(XML_BTN_ON_TXTR); -	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1)); -	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1)); -	 -	text_icon->setVisible(FALSE); -} -		 -void LLPanelPickEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) -{ -        text_icon->setVisible(TRUE); -} - -void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) -{ -	text_icon->setVisible(FALSE); -} diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h deleted file mode 100644 index 7a8bd66fcf..0000000000 --- a/indra/newview/llpanelpick.h +++ /dev/null @@ -1,264 +0,0 @@ -/**  - * @file llpanelpick.h - * @brief LLPanelPick class definition - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -// Display of a "Top Pick" used both for the global top picks in the  -// Find directory, and also for each individual user's picks in their -// profile. - -#ifndef LL_LLPANELPICK_H -#define LL_LLPANELPICK_H - -#include "llpanel.h" -#include "llremoteparcelrequest.h" -#include "llavatarpropertiesprocessor.h" - -class LLIconCtrl; -class LLTextureCtrl; -class LLScrollContainer; -class LLMessageSystem; -class LLAvatarPropertiesObserver; - -/** - * Panel for displaying Pick Information - snapshot, name, description, etc. - */ -class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver -{ -	LOG_CLASS(LLPanelPickInfo); -public: -	 -	// Creates new panel -	static LLPanelPickInfo* create(); - -	virtual ~LLPanelPickInfo(); - -	/** -	 * Initializes panel properties -	 * -	 * By default Pick will be created for current Agent location. -	 * Use setPickData to change Pick properties. -	 */ -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ BOOL postBuild(); - -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	/** -	 * Sends remote parcel info request to resolve parcel name from its ID. -	 */ -	void sendParcelInfoRequest(); - -	/** -	 * Sets "Back" button click callback -	 */ -	virtual void setExitCallback(const commit_callback_t& cb); - -	/** -	 * Sets "Edit" button click callback -	 */ -	virtual void setEditPickCallback(const commit_callback_t& cb); - -	//This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing -	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); -	/*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } -	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {}; - -protected: - -	LLPanelPickInfo(); -	 -	/** -	 * Resets Pick information -	 */ -	virtual void resetData(); - -	/** -	 * Resets UI controls (visibility, values) -	 */ -	virtual void resetControls(); - -	/**  -	* "Location text" is actually the owner name, the original -	* name that owner gave the parcel, and the location. -	*/ -	static std::string createLocationText( -		const std::string& owner_name,  -		const std::string& original_name, -		const std::string& sim_name,  -		const LLVector3d& pos_global); - -	virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } -	virtual LLUUID& getAvatarId() { return mAvatarId; } - -	/** -	 * Sets snapshot id. -	 * -	 * Will mark snapshot control as valid if id is not null. -	 * Will mark snapshot control as invalid if id is null. If null id is a valid value, -	 * you have to manually mark snapshot is valid. -	 */ -	virtual void setSnapshotId(const LLUUID& id); -	 -	virtual void setPickId(const LLUUID& id) { mPickId = id; } -	virtual LLUUID& getPickId() { return mPickId; } -	 -	virtual void setPickName(const std::string& name); -	 -	virtual void setPickDesc(const std::string& desc); -	 -	virtual void setPickLocation(const std::string& location); -	 -	virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } -	virtual LLVector3d& getPosGlobal() { return mPosGlobal; } - -	/** -	 * Callback for "Map" button, opens Map -	 */ -	void onClickMap(); - -	/** -	 * Callback for "Teleport" button, teleports user to Pick location. -	 */ -	void onClickTeleport(); - -	void onClickBack(); - -protected: - -	S32						mScrollingPanelMinHeight; -	S32						mScrollingPanelWidth; -	LLScrollContainer*		mScrollContainer; -	LLPanel*				mScrollingPanel; -	LLTextureCtrl*			mSnapshotCtrl; - -	LLUUID mAvatarId; -	LLVector3d mPosGlobal; -	LLUUID mParcelId; -	LLUUID mPickId; -	LLUUID mRequestedId; -}; - -/** - * Panel for creating/editing Pick. - */ -class LLPanelPickEdit : public LLPanelPickInfo -{ -	LOG_CLASS(LLPanelPickEdit); -public: - -	/** -	 * Creates new panel -	 */ -	static LLPanelPickEdit* create(); - -	/*virtual*/ ~LLPanelPickEdit(); - -	/*virtual*/ void onOpen(const LLSD& key); - -	virtual void setPickData(const LLPickData* pick_data); - -	/*virtual*/ BOOL postBuild(); - -	/** -	 * Sets "Save" button click callback -	 */ -	virtual void setSaveCallback(const commit_callback_t& cb); - -	/** -	 * Sets "Cancel" button click callback -	 */ -	virtual void setCancelCallback(const commit_callback_t& cb); - -	/** -	 * Resets panel and all cantrols to unedited state -	 */ -	/*virtual*/ void resetDirty(); - -	/** -	 * Returns true if any of Pick properties was changed by user. -	 */ -	/*virtual*/ BOOL isDirty() const; - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -protected: - -	LLPanelPickEdit(); - -	/** -	 * Sends Pick properties to server. -	 */ -	void sendUpdate(); - -	/** -	 * Called when snapshot image changes. -	 */ -	void onSnapshotChanged(); -	 -	/** -	 * Callback for Pick snapshot, name and description changed event. -	 */ -	void onPickChanged(LLUICtrl* ctrl); - -	/*virtual*/ void resetData(); - -	/** -	 * Enables/disables "Save" button -	 */ -	void enableSaveButton(bool enable); - -	/** -	 * Callback for "Set Location" button click -	 */ -	void onClickSetLocation(); - -	/** -	 * Callback for "Save" button click -	 */ -	void onClickSave(); - -	std::string getLocationNotice(); - -protected: - -	bool mLocationChanged; -	bool mNeedData; -	bool mNewPick; - -private: - -	void initTexturePickerMouseEvents(); -        void onTexturePickerMouseEnter(LLUICtrl* ctrl); -	void onTexturePickerMouseLeave(LLUICtrl* ctrl); - -private: - -	LLIconCtrl* text_icon; -}; - -#endif // LL_LLPANELPICK_H diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp deleted file mode 100644 index 8294977f99..0000000000 --- a/indra/newview/llpanelpicks.cpp +++ /dev/null @@ -1,1484 +0,0 @@ -/**  - * @file llpanelpicks.cpp - * @brief LLPanelPicks and related class implementations - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelpicks.h" - -#include "llagent.h" -#include "llagentpicksinfo.h" -#include "llcommandhandler.h" -#include "lldispatcher.h" -#include "llflatlistview.h" -#include "llfloaterreg.h" -#include "llfloatersidepanelcontainer.h" -#include "llfloaterworldmap.h" -#include "llnotificationsutil.h" -#include "llstartup.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" -#include "lltrans.h" -#include "llviewergenericmessage.h"	// send_generic_message -#include "llmenugl.h" -#include "llviewermenu.h" -#include "llregistry.h" - -#include "llaccordionctrl.h" -#include "llaccordionctrltab.h" -#include "llavatarpropertiesprocessor.h" -#include "llfloatersidepanelcontainer.h" -#include "llpanelavatar.h" -#include "llpanelprofile.h" -#include "llpanelpick.h" -#include "llpanelclassified.h" - -static const std::string XML_BTN_NEW = "new_btn"; -static const std::string XML_BTN_DELETE = "trash_btn"; -static const std::string XML_BTN_INFO = "info_btn"; -static const std::string XML_BTN_TELEPORT = "teleport_btn"; -static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn"; - -static const std::string PICK_ID("pick_id"); -static const std::string PICK_CREATOR_ID("pick_creator_id"); -static const std::string PICK_NAME("pick_name"); - -static const std::string CLASSIFIED_ID("classified_id"); -static const std::string CLASSIFIED_NAME("classified_name"); - - -static LLPanelInjector<LLPanelPicks> t_panel_picks("panel_picks"); - - -class LLPickHandler : public LLCommandHandler, -					  public LLAvatarPropertiesObserver -{ -public: - -	std::set<LLUUID> mPickIds; -	 -	// requires trusted browser to trigger -	LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } - -	bool handle(const LLSD& params, const LLSD& query_map, -		LLMediaCtrl* web) -	{ -		if (LLStartUp::getStartupState() < STATE_STARTED) -		{ -			return true; -		} - -		if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnablePicks")) -		{ -			LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); -			return true; -		} - -		// handle app/classified/create urls first -		if (params.size() == 1 && params[0].asString() == "create") -		{ -			createPick(); -			return true; -		} - -		// then handle the general app/pick/{UUID}/{CMD} urls -		if (params.size() < 2) -		{ -			return false; -		} - -		// get the ID for the pick_id -		LLUUID pick_id; -		if (!pick_id.set(params[0], FALSE)) -		{ -			return false; -		} - -		// edit the pick in the side tray. -		// need to ask the server for more info first though... -		const std::string verb = params[1].asString(); -		if (verb == "edit") -		{		 -			mPickIds.insert(pick_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(gAgent.getID(),pick_id); -			return true; -		} -		else -		{ -			LL_WARNS() << "unknown verb " << verb << LL_ENDL; -			return false; -		} -	} - -	void createPick() -	{ -		// open the new pick panel on the Picks floater -		LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - -		LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); -		if (picks) -		{ -			picks->createNewPick(); -		} -	} - -	void editPick(LLPickData* pick_info) -	{ -		LLSD params; -		params["open_tab_name"] = "panel_picks"; -		params["show_tab_panel"] = "edit_pick"; -		params["pick_id"] = pick_info->pick_id; -		params["avatar_id"] = pick_info->creator_id; -		params["snapshot_id"] = pick_info->snapshot_id; -		params["pick_name"] = pick_info->name; -		params["pick_desc"] = pick_info->desc; -		LLFloaterSidePanelContainer::showPanel("picks", params); -	} -	 -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) -	{ -		if (APT_PICK_INFO != type) -		{ -			return; -		} - -		// is this the pick that we asked for? -		LLPickData* pick_info = static_cast<LLPickData*>(data); -		if (!pick_info || mPickIds.find(pick_info->pick_id) == mPickIds.end()) -		{ -			return; -		} - -		// open the edit side tray for this pick -		if (pick_info->creator_id == gAgent.getID()) -		{ -			editPick(pick_info); -		} -		else -		{ -			LL_WARNS() << "Can't edit a pick you did not create" << LL_ENDL; -		} - -		// remove our observer now that we're done -		mPickIds.erase(pick_info->pick_id); -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); -	} -}; - -LLPickHandler gPickHandler; - -class LLClassifiedHandler : -	public LLCommandHandler, -	public LLAvatarPropertiesObserver -{ -public: -	// throttle calls from untrusted browsers -	LLClassifiedHandler() :	LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} - -	std::set<LLUUID> mClassifiedIds; - -	std::string mRequestVerb; -	 -	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) -	{ -		if (LLStartUp::getStartupState() < STATE_STARTED) -		{ -			return true; -		} - -		if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds")) -		{ -			LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); -			return true; -		} - -		// handle app/classified/create urls first -		if (params.size() == 1 && params[0].asString() == "create") -		{ -			createClassified(); -			return true; -		} - -		// then handle the general app/classified/{UUID}/{CMD} urls -		if (params.size() < 2) -		{ -			return false; -		} - -		// get the ID for the classified -		LLUUID classified_id; -		if (!classified_id.set(params[0], FALSE)) -		{ -			return false; -		} - -		// show the classified in the side tray. -		// need to ask the server for more info first though... -		const std::string verb = params[1].asString(); -		if (verb == "about") -		{ -			mRequestVerb = verb; -			mClassifiedIds.insert(classified_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); -			return true; -		} -		else if (verb == "edit") -		{ -			mRequestVerb = verb; -			mClassifiedIds.insert(classified_id); -			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); -			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); -			return true; -		} - -		return false; -	} - -	void createClassified() -	{ -		// open the new classified panel on the Picks floater -		LLFloater* picks_floater = LLFloaterReg::showInstance("picks"); - -		LLPanelPicks* picks = picks_floater->findChild<LLPanelPicks>("panel_picks"); -		if (picks) -		{ -			picks->createNewClassified(); -		} -	} - -	void openClassified(LLAvatarClassifiedInfo* c_info) -	{ -		if (mRequestVerb == "about") -		{ -			// open the classified info panel on the Me > Picks sidetray -			LLSD params; -			params["id"] = c_info->creator_id; -			params["open_tab_name"] = "panel_picks"; -			params["show_tab_panel"] = "classified_details"; -			params["classified_id"] = c_info->classified_id; -			params["classified_creator_id"] = c_info->creator_id; -			params["classified_snapshot_id"] = c_info->snapshot_id; -			params["classified_name"] = c_info->name; -			params["classified_desc"] = c_info->description; -			params["from_search"] = true; -			LLFloaterSidePanelContainer::showPanel("picks", params); -		} -		else if (mRequestVerb == "edit") -		{ -			if (c_info->creator_id == gAgent.getID()) -			{ -				LL_WARNS() << "edit in progress" << LL_ENDL; -				// open the new classified panel on the Me > Picks sidetray -				LLSD params; -				params["id"] = gAgent.getID(); -				params["open_tab_name"] = "panel_picks"; -				params["show_tab_panel"] = "edit_classified"; -				params["classified_id"] = c_info->classified_id; -				LLFloaterSidePanelContainer::showPanel("my_profile", params); -			} -			else -			{ -				LL_WARNS() << "Can't edit a classified you did not create" << LL_ENDL; -			} -		} -	} - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type) -	{ -		if (APT_CLASSIFIED_INFO != type) -		{ -			return; -		} - -		// is this the classified that we asked for? -		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -		if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) -		{ -			return; -		} - -		// open the detail side tray for this classified -		openClassified(c_info); - -		// remove our observer now that we're done -		mClassifiedIds.erase(c_info->classified_id); -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); -	} - -}; -LLClassifiedHandler gClassifiedHandler; - -////////////////////////////////////////////////////////////////////////// - - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPanelPicks::LLPanelPicks() -:	LLPanelProfileTab(), -	mPopupMenu(NULL), -	mProfilePanel(NULL), -	mPickPanel(NULL), -	mPicksList(NULL), -	mClassifiedsList(NULL), -	mPanelPickInfo(NULL), -	mPanelPickEdit(NULL), -	mPlusMenu(NULL), -	mPicksAccTab(NULL), -	mClassifiedsAccTab(NULL), -	mPanelClassifiedInfo(NULL), -	mNoClassifieds(false), -	mNoPicks(false) -{ -} - -LLPanelPicks::~LLPanelPicks() -{ -	if(getAvatarId().notNull()) -	{ -		LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); -	} -} - -void* LLPanelPicks::create(void* data /* = NULL */) -{ -	return new LLPanelPicks(); -} - -void LLPanelPicks::updateData() -{ -	// Send Picks request only when we need to, not on every onOpen(during tab switch). -	if(isDirty()) -	{ -		mNoPicks = false; -		mNoClassifieds = false; - -		mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); -		mNoItemsLabel->setVisible(TRUE); - -		mPicksList->clear(); -		LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); - -		mClassifiedsList->clear(); -		LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); -	} -} - -void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_PICKS == type) -	{ -		LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); -		if(avatar_picks && getAvatarId() == avatar_picks->target_id) -		{ -			LLAvatarName av_name; -			LLAvatarNameCache::get(getAvatarId(), &av_name); -			getChild<LLUICtrl>("pick_title")->setTextArg("[NAME]", av_name.getUserName()); -			 -			// Save selection, to be able to edit same item after saving changes. See EXT-3023. -			LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID]; - -			mPicksList->clear(); - -			LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); -			for(; avatar_picks->picks_list.end() != it; ++it) -			{ -				LLUUID pick_id = it->first; -				std::string pick_name = it->second; - -				LLPickItem* picture = LLPickItem::create(); -				picture->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); -				picture->setPickName(pick_name); -				picture->setPickId(pick_id); -				picture->setCreatorId(getAvatarId()); - -				LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture); -				picture->update(); - -				LLSD pick_value = LLSD(); -				pick_value.insert(PICK_ID, pick_id); -				pick_value.insert(PICK_NAME, pick_name); -				pick_value.insert(PICK_CREATOR_ID, getAvatarId()); - -				mPicksList->addItem(picture, pick_value); - -				// Restore selection by item id.  -				if ( pick_id == selected_id ) -					mPicksList->selectItemByValue(pick_value); - -				picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1)); -				picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -				picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -			} - -			showAccordion("tab_picks", mPicksList->size()); - -			resetDirty(); -			updateButtons(); -		} -		 -		mNoPicks = !mPicksList->size(); -	} -	else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) -	{ -		LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); -		if(c_info && getAvatarId() == c_info->target_id) -		{ -			// do not clear classified list in case we will receive two or more data packets. -			// list has been cleared in updateData(). (fix for EXT-6436) - -			LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); -			for(; c_info->classifieds_list.end() != it; ++it) -			{ -				LLAvatarClassifieds::classified_data c_data = *it; - -				LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), c_data.classified_id); -				c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); -				c_item->setClassifiedName(c_data.name); - -				LLSD pick_value = LLSD(); -				pick_value.insert(CLASSIFIED_ID, c_data.classified_id); -				pick_value.insert(CLASSIFIED_NAME, c_data.name); - -				if (!findClassifiedById(c_data.classified_id)) -				{ -					mClassifiedsList->addItem(c_item, pick_value); -				} - -				c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); -				c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -				c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -			} - -			showAccordion("tab_classifieds", mClassifiedsList->size()); - -			resetDirty(); -			updateButtons(); -		} -		 -		mNoClassifieds = !mClassifiedsList->size(); -	} - -    updateNoItemsLabel(); -} - -LLPickItem* LLPanelPicks::getSelectedPickItem() -{ -	LLPanel* selected_item = mPicksList->getSelectedItem(); -	if (!selected_item) return NULL; - -	return dynamic_cast<LLPickItem*>(selected_item); -} - -LLClassifiedItem* LLPanelPicks::getSelectedClassifiedItem() -{ -	LLPanel* selected_item = mClassifiedsList->getSelectedItem(); -	if (!selected_item)  -	{ -		return NULL; -	} -	return dynamic_cast<LLClassifiedItem*>(selected_item); -} - -BOOL LLPanelPicks::postBuild() -{ -	mPicksList = getChild<LLFlatListView>("picks_list"); -	mClassifiedsList = getChild<LLFlatListView>("classifieds_list"); - -	mPicksList->setCommitOnSelectionChange(true); -	mClassifiedsList->setCommitOnSelectionChange(true); - -	mPicksList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mPicksList)); -	mClassifiedsList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mClassifiedsList)); - -	mPicksList->setNoItemsCommentText(getString("no_picks")); -	mClassifiedsList->setNoItemsCommentText(getString("no_classifieds")); - -	mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); - -	childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this)); -	childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this)); -	childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this)); -	childSetAction(XML_BTN_SHOW_ON_MAP, boost::bind(&LLPanelPicks::onClickMap, this)); -	childSetAction(XML_BTN_INFO, boost::bind(&LLPanelPicks::onClickInfo, this)); - -	mPicksAccTab = getChild<LLAccordionCtrlTab>("tab_picks"); -	mPicksAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mPicksAccTab)); -	mPicksAccTab->setDisplayChildren(true); - -	mClassifiedsAccTab = getChild<LLAccordionCtrlTab>("tab_classifieds"); -	mClassifiedsAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mClassifiedsAccTab)); -	mClassifiedsAccTab->setDisplayChildren(false); -	 -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; -	registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this)); -	registar.add("Pick.Edit", boost::bind(&LLPanelPicks::onClickMenuEdit, this));  -	registar.add("Pick.Teleport", boost::bind(&LLPanelPicks::onClickTeleport, this)); -	registar.add("Pick.Map", boost::bind(&LLPanelPicks::onClickMap, this)); -	registar.add("Pick.Delete", boost::bind(&LLPanelPicks::onClickDelete, this)); -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registar; -	enable_registar.add("Pick.Enable", boost::bind(&LLPanelPicks::onEnableMenuItem, this, _2)); - -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar; -	plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2)); -	mEnableCallbackRegistrar.add("Picks.Plus.Enable", boost::bind(&LLPanelPicks::isActionEnabled, this, _2)); -	mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	 -	return TRUE; -} - -void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param) -{ -	std::string value = param.asString(); - -	if("new_pick" == value) -	{ -		createNewPick(); -	} -	else if("new_classified" == value) -	{ -		createNewClassified(); -	} -} - -bool LLPanelPicks::isActionEnabled(const LLSD& userdata) const -{ -	std::string command_name = userdata.asString(); - -	if (command_name == "new_pick" && LLAgentPicksInfo::getInstance()->isPickLimitReached()) -	{ -		return false; -	} - -	return true; -} - -bool LLPanelPicks::isClassifiedPublished(LLClassifiedItem* c_item) -{ -	if(c_item) -	{ -		LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; -		if(panel) -		{ -			 return !panel->isNewWithErrors(); -		} - -		// we've got this classified from server - it's published -		return true; -	} -	return false; -} - -void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab) -{ -	if(!mPicksAccTab->getDisplayChildren()) -	{ -		mPicksList->resetSelection(true); -	} -	if(!mClassifiedsAccTab->getDisplayChildren()) -	{ -		mClassifiedsList->resetSelection(true); -	} - -	updateButtons(); -} - -void LLPanelPicks::onOpen(const LLSD& key) -{ -	const LLUUID id(key.asUUID()); -	BOOL self = (gAgent.getID() == id); - -	// only agent can edit her picks  -	getChildView("edit_panel")->setEnabled(self); -	getChildView("edit_panel")->setVisible( self); - -	// Disable buttons when viewing profile for first time -	if(getAvatarId() != id) -	{ -		getChildView(XML_BTN_INFO)->setEnabled(FALSE); -		getChildView(XML_BTN_TELEPORT)->setEnabled(FALSE); -		getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(FALSE); -	} - -	// and see a special title - set as invisible by default in xml file -	if (self) -	{ -		getChildView("pick_title")->setVisible( !self); -		getChildView("pick_title_agent")->setVisible( self); - -		mPopupMenu->setItemVisible("pick_delete", TRUE); -		mPopupMenu->setItemVisible("pick_edit", TRUE); -		mPopupMenu->setItemVisible("pick_separator", TRUE); -	} - -	if(getAvatarId() != id) -	{ -		showAccordion("tab_picks", false); -		showAccordion("tab_classifieds", false); - -		mPicksList->goToTop(); -		// Set dummy value to make panel dirty and make it reload picks -		setValue(LLSD()); -	} - -	LLPanelProfileTab::onOpen(key); -} - -void LLPanelPicks::onClosePanel() -{ -	if (mPanelClassifiedInfo) -	{ -		onPanelClassifiedClose(mPanelClassifiedInfo); -	} -	if (mPanelPickInfo) -	{ -		onPanelPickClose(mPanelPickInfo); -	} -} - -void LLPanelPicks::onListCommit(const LLFlatListView* f_list) -{ -	// Make sure only one of the lists has selection. -	if(f_list == mPicksList) -	{ -		mClassifiedsList->resetSelection(true); -	} -	else if(f_list == mClassifiedsList) -	{ -		mPicksList->resetSelection(true); -	} -	else -	{ -		LL_WARNS() << "Unknown list" << LL_ENDL; -	} - -	updateButtons(); -} - -//static -void LLPanelPicks::onClickDelete() -{ -	LLSD value = mPicksList->getSelectedValue(); -	if (value.isDefined()) -	{ -		LLSD args;  -		args["PICK"] = value[PICK_NAME];  -		LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeletePick, this, _1, _2));  -		return; -	} - -	value = mClassifiedsList->getSelectedValue(); -	if(value.isDefined()) -	{ -		LLSD args;  -		args["NAME"] = value[CLASSIFIED_NAME];  -		LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeleteClassified, this, _1, _2));  -		return; -	} -} - -bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& response)  -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	LLSD pick_value = mPicksList->getSelectedValue(); - -	if (0 == option) -	{ -		LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]); -		mPicksList->removeItemByValue(pick_value); -         -        mNoPicks = !mPicksList->size(); -        if (mNoPicks) -        { -            showAccordion("tab_picks", false); -        } -        updateNoItemsLabel(); -	} -	updateButtons(); -	return false; -} - -bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response)  -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	LLSD value = mClassifiedsList->getSelectedValue(); - -	if (0 == option) -	{ -		LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]); -		mClassifiedsList->removeItemByValue(value); - -        mNoClassifieds = !mClassifiedsList->size(); -        if (mNoClassifieds) -        { -            showAccordion("tab_classifieds", false); -        } -        updateNoItemsLabel(); -	} -	updateButtons(); -	return false; -} - -bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response ) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	if (0 == option) -	{ -		onClickTeleport(); -	} -	return false; -} - -//static -void LLPanelPicks::onClickTeleport() -{ -	LLPickItem* pick_item = getSelectedPickItem(); -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); - -	LLVector3d pos; -	if(pick_item) -		pos = pick_item->getPosGlobal(); -	else if(c_item) -	{ -		pos = c_item->getPosGlobal(); -		LLPanelClassifiedInfo::sendClickMessage("teleport", false, -			c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); -	} - -	if (!pos.isExactlyZero()) -	{ -		gAgent.teleportViaLocation(pos); -		LLFloaterWorldMap::getInstance()->trackLocation(pos); -	} -} - -//static -void LLPanelPicks::onClickMap() -{ -	LLPickItem* pick_item = getSelectedPickItem(); -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); - -	LLVector3d pos; -	if (pick_item) -		pos = pick_item->getPosGlobal(); -	else if(c_item) -	{ -		LLPanelClassifiedInfo::sendClickMessage("map", false, -			c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null); -		pos = c_item->getPosGlobal(); -	} - -	LLFloaterWorldMap::getInstance()->trackLocation(pos); -	LLFloaterReg::showInstance("world_map", "center"); -} - - -void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) -{ -	updateButtons(); - -	if (mPopupMenu) -	{ -		mPopupMenu->buildDrawLabels(); -		mPopupMenu->updateParent(LLMenuGL::sMenuContainer); -		((LLContextMenu*)mPopupMenu)->show(x, y); -		LLMenuGL::showPopup(item, mPopupMenu, x, y); -	} -} - -void LLPanelPicks::onDoubleClickPickItem(LLUICtrl* item) -{ -	LLSD pick_value = mPicksList->getSelectedValue(); -	if (pick_value.isUndefined()) return; -	 -	LLSD args;  -	args["PICK"] = pick_value[PICK_NAME];  -	LLNotificationsUtil::add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));  -} - -void LLPanelPicks::onDoubleClickClassifiedItem(LLUICtrl* item) -{ -	LLSD value = mClassifiedsList->getSelectedValue(); -	if (value.isUndefined()) return; - -	LLSD args;  -	args["CLASSIFIED"] = value[CLASSIFIED_NAME];  -	LLNotificationsUtil::add("TeleportToClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));  -} - -void LLPanelPicks::updateButtons() -{ -	bool has_selected = mPicksList->numSelected() > 0 || mClassifiedsList->numSelected() > 0; - -	if (getAvatarId() == gAgentID) -	{ -		getChildView(XML_BTN_DELETE)->setEnabled(has_selected); -	} - -	getChildView(XML_BTN_INFO)->setEnabled(has_selected); -	getChildView(XML_BTN_TELEPORT)->setEnabled(has_selected); -	getChildView(XML_BTN_SHOW_ON_MAP)->setEnabled(has_selected); - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	if(c_item) -	{ -		getChildView(XML_BTN_INFO)->setEnabled(isClassifiedPublished(c_item)); -	} -} - -void LLPanelPicks::updateNoItemsLabel() -{ -    bool no_data = mNoPicks && mNoClassifieds; -    mNoItemsLabel->setVisible(no_data); -    if (no_data) -    { -        if (getAvatarId() == gAgentID) -        { -            mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText")); -        } -        else -        { -            mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText")); -        } -    } -} - -void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel) -{ -	mProfilePanel = profile_panel; -} - - -void LLPanelPicks::buildPickPanel() -{ -// 	if (mPickPanel == NULL) -// 	{ -// 		mPickPanel = new LLPanelPick(); -// 		mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, NULL)); -// 	} -} - -void LLPanelPicks::onClickPlusBtn() -{ -	LLRect rect(getChildView(XML_BTN_NEW)->getRect()); - -	mPlusMenu->updateParent(LLMenuGL::sMenuContainer); -	mPlusMenu->setButtonRect(rect, this); -	LLMenuGL::showPopup(this, mPlusMenu, rect.mLeft, rect.mTop); -} - -void LLPanelPicks::createNewPick() -{ -	createPickEditPanel(); - -	getProfilePanel()->openPanel(mPanelPickEdit, LLSD()); -} - -void LLPanelPicks::createNewClassified() -{ -	LLPanelClassifiedEdit* panel = NULL; -	createClassifiedEditPanel(&panel); - -	getProfilePanel()->openPanel(panel, LLSD()); -} - -void LLPanelPicks::onClickInfo() -{ -	if(mPicksList->numSelected() > 0) -	{ -		openPickInfo(); -	} -	else if(mClassifiedsList->numSelected() > 0) -	{ -		openClassifiedInfo(); -	} -} - -void LLPanelPicks::openPickInfo() -{ -	LLSD selected_value = mPicksList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLPickItem* pick = (LLPickItem*)mPicksList->getSelectedItem(); - -	createPickInfoPanel(); - -	LLSD params; -	params["pick_id"] = pick->getPickId(); -	params["avatar_id"] = pick->getCreatorId(); -	params["snapshot_id"] = pick->getSnapshotId(); -	params["pick_name"] = pick->getPickName(); -	params["pick_desc"] = pick->getPickDesc(); - -	getProfilePanel()->openPanel(mPanelPickInfo, params); -} - -void LLPanelPicks::openClassifiedInfo() -{ -	LLSD selected_value = mClassifiedsList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLClassifiedItem* c_item = getSelectedClassifiedItem(); -	LLSD params; -	params["classified_id"] = c_item->getClassifiedId(); -	params["classified_creator_id"] = c_item->getAvatarId(); -	params["classified_snapshot_id"] = c_item->getSnapshotId(); -	params["classified_name"] = c_item->getClassifiedName(); -	params["classified_desc"] = c_item->getDescription(); -	params["from_search"] = false; - -	openClassifiedInfo(params); -} - -void LLPanelPicks::openClassifiedInfo(const LLSD ¶ms) -{ -	createClassifiedInfoPanel(); -	getProfilePanel()->openPanel(mPanelClassifiedInfo, params); -} - -void LLPanelPicks::openClassifiedEdit(const LLSD& params) -{ -	LLUUID classified_id = params["classified_id"].asUUID();; -	LL_INFOS() << "opening classified " << classified_id << " for edit" << LL_ENDL; -	editClassified(classified_id); -} - -void LLPanelPicks::showAccordion(const std::string& name, bool show) -{ -	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); -	tab->setVisible(show); -	LLAccordionCtrl* acc = getChild<LLAccordionCtrl>("accordion"); -	acc->arrange(); -} - -void LLPanelPicks::onPanelPickClose(LLPanel* panel) -{ -	getProfilePanel()->closePanel(panel); -} - -void LLPanelPicks::onPanelPickSave(LLPanel* panel) -{ -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel) -{ -	if(!panel->canClose()) -	{ -		return; -	} - -	if(panel->isNew()) -	{ -		mEditClassifiedPanels[panel->getClassifiedId()] = panel; - -		LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); -		c_item->fillIn(panel); - -		LLSD c_value; -		c_value.insert(CLASSIFIED_ID, c_item->getClassifiedId()); -		c_value.insert(CLASSIFIED_NAME, c_item->getClassifiedName()); -		mClassifiedsList->addItem(c_item, c_value, ADD_TOP); - -		c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); -		c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); -		c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); -		c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); - -		// order does matter, showAccordion will invoke arrange for accordions. -		mClassifiedsAccTab->changeOpenClose(false); -		showAccordion("tab_classifieds", true); -	} -	else if(panel->isNewWithErrors()) -	{ -		LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -		llassert(c_item); -		if (c_item) -		{ -			c_item->fillIn(panel); -		} -	} -	else  -	{ -		onPanelClassifiedClose(panel); -		return; -	} - -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::onPanelClassifiedClose(LLPanelClassifiedInfo* panel) -{ -	if(panel->getInfoLoaded() && !panel->isDirty()) -	{ -		std::vector<LLSD> values; -		mClassifiedsList->getValues(values); -		for(size_t n = 0; n < values.size(); ++n) -		{ -			LLUUID c_id = values[n][CLASSIFIED_ID].asUUID(); -			if(panel->getClassifiedId() == c_id) -			{ -				LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>( -					mClassifiedsList->getItemByValue(values[n])); -				llassert(c_item); -				if (c_item) -				{ -					c_item->setClassifiedName(panel->getClassifiedName()); -					c_item->setDescription(panel->getDescription()); -					c_item->setSnapshotId(panel->getSnapshotId()); -				} -			} -		} -	} - -	onPanelPickClose(panel); -	updateButtons(); -} - -void LLPanelPicks::createPickInfoPanel() -{ -	if(!mPanelPickInfo) -	{ -		mPanelPickInfo = LLPanelPickInfo::create(); -		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); -		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); -		mPanelPickInfo->setVisible(FALSE); -	} -} - -void LLPanelPicks::createClassifiedInfoPanel() -{ -	mPanelClassifiedInfo = LLPanelClassifiedInfo::create(); -	mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo)); -	mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this)); -	mPanelClassifiedInfo->setVisible(FALSE); -} - -void LLPanelPicks::createClassifiedEditPanel(LLPanelClassifiedEdit** panel) -{ -	if(panel) -	{ -		LLPanelClassifiedEdit* new_panel = LLPanelClassifiedEdit::create(); -		new_panel->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); -		new_panel->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, new_panel)); -		new_panel->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel)); -		new_panel->setVisible(FALSE); -		*panel = new_panel; -	} -} - -void LLPanelPicks::createPickEditPanel() -{ -	mPanelPickEdit = LLPanelPickEdit::create(); -	mPanelPickEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); -	mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickSave, this, mPanelPickEdit)); -	mPanelPickEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit)); -	mPanelPickEdit->setVisible(FALSE); -} - -// void LLPanelPicks::openPickEditPanel(LLPickItem* pick) -// { -// 	if(!pick) -// 	{ -// 		return; -// 	} -// } - -// void LLPanelPicks::openPickInfoPanel(LLPickItem* pick) -// { -// 	if(!mPanelPickInfo) -// 	{ -// 		mPanelPickInfo = LLPanelPickInfo::create(); -// 		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo)); -// 		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this)); -// 		mPanelPickInfo->setVisible(FALSE); -// 	} -//  -// 	LLSD params; -// 	params["pick_id"] = pick->getPickId(); -// 	params["avatar_id"] = pick->getCreatorId(); -// 	params["snapshot_id"] = pick->getSnapshotId(); -// 	params["pick_name"] = pick->getPickName(); -// 	params["pick_desc"] = pick->getPickDesc(); -//  -// 	getProfilePanel()->openPanel(mPanelPickInfo, params); -// } - -void LLPanelPicks::openPickEdit(const LLSD& params) -{ -	createPickEditPanel(); -	getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelPickEdit() -{ -	LLSD selected_value = mPicksList->getSelectedValue(); -	if (selected_value.isUndefined()) return; - -	LLPickItem* pick = dynamic_cast<LLPickItem*>(mPicksList->getSelectedItem()); -	 -	createPickEditPanel(); - -	LLSD params; -	params["pick_id"] = pick->getPickId(); -	params["avatar_id"] = pick->getCreatorId(); -	params["snapshot_id"] = pick->getSnapshotId(); -	params["pick_name"] = pick->getPickName(); -	params["pick_desc"] = pick->getPickDesc(); - -	getProfilePanel()->openPanel(mPanelPickEdit, params); -} - -void LLPanelPicks::onPanelClassifiedEdit() -{ -	LLSD selected_value = mClassifiedsList->getSelectedValue(); -	if (selected_value.isUndefined())  -	{ -		return; -	} - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	llassert(c_item); -	if (!c_item) -	{ -		return; -	} -	editClassified(c_item->getClassifiedId()); -} - -LLClassifiedItem *LLPanelPicks::findClassifiedById(const LLUUID& classified_id) -{ -	// HACK - find item by classified id.  Should be a better way. -	std::vector<LLPanel*> items; -	mClassifiedsList->getItems(items); -	LLClassifiedItem* c_item = NULL; -	for(std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) -	{ -		LLClassifiedItem *test_item = dynamic_cast<LLClassifiedItem*>(*it); -		if (test_item && test_item->getClassifiedId() == classified_id) -		{ -			c_item = test_item; -			break; -		} -	} -	return c_item; -} - -void LLPanelPicks::editClassified(const LLUUID&  classified_id) -{ -	LLClassifiedItem* c_item = findClassifiedById(classified_id); -	if (!c_item) -	{ -		LL_WARNS() << "item not found for classified_id " << classified_id << LL_ENDL; -		return; -	} - -	LLSD params; -	params["classified_id"] = c_item->getClassifiedId(); -	params["classified_creator_id"] = c_item->getAvatarId(); -	params["snapshot_id"] = c_item->getSnapshotId(); -	params["name"] = c_item->getClassifiedName(); -	params["desc"] = c_item->getDescription(); -	params["category"] = (S32)c_item->getCategory(); -	params["content_type"] = (S32)c_item->getContentType(); -	params["auto_renew"] = c_item->getAutoRenew(); -	params["price_for_listing"] = c_item->getPriceForListing(); -	params["location_text"] = c_item->getLocationText(); - -	LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()]; -	if(!panel) -	{ -		createClassifiedEditPanel(&panel); -		mEditClassifiedPanels[c_item->getClassifiedId()] = panel; -	} -	getProfilePanel()->openPanel(panel, params); -	panel->setPosGlobal(c_item->getPosGlobal()); -} - -void LLPanelPicks::onClickMenuEdit() -{ -	if(getSelectedPickItem()) -	{ -		onPanelPickEdit(); -	} -	else if(getSelectedClassifiedItem()) -	{ -		onPanelClassifiedEdit(); -	} -} - -bool LLPanelPicks::onEnableMenuItem(const LLSD& user_data) -{ -	std::string param = user_data.asString(); - -	LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); -	if(c_item && "info" == param) -	{ -		// dont show Info panel if classified was not created -		return isClassifiedPublished(c_item); -	} - -	return true; -} - -inline LLPanelProfile* LLPanelPicks::getProfilePanel() -{ -	llassert_always(NULL != mProfilePanel); -	return mProfilePanel; -} - -//----------------------------------------------------------------------------- -// LLPanelPicks -//----------------------------------------------------------------------------- -LLPickItem::LLPickItem() -: LLPanel() -, mPickID(LLUUID::null) -, mCreatorID(LLUUID::null) -, mParcelID(LLUUID::null) -, mSnapshotID(LLUUID::null) -, mNeedData(true) -{ -	buildFromFile("panel_pick_list_item.xml"); -} - -LLPickItem::~LLPickItem() -{ -	if (mCreatorID.notNull()) -	{ -		LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); -	} - -} - -LLPickItem* LLPickItem::create() -{ -	return new LLPickItem(); -} - -void LLPickItem::init(LLPickData* pick_data) -{ -	setPickDesc(pick_data->desc); -	setSnapshotId(pick_data->snapshot_id); -	mPosGlobal = pick_data->pos_global; -	mSimName = pick_data->sim_name; -	mPickDescription = pick_data->desc; -	mUserName = pick_data->user_name; -	mOriginalName = pick_data->original_name; - -	LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture"); -	picture->setImageAssetID(pick_data->snapshot_id); -} - -void LLPickItem::setPickName(const std::string& name) -{ -	mPickName = name; -	getChild<LLUICtrl>("picture_name")->setValue(name); - -} - -const std::string& LLPickItem::getPickName() -{ -	return mPickName; -} - -const LLUUID& LLPickItem::getCreatorId() -{ -	return mCreatorID; -} - -const LLUUID& LLPickItem::getSnapshotId() -{ -	return mSnapshotID; -} - -void LLPickItem::setPickDesc(const std::string& descr) -{ -	getChild<LLUICtrl>("picture_descr")->setValue(descr); -} - -void LLPickItem::setPickId(const LLUUID& id) -{ -	mPickID = id; -} - -const LLUUID& LLPickItem::getPickId() -{ -	return mPickID; -} - -const LLVector3d& LLPickItem::getPosGlobal() -{ -	return mPosGlobal; -} - -const std::string LLPickItem::getDescription() -{ -	return getChild<LLUICtrl>("picture_descr")->getValue().asString(); -} - -void LLPickItem::update() -{ -	setNeedData(true); -	LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID); -} - -void LLPickItem::processProperties(void *data, EAvatarProcessorType type) -{ -	if (APT_PICK_INFO != type)  -	{ -		return; -	} - -	LLPickData* pick_data = static_cast<LLPickData *>(data); -	if (!pick_data || mPickID != pick_data->pick_id)  -	{ -		return; -	} - -	init(pick_data); -	setNeedData(false); -	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this); -} - -void set_child_visible(LLView* parent, const std::string& child_name, bool visible) -{ -	parent->getChildView(child_name)->setVisible(visible); -} - -BOOL LLPickItem::postBuild() -{ -	setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); -	setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); -	return TRUE; -} - -void LLPickItem::setValue(const LLSD& value) -{ -	if (!value.isMap()) return;; -	if (!value.has("selected")) return; -	getChildView("selected_icon")->setVisible( value["selected"]); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id) - : LLPanel() - , mAvatarId(avatar_id) - , mClassifiedId(classified_id) -{ -	buildFromFile("panel_classifieds_list_item.xml"); - -	LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); -	LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); -} - -LLClassifiedItem::~LLClassifiedItem() -{ -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type) -{ -	if(APT_CLASSIFIED_INFO != type) -	{ -		return; -	} - -	LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); -	if( !c_info || c_info->classified_id != getClassifiedId() ) -	{ -		return; -	} - -	setClassifiedName(c_info->name); -	setDescription(c_info->description); -	setSnapshotId(c_info->snapshot_id); -	setPosGlobal(c_info->pos_global); - -	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); -} - -BOOL LLClassifiedItem::postBuild() -{ -	setMouseEnterCallback(boost::bind(&set_child_visible, this, "hovered_icon", true)); -	setMouseLeaveCallback(boost::bind(&set_child_visible, this, "hovered_icon", false)); -	return TRUE; -} - -void LLClassifiedItem::setValue(const LLSD& value) -{ -	if (!value.isMap()) return;; -	if (!value.has("selected")) return; -	getChildView("selected_icon")->setVisible( value["selected"]); -} - -void LLClassifiedItem::fillIn(LLPanelClassifiedEdit* panel) -{ -	if(!panel) -	{ -		return; -	} - -	setClassifiedName(panel->getClassifiedName()); -	setDescription(panel->getDescription()); -	setSnapshotId(panel->getSnapshotId()); -	setCategory(panel->getCategory()); -	setContentType(panel->getContentType()); -	setAutoRenew(panel->getAutoRenew()); -	setPriceForListing(panel->getPriceForListing()); -	setPosGlobal(panel->getPosGlobal()); -	setLocationText(panel->getClassifiedLocation()); -} - -void LLClassifiedItem::setClassifiedName(const std::string& name) -{ -	getChild<LLUICtrl>("name")->setValue(name); -} - -void LLClassifiedItem::setDescription(const std::string& desc) -{ -	getChild<LLUICtrl>("description")->setValue(desc); -} - -void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id) -{ -	getChild<LLUICtrl>("picture")->setValue(snapshot_id); -} - -LLUUID LLClassifiedItem::getSnapshotId() -{ -	return getChild<LLUICtrl>("picture")->getValue(); -} - -//EOF diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h deleted file mode 100644 index fd7688b99d..0000000000 --- a/indra/newview/llpanelpicks.h +++ /dev/null @@ -1,315 +0,0 @@ -/**  - * @file llpanelpicks.h - * @brief LLPanelPicks and related class definitions - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPANELPICKS_H -#define LL_LLPANELPICKS_H - -#include "llpanel.h" -#include "v3dmath.h" -#include "lluuid.h" -#include "llavatarpropertiesprocessor.h" -#include "llpanelavatar.h" -#include "llregistry.h" - -class LLAccordionCtrlTab; -class LLPanelProfile; -class LLMessageSystem; -class LLVector3d; -class LLPanelProfileTab; -class LLAgent; -class LLMenuGL; -class LLPickItem; -class LLClassifiedItem; -class LLFlatListView; -class LLPanelPickInfo; -class LLPanelPickEdit; -class LLToggleableMenu; -class LLPanelClassifiedInfo; -class LLPanelClassifiedEdit; - -// *TODO -// Panel Picks has been consolidated with Classifieds (EXT-2095), give LLPanelPicks -// and corresponding files (cpp, h, xml) a new name. (new name is TBD at the moment) - -class LLPanelPicks  -	: public LLPanelProfileTab -{ -public: -	LLPanelPicks(); -	~LLPanelPicks(); - -	static void* create(void* data); - -	/*virtual*/ BOOL postBuild(void); - -	/*virtual*/ void onOpen(const LLSD& key); - -	/*virtual*/ void onClosePanel(); - -	void processProperties(void* data, EAvatarProcessorType type); - -	void updateData(); - -	// returns the selected pick item -	LLPickItem* getSelectedPickItem(); -	LLClassifiedItem* getSelectedClassifiedItem(); -	LLClassifiedItem* findClassifiedById(const LLUUID& classified_id); - -	//*NOTE top down approch when panel toggling is done only by  -	// parent panels failed to work (picks related code was in my profile panel) -	void setProfilePanel(LLPanelProfile* profile_panel); - -	void createNewPick(); -	void createNewClassified(); - -protected: -	/*virtual*/void updateButtons(); -	void updateNoItemsLabel(); - -private: -	void onClickDelete(); -	void onClickTeleport(); -	void onClickMap(); - -	void onPlusMenuItemClicked(const LLSD& param); -	bool isActionEnabled(const LLSD& userdata) const; - -	bool isClassifiedPublished(LLClassifiedItem* c_item); - -	void onListCommit(const LLFlatListView* f_list); -	void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); - -	//------------------------------------------------ -	// Callbacks which require panel toggling -	//------------------------------------------------ -	void onClickPlusBtn(); -	void onClickInfo(); -	void onPanelPickClose(LLPanel* panel); -	void onPanelPickSave(LLPanel* panel); -	void onPanelClassifiedSave(LLPanelClassifiedEdit* panel); -	void onPanelClassifiedClose(LLPanelClassifiedInfo* panel); -	void openPickEdit(const LLSD& params); -	void onPanelPickEdit(); -	void onPanelClassifiedEdit(); -	void editClassified(const LLUUID&  classified_id); -	void onClickMenuEdit(); - -	bool onEnableMenuItem(const LLSD& user_data); - -	void openPickInfo(); -	void openClassifiedInfo(); -	void openClassifiedInfo(const LLSD& params); -	void openClassifiedEdit(const LLSD& params); -	friend class LLPanelProfile; - -	void showAccordion(const std::string& name, bool show); - -	void buildPickPanel(); - -	bool callbackDeletePick(const LLSD& notification, const LLSD& response); -	bool callbackDeleteClassified(const LLSD& notification, const LLSD& response); -	bool callbackTeleport(const LLSD& notification, const LLSD& response); - - -	virtual void onDoubleClickPickItem(LLUICtrl* item); -	virtual void onDoubleClickClassifiedItem(LLUICtrl* item); -	virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); - -	LLPanelProfile* getProfilePanel(); - -	void createPickInfoPanel(); -	void createPickEditPanel(); -	void createClassifiedInfoPanel(); -	void createClassifiedEditPanel(LLPanelClassifiedEdit** panel); - -	LLMenuGL* mPopupMenu; -	LLPanelProfile* mProfilePanel; -	LLPanelPickInfo* mPickPanel; -	LLFlatListView* mPicksList; -	LLFlatListView* mClassifiedsList; -	LLPanelPickInfo* mPanelPickInfo; -	LLPanelClassifiedInfo* mPanelClassifiedInfo; -	LLPanelPickEdit* mPanelPickEdit; -	LLToggleableMenu* mPlusMenu; -	LLUICtrl* mNoItemsLabel; - -	// <classified_id, edit_panel> -	typedef std::map<LLUUID, LLPanelClassifiedEdit*> panel_classified_edit_map_t; - -	// This map is needed for newly created classifieds. The purpose of panel is to -	// sit in this map and listen to LLPanelClassifiedEdit::processProperties callback. -	panel_classified_edit_map_t mEditClassifiedPanels; - -	LLAccordionCtrlTab* mPicksAccTab; -	LLAccordionCtrlTab* mClassifiedsAccTab; - -	//true if picks list is empty after processing picks -	bool mNoPicks; -	//true if classifieds list is empty after processing classifieds -	bool mNoClassifieds; -}; - -class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - -	LLPickItem(); - -	static LLPickItem* create(); - -	void init(LLPickData* pick_data); - -	void setPickName(const std::string& name); - -	void setPickDesc(const std::string& descr); - -	void setPickId(const LLUUID& id); - -	void setCreatorId(const LLUUID& id) {mCreatorID = id;}; - -	void setSnapshotId(const LLUUID& id) {mSnapshotID = id;}; - -	void setNeedData(bool need){mNeedData = need;}; - -	const LLUUID& getPickId();  - -	const std::string& getPickName(); - -	const LLUUID& getCreatorId(); - -	const LLUUID& getSnapshotId(); - -	const LLVector3d& getPosGlobal(); - -	const std::string getDescription(); - -	const std::string& getSimName() { return mSimName; } - -	const std::string& getUserName() { return mUserName; } - -	const std::string& getOriginalName() { return mOriginalName; } - -	const std::string& getPickDesc() { return mPickDescription; } - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	void update(); - -	~LLPickItem(); - -	/*virtual*/ BOOL postBuild(); - -	/** setting on/off background icon to indicate selected state */ -	/*virtual*/ void setValue(const LLSD& value); - -protected: - -	LLUUID mPickID; -	LLUUID mCreatorID; -	LLUUID mParcelID; -	LLUUID mSnapshotID; -	LLVector3d mPosGlobal; -	bool mNeedData; - -	std::string mPickName; -	std::string mUserName; -	std::string mOriginalName; -	std::string mPickDescription; -	std::string mSimName; -}; - -class LLClassifiedItem : public LLPanel, public LLAvatarPropertiesObserver -{ -public: - -	LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id); -	 -	virtual ~LLClassifiedItem(); - -	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - -	/*virtual*/ BOOL postBuild(); - -	/*virtual*/ void setValue(const LLSD& value); - -	void fillIn(LLPanelClassifiedEdit* panel); - -	LLUUID getAvatarId() {return mAvatarId;} -	 -	void setAvatarId(const LLUUID& avatar_id) {mAvatarId = avatar_id;} - -	LLUUID getClassifiedId() {return mClassifiedId;} - -	void setClassifiedId(const LLUUID& classified_id) {mClassifiedId = classified_id;} - -	void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } - -	const LLVector3d getPosGlobal() { return mPosGlobal; } - -	void setLocationText(const std::string location) { mLocationText = location; } - -	std::string getLocationText() { return mLocationText; } - -	void setClassifiedName (const std::string& name); - -	std::string getClassifiedName() { return getChild<LLUICtrl>("name")->getValue().asString(); } - -	void setDescription(const std::string& desc); - -	std::string getDescription() { return getChild<LLUICtrl>("description")->getValue().asString(); } - -	void setSnapshotId(const LLUUID& snapshot_id); - -	LLUUID getSnapshotId(); - -	void setCategory(U32 cat) { mCategory = cat; } - -	U32 getCategory() { return mCategory; } - -	void setContentType(U32 ct) { mContentType = ct; } - -	U32 getContentType() { return mContentType; } - -	void setAutoRenew(U32 renew) { mAutoRenew = renew; } - -	bool getAutoRenew() { return mAutoRenew; } - -	void setPriceForListing(S32 price) { mPriceForListing = price; } - -	S32 getPriceForListing() { return mPriceForListing; } - -private: -	LLUUID mAvatarId; -	LLUUID mClassifiedId; -	LLVector3d mPosGlobal; -	std::string mLocationText; -	U32 mCategory; -	U32 mContentType; -	bool mAutoRenew; -	S32 mPriceForListing; -}; - -#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 9157df789f..fb5957ff8f 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -27,6 +27,8 @@  #include "llviewerprecompiledheaders.h"  #include "llpanelplaceinfo.h" +#include "llfloaterprofile.h" +#include "llfloaterreg.h"  #include "llavatarname.h"  #include "llsdutil.h" @@ -42,7 +44,6 @@  #include "llagent.h"  #include "llexpandabletextbox.h" -#include "llpanelpick.h"  #include "llslurl.h"  #include "lltexturectrl.h"  #include "llviewerregion.h" @@ -287,7 +288,7 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)  	}  } -void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel) +void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global)  {  	LLPickData data;  	data.pos_global = pos_global; @@ -296,7 +297,12 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit*  	data.desc = mDescEditor->getText();  	data.snapshot_id = mSnapshotCtrl->getImageAssetID();  	data.parcel_id = mParcelID; -	pick_panel->setPickData(&data); + +    LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::showInstance("profile", LLSD().with("id", gAgentID))); +    if (profile_floater) +    { +        profile_floater->createPick(data); +    }  }  // static diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 8bf67cfe7d..533215016a 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -38,7 +38,6 @@ class LLAvatarName;  class LLExpandableTextBox;  class LLIconCtrl;  class LLInventoryItem; -class LLPanelPickEdit;  class LLParcel;  class LLScrollContainer;  class LLTextBox; @@ -94,7 +93,7 @@ public:  	// Create a pick for the location specified  	// by global_pos. -	void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel); +	void createPick(const LLVector3d& pos_global);  protected:  	static void onNameCache(LLTextBox* text, const std::string& full_name); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 69f181e1b3..74ec576554 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -63,7 +63,6 @@  #include "lllayoutstack.h"  #include "llpanellandmarkinfo.h"  #include "llpanellandmarks.h" -#include "llpanelpick.h"  #include "llpanelplaceprofile.h"  #include "llpanelteleporthistory.h"  #include "llremoteparcelrequest.h" @@ -238,7 +237,6 @@ LLPanelPlaces::LLPanelPlaces()  		mFilterEditor(NULL),  		mPlaceProfile(NULL),  		mLandmarkInfo(NULL), -		mPickPanel(NULL),  		mItem(NULL),  		mPlaceMenu(NULL),  		mLandmarkMenu(NULL), @@ -952,28 +950,11 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)  	}  	else if (item == "pick")  	{ -		if (mPickPanel == NULL) -		{ -			mPickPanel = LLPanelPickEdit::create(); -			addChild(mPickPanel); - -			mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); -			mPickPanel->setCancelCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); -			mPickPanel->setSaveCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); -		} - -		togglePickPanel(TRUE); -		mPickPanel->onOpen(LLSD()); -  		LLPanelPlaceInfo* panel = getCurrentInfoPanel();  		if (panel)  		{ -			panel->createPick(mPosGlobal, mPickPanel); +			panel->createPick(mPosGlobal);  		} - -		LLRect rect = getRect(); -		mPickPanel->reshape(rect.getWidth(), rect.getHeight()); -		mPickPanel->setRect(rect);  	}  	else if (item == "add_to_favbar")  	{ @@ -1050,17 +1031,6 @@ bool LLPanelPlaces::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_t      return false;  } -void LLPanelPlaces::togglePickPanel(BOOL visible) -{ -	if (mPickPanel) -	{ -		mPickPanel->setVisible(visible); -		mPlaceProfile->setVisible(!visible); -		updateVerbs(); -	} - -} -  void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)  {  	if (!mPlaceProfile || !mLandmarkInfo) @@ -1309,15 +1279,11 @@ void LLPanelPlaces::updateVerbs()  	bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;  	bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; -	bool is_pick_panel_visible = false; -	if(mPickPanel) -	{ -		is_pick_panel_visible = mPickPanel->isInVisibleChain(); -	} +  	bool have_3d_pos = ! mPosGlobal.isExactlyZero(); -	mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); -	mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); +	mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); +	mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);  	mSaveBtn->setVisible(isLandmarkEditModeOn);  	mCancelBtn->setVisible(isLandmarkEditModeOn);  	mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 3b87eb6cb9..e554099343 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -38,7 +38,6 @@ class LLLandmark;  class LLPanelLandmarkInfo;  class LLPanelPlaceProfile; -class LLPanelPickEdit;  class LLPanelPlaceInfo;  class LLPanelPlacesTab;  class LLParcelSelection; @@ -95,7 +94,6 @@ private:  	void onOverflowButtonClicked();  	void onOverflowMenuItemClicked(const LLSD& param);  	bool onOverflowMenuItemEnable(const LLSD& param); -	void onCreateLandmarkButtonClicked(const LLUUID& folder_id);  	void onBackButtonClicked();      void onGearMenuClick();      void onSortingMenuClick(); @@ -103,9 +101,6 @@ private:      void onRemoveButtonClicked();      bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept); - -	void toggleMediaPanel(); -	void togglePickPanel(BOOL visible);  	void togglePlaceInfoPanel(BOOL visible);  	/*virtual*/ void onVisibilityChange(BOOL new_visibility); @@ -122,7 +117,6 @@ private:  	LLPanelPlaceProfile*		mPlaceProfile;  	LLPanelLandmarkInfo*		mLandmarkInfo; -	LLPanelPickEdit*			mPickPanel;  	LLToggleableMenu*			mPlaceMenu;  	LLToggleableMenu*			mLandmarkMenu; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 5f13b223fb..29c9329a26 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1,25 +1,25 @@ -/**  +/**  * @file llpanelprofile.cpp  * @brief Profile panel implementation  * -* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* $LicenseInfo:firstyear=2022&license=viewerlgpl$  * Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -*  +* Copyright (C) 2022, 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$  */ @@ -27,32 +27,432 @@  #include "llviewerprecompiledheaders.h"  #include "llpanelprofile.h" -#include "llagent.h" +// Common +#include "llavatarnamecache.h" +#include "llsdutil.h" +#include "llslurl.h" +#include "lldateutil.h" //ageFromDate + +// UI +#include "llavatariconctrl.h" +#include "llclipboard.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lllineeditor.h" +#include "llloadingindicator.h" +#include "llmenubutton.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltoggleablemenu.h" +#include "llgrouplist.h" +#include "llurlaction.h" + +// Image +#include "llimagej2c.h" + +// Newview +#include "llagent.h" //gAgent +#include "llagentpicksinfo.h"  #include "llavataractions.h" -#include "llfloaterreg.h" +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h"  #include "llcommandhandler.h" -#include "llnotificationsutil.h" -#include "llpanelpicks.h" -#include "lltabcontainer.h" -#include "llviewercontrol.h" -#include "llviewernetwork.h" +#include "llfloaterprofiletexture.h" +#include "llfloaterreg.h" +#include "llfilepicker.h" +#include "llfirstuse.h" +#include "llgroupactions.h" +#include "lllogchat.h"  #include "llmutelist.h" +#include "llnotificationsutil.h"  #include "llpanelblockedlist.h" +#include "llpanelprofileclassifieds.h" +#include "llpanelprofilepicks.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" //is_agent_mappable +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h"  #include "llweb.h" -static const std::string PANEL_PICKS = "panel_picks"; -std::string getProfileURL(const std::string& agent_name) +static LLPanelInjector<LLPanelProfileSecondLife> t_panel_profile_secondlife("panel_profile_secondlife"); +static LLPanelInjector<LLPanelProfileWeb> t_panel_web("panel_profile_web"); +static LLPanelInjector<LLPanelProfilePicks> t_panel_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfileFirstLife> t_panel_firstlife("panel_profile_firstlife"); +static LLPanelInjector<LLPanelProfileNotes> t_panel_notes("panel_profile_notes"); +static LLPanelInjector<LLPanelProfile>          t_panel_profile("panel_profile"); + +static const std::string PANEL_SECONDLIFE   = "panel_profile_secondlife"; +static const std::string PANEL_WEB          = "panel_profile_web"; +static const std::string PANEL_PICKS        = "panel_profile_picks"; +static const std::string PANEL_CLASSIFIEDS  = "panel_profile_classifieds"; +static const std::string PANEL_FIRSTLIFE    = "panel_profile_firstlife"; +static const std::string PANEL_NOTES        = "panel_profile_notes"; +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; +static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; + + +////////////////////////////////////////////////////////////////////////// + +void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("request_avatar_properties_coro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders; + +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    httpOpts->setFollowRedirects(true); + +    std::string finalUrl = cap_url + "/" + agent_id.asString(); + +    LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Result: " << httpResults << LL_ENDL; + +    if (!status +        || !result.has("id") +        || agent_id != result["id"].asUUID()) +    { +        LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; +        return; +    } + +    LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", agent_id)); +    if (!floater_profile) +    { +        // floater is dead, so panels are dead as well +        return; +    } + +    LLPanel *panel = floater_profile->findChild<LLPanel>(PANEL_PROFILE_VIEW, TRUE); +    LLPanelProfile *panel_profile = dynamic_cast<LLPanelProfile*>(panel); +    if (!panel_profile) +    { +        LL_WARNS() << PANEL_PROFILE_VIEW << " not found" << LL_ENDL; +        return; +    } + + +    // Avatar Data + +    LLAvatarData *avatar_data = &panel_profile->mAvatarData; +    std::string birth_date; + +    avatar_data->agent_id = agent_id; +    avatar_data->avatar_id = agent_id; +    avatar_data->image_id = result["sl_image_id"].asUUID(); +    avatar_data->fl_image_id = result["fl_image_id"].asUUID(); +    avatar_data->partner_id = result["partner_id"].asUUID(); +    avatar_data->about_text = result["sl_about_text"].asString(); +    avatar_data->fl_about_text = result["fl_about_text"].asString(); +    avatar_data->born_on = result["member_since"].asDate(); +    avatar_data->profile_url = getProfileURL(agent_id.asString()); + +    avatar_data->flags = 0; + +    if (result["online"].asBoolean()) +    { +        avatar_data->flags |= AVATAR_ONLINE; +    } +    if (result["allow_publish"].asBoolean()) +    { +        avatar_data->flags |= AVATAR_ALLOW_PUBLISH; +    } +    if (result["identified"].asBoolean()) +    { +        avatar_data->flags |= AVATAR_IDENTIFIED; +    } +    if (result["transacted"].asBoolean()) +    { +        avatar_data->flags |= AVATAR_TRANSACTED; +    } + +    avatar_data->caption_index = 0; +    if (result.has("charter_member")) // won't be present if "caption" is set +    { +        avatar_data->caption_index = result["charter_member"].asInteger(); +    } +    else if (result.has("caption")) +    { +        avatar_data->caption_text = result["caption"].asString(); +    } + +    panel = floater_profile->findChild<LLPanel>(PANEL_SECONDLIFE, TRUE); +    LLPanelProfileSecondLife *panel_sl = dynamic_cast<LLPanelProfileSecondLife*>(panel); +    if (panel_sl) +    { +        panel_sl->processProfileProperties(avatar_data); +    } + +    panel = floater_profile->findChild<LLPanel>(PANEL_WEB, TRUE); +    LLPanelProfileWeb *panel_web = dynamic_cast<LLPanelProfileWeb*>(panel); +    if (panel_web) +    { +        panel_web->setLoaded(); +    } + +    panel = floater_profile->findChild<LLPanel>(PANEL_FIRSTLIFE, TRUE); +    LLPanelProfileFirstLife *panel_first = dynamic_cast<LLPanelProfileFirstLife*>(panel); +    if (panel_first) +    { +        panel_first->processProperties(avatar_data); +    } + +    // Picks + +    LLSD picks_array = result["picks"]; +    LLAvatarPicks avatar_picks; +    avatar_picks.agent_id = agent_id; // Not in use? +    avatar_picks.target_id = agent_id; + +    for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) +    { +        const LLSD& pick_data = *it; +        avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); +    } + +    panel = floater_profile->findChild<LLPanel>(PANEL_PICKS, TRUE); +    LLPanelProfilePicks *panel_picks = dynamic_cast<LLPanelProfilePicks*>(panel); +    if (panel_picks) +    { +        // Refresh pick limit before processing +        LLAgentPicksInfo::getInstance()->onServerRespond(&avatar_picks); +        panel_picks->processProperties(&avatar_picks); +    } + +    // Groups + +    LLSD groups_array = result["groups"]; +    LLAvatarGroups avatar_groups; +    avatar_groups.agent_id = agent_id; // Not in use? +    avatar_groups.avatar_id = agent_id; // target_id + +    for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) +    { +        const LLSD& group_info = *it; +        LLAvatarGroups::LLGroupData group_data; +        group_data.group_powers = 0; // Not in use? +        group_data.group_title = group_info["name"].asString(); // Missing data, not in use? +        group_data.group_id = group_info["id"].asUUID(); +        group_data.group_name = group_info["name"].asString(); +        group_data.group_insignia_id = group_info["image_id"].asUUID(); + +        avatar_groups.group_list.push_back(group_data); +    } + +    if (panel_sl) +    { +        panel_sl->processGroupProperties(&avatar_groups); +    } + +    // Notes +    LLAvatarNotes avatar_notes; + +    avatar_notes.agent_id = agent_id; +    avatar_notes.target_id = agent_id; +    avatar_notes.notes = result["notes"].asString(); + +    panel = floater_profile->findChild<LLPanel>(PANEL_NOTES, TRUE); +    LLPanelProfileNotes *panel_notes = dynamic_cast<LLPanelProfileNotes*>(panel); +    if (panel_notes) +    { +        panel_notes->processProperties(&avatar_notes); +    } +} + +//TODO: changes take two minutes to propagate! +// Add some storage that holds updated data for two minutes +// for new instances to reuse the data +// Profile data is only relevant to won avatar, but notes +// are for everybody +void put_avatar_properties_coro(std::string cap_url, LLUUID agent_id, LLSD data) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders; + +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    httpOpts->setFollowRedirects(true); + +    std::string finalUrl = cap_url + "/" + agent_id.asString(); + +    LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS("AvatarProperties") << "Failed to put agent information " << data << " for id " << agent_id << LL_ENDL; +        return; +    } + +    LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Data: " << data << " Result: " << httpResults << LL_ENDL; +} + +LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle<LLPanel> *handle) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders; + +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    httpOpts->setFollowRedirects(true); +     +    LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        // todo: notification? +        LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; +        return LLUUID::null; +    } +    if (!result.has("uploader")) +    { +        // todo: notification? +        LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; +        return LLUUID::null; +    } +    std::string uploader_cap = result["uploader"].asString(); +    if (uploader_cap.empty()) +    { +        LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL; +        return LLUUID::null; +    } + +    // Upload the image + +    LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); +    LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); +    S64 length; + +    { +        llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); +        if (!instream.is_open()) +        { +            LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; +            return LLUUID::null; +        } +        length = instream.tellg(); +    } + +    uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional +    uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! +    uploaderhttpOpts->setFollowRedirects(true); + +    result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); + +    httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    LL_WARNS("AvatarProperties") << result << LL_ENDL; + +    if (!status) +    { +        LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; +        return LLUUID::null; +    } + +    if (result["state"].asString() != "complete") +    { +        if (result.has("message")) +        { +            LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; +        } +        else +        { +            LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; +        } +        return LLUUID::null; +    } + +    return result["new_asset"].asUUID(); +} + +enum EProfileImageType +{ +    PROFILE_IMAGE_SL, +    PROFILE_IMAGE_FL, +}; + +void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image, LLHandle<LLPanel> *handle)  { -	std::string url = "[WEB_PROFILE_URL][AGENT_NAME]"; -	LLSD subs; -	subs["WEB_PROFILE_URL"] = LLGridManager::getInstance()->getWebProfileURL(); -	subs["AGENT_NAME"] = agent_name; -	url = LLWeb::expandURLSubstitutions(url, subs); -	LLStringUtil::toLower(url); -	return url; +    LLSD data; +    switch (type) +    { +    case PROFILE_IMAGE_SL: +        data["profile-image-asset"] = "sl_image_id"; +        break; +    case PROFILE_IMAGE_FL: +        data["profile-image-asset"] = "fl_image_id"; +        break; +    } + +    LLUUID result = post_profile_image(cap_url, data, path_to_image, handle); + +    // reset loading indicator +    if (!handle->isDead()) +    { +        switch (type) +        { +        case PROFILE_IMAGE_SL: +            { +                LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get()); +                if (result.notNull()) +                { +                    panel->setProfileImageUploaded(result); +                } +                else +                { +                    // failure, just stop progress indicator +                    panel->setProfileImageUploading(false); +                } +                break; +            } +        case PROFILE_IMAGE_FL: +            { +                LLPanelProfileFirstLife* panel = static_cast<LLPanelProfileFirstLife*>(handle->get()); +                if (result.notNull()) +                { +                    panel->setProfileImageUploaded(result); +                } +                else +                { +                    // failure, just stop progress indicator +                    panel->setProfileImageUploading(false); +                } +                break; +            } +        } +    } + +    // Cleanup +    LLFile::remove(path_to_image); +    delete handle;  } +////////////////////////////////////////////////////////////////////////// +// LLProfileHandler +  class LLProfileHandler : public LLCommandHandler  {  public: @@ -73,6 +473,10 @@ public:  };  LLProfileHandler gProfileHandler; + +////////////////////////////////////////////////////////////////////////// +// LLAgentHandler +  class LLAgentHandler : public LLCommandHandler  {  public: @@ -184,273 +588,2067 @@ public:  LLAgentHandler gAgentHandler; -//-- LLPanelProfile::ChildStack begins ---------------------------------------- -LLPanelProfile::ChildStack::ChildStack() -:	mParent(NULL) +///---------------------------------------------------------------------------- +/// LLFloaterProfilePermissions +///---------------------------------------------------------------------------- + +class LLFloaterProfilePermissions +    : public LLFloater +    , public LLFriendObserver +{ +public: +    LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); +    ~LLFloaterProfilePermissions(); +    BOOL postBuild() override; +    void onOpen(const LLSD& key) override; +    void draw() override; +    void changed(U32 mask) override; // LLFriendObserver + +    void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +    bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } + +    void onApplyRights(); + +private: +    void fillRightsData(); +    void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); +    void confirmModifyRights(bool grant); +    void onCommitSeeOnlineRights(); +    void onCommitEditRights(); +    void onCancel(); + +    LLTextBase*         mDescription; +    LLCheckBoxCtrl*     mOnlineStatus; +    LLCheckBoxCtrl*     mMapRights; +    LLCheckBoxCtrl*     mEditObjectRights; +    LLButton*           mOkBtn; +    LLButton*           mCancelBtn; + +    LLUUID              mAvatarID; +    F32                 mContextConeOpacity; +    bool                mHasUnsavedPermChanges; +    LLHandle<LLView>    mOwnerHandle; + +    boost::signals2::connection	mAvatarNameCacheConnection; +}; + +LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) +    : LLFloater(LLSD()) +    , mAvatarID(avatar_id) +    , mContextConeOpacity(0.0f) +    , mHasUnsavedPermChanges(false) +    , mOwnerHandle(owner->getHandle())  { +    buildFromFile("floater_profile_permissions.xml");  } -LLPanelProfile::ChildStack::~ChildStack() +LLFloaterProfilePermissions::~LLFloaterProfilePermissions()  { -	while (mStack.size() != 0) -	{ -		view_list_t& top = mStack.back(); -		for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) -		{ -			LLView* viewp = *it; -			if (viewp) -			{ -				viewp->die(); -			} -		} -		mStack.pop_back(); -	} +    mAvatarNameCacheConnection.disconnect(); +    if (mAvatarID.notNull()) +    { +        LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); +    }  } -void LLPanelProfile::ChildStack::setParent(LLPanel* parent) +BOOL LLFloaterProfilePermissions::postBuild()  { -	llassert_always(parent != NULL); -	mParent = parent; +    mDescription = getChild<LLTextBase>("perm_description"); +    mOnlineStatus = getChild<LLCheckBoxCtrl>("online_check"); +    mMapRights = getChild<LLCheckBoxCtrl>("map_check"); +    mEditObjectRights = getChild<LLCheckBoxCtrl>("objects_check"); +    mOkBtn = getChild<LLButton>("perms_btn_ok"); +    mCancelBtn = getChild<LLButton>("perms_btn_cancel"); + +    mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); +    mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); +    mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); +    mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); +    mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); + +    return TRUE;  } -/// Save current parent's child views and remove them from the child list. -bool LLPanelProfile::ChildStack::push() +void LLFloaterProfilePermissions::onOpen(const LLSD& key)  { -	view_list_t vlist = *mParent->getChildList(); +    if (LLAvatarActions::isFriend(mAvatarID)) +    { +        LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); +        fillRightsData(); +    } -	for (view_list_t::const_iterator it = vlist.begin(); it != vlist.end(); ++it) -	{ -		LLView* viewp = *it; -		mParent->removeChild(viewp); -	} +    mCancelBtn->setFocus(true); -	mStack.push_back(vlist); -	dump(); -	return true; +    mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2));  } -/// Restore saved children (adding them back to the child list). -bool LLPanelProfile::ChildStack::pop() +void LLFloaterProfilePermissions::draw()  { -	if (mStack.size() == 0) -	{ -		LL_WARNS() << "Empty stack" << LL_ENDL; -		llassert(mStack.size() == 0); -		return false; -	} +    // drawFrustum +    LLView *owner = mOwnerHandle.get(); +    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); +    drawConeToOwner(mContextConeOpacity, max_opacity, owner); +    LLFloater::draw(); +} -	view_list_t& top = mStack.back(); -	for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) -	{ -		LLView* viewp = *it; -		mParent->addChild(viewp); -	} +void LLFloaterProfilePermissions::changed(U32 mask) +{ +    if (mask != LLFriendObserver::ONLINE) +    { +        fillRightsData(); +    } +} + +void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mAvatarNameCacheConnection.disconnect(); -	mStack.pop_back(); -	dump(); -	return true; +    LLStringUtil::format_map_t args; +    args["[AGENT_NAME]"] = av_name.getDisplayName(); +    std::string descritpion = getString("description_string", args); +    mDescription->setValue(descritpion);  } -/// Temporarily add all saved children back. -void LLPanelProfile::ChildStack::preParentReshape() +void LLFloaterProfilePermissions::fillRightsData()  { -	mSavedStack = mStack; -	while(mStack.size() > 0) -	{ -		pop(); -	} +    const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); +    // If true - we are viewing friend's profile, enable check boxes and set values. +    if (relation) +    { +        S32 rights = relation->getRightsGrantedTo(); + +        BOOL see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE; +        mOnlineStatus->setValue(see_online); +        mMapRights->setEnabled(see_online); +        mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); +        mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); +    } +    else +    { +        closeFloater(); +        LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; +    }  } -/// Add the temporarily saved children back. -void LLPanelProfile::ChildStack::postParentReshape() +void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, +    const LLSD& response)  { -	mStack = mSavedStack; -	mSavedStack = stack_t(); +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +    if (option != 0) // canceled +    { +        mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? FALSE : TRUE); +    } +    else +    { +        mHasUnsavedPermChanges = true; +    } +} -	for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it) -	{ -		const view_list_t& vlist = (*stack_it); -		for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) -		{ -			LLView* viewp = *list_it; -			LL_DEBUGS() << "removing " << viewp->getName() << LL_ENDL; -			mParent->removeChild(viewp); -		} -	} +void LLFloaterProfilePermissions::confirmModifyRights(bool grant) +{ +    LLSD args; +    args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); +    LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), +        boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2));  } -void LLPanelProfile::ChildStack::dump() +void LLFloaterProfilePermissions::onCommitSeeOnlineRights()  { -	unsigned lvl = 0; -	LL_DEBUGS() << "child stack dump:" << LL_ENDL; -	for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it, ++lvl) -	{ -		std::ostringstream dbg_line; -		dbg_line << "lvl #" << lvl << ":"; -		const view_list_t& vlist = (*stack_it); -		for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) -		{ -			dbg_line << " " << (*list_it)->getName(); -		} -		LL_DEBUGS() << dbg_line.str() << LL_ENDL; -	} +    bool see_online = mOnlineStatus->getValue().asBoolean(); +    mMapRights->setEnabled(see_online); +    if (see_online) +    { +        const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); +        if (relation) +        { +            S32 rights = relation->getRightsGrantedTo(); +            mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); +        } +        else +        { +            closeFloater(); +            LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; +        } +    } +    else +    { +        mMapRights->setValue(FALSE); +    } +    mHasUnsavedPermChanges = true;  } -//-- LLPanelProfile::ChildStack ends ------------------------------------------ +void LLFloaterProfilePermissions::onCommitEditRights() +{ +    const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); -LLPanelProfile::LLPanelProfile() - : LLPanel() - , mAvatarId(LLUUID::null) +    if (!buddy_relationship) +    { +        LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; +        closeFloater(); +        return; +    } + +    bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); + +    // if modify objects checkbox clicked +    if (buddy_relationship->isRightGrantedTo( +        LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) +    { +        confirmModifyRights(allow_modify_objects); +    } +} + +void LLFloaterProfilePermissions::onApplyRights() +{ +    const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + +    if (!buddy_relationship) +    { +        LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; +        return; +    } + +    S32 rights = 0; + +    if (mOnlineStatus->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_ONLINE_STATUS; +    } +    if (mMapRights->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_MAP_LOCATION; +    } +    if (mEditObjectRights->getValue().asBoolean()) +    { +        rights |= LLRelationship::GRANT_MODIFY_OBJECTS; +    } + +    LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); + +    closeFloater(); +} + +void LLFloaterProfilePermissions::onCancel()  { -	mChildStack.setParent(this); +    closeFloater();  } -BOOL LLPanelProfile::postBuild() +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileSecondLife + +LLPanelProfileSecondLife::LLPanelProfileSecondLife() +    : LLPanelProfileTab() +    , mAvatarNameCacheConnection() +    , mHasUnsavedDescriptionChanges(false) +    , mWaitingForImageUpload(false) +    , mAllowPublish(false) +{ +} + +LLPanelProfileSecondLife::~LLPanelProfileSecondLife()  { -	LLPanelPicks* panel_picks = findChild<LLPanelPicks>(PANEL_PICKS); -	panel_picks->setProfilePanel(this); +    if (getAvatarId().notNull()) +    { +        LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +    } -	getTabContainer()[PANEL_PICKS] = panel_picks; +    if (LLVoiceClient::instanceExists()) +    { +        LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); +    } -	return TRUE; +    if (mAvatarNameCacheConnection.connected()) +    { +        mAvatarNameCacheConnection.disconnect(); +    }  } -// virtual -void LLPanelProfile::reshape(S32 width, S32 height, BOOL called_from_parent) +BOOL LLPanelProfileSecondLife::postBuild()  { -	// Temporarily add saved children back and reshape them. -	mChildStack.preParentReshape(); -	LLPanel::reshape(width, height, called_from_parent); -	mChildStack.postParentReshape(); +    mGroupList              = getChild<LLGroupList>("group_list"); +    mShowInSearchCombo      = getChild<LLComboBox>("show_in_search"); +    mSecondLifePic          = getChild<LLIconCtrl>("2nd_life_pic"); +    mSecondLifePicLayout    = getChild<LLPanel>("image_panel"); +    mDescriptionEdit        = getChild<LLTextEditor>("sl_description_edit"); +    mAgentActionMenuButton  = getChild<LLMenuButton>("agent_actions_menu"); +    mSaveDescriptionChanges = getChild<LLButton>("save_description_changes"); +    mDiscardDescriptionChanges = getChild<LLButton>("discard_description_changes"); +    mCanSeeOnlineIcon       = getChild<LLIconCtrl>("can_see_online"); +    mCantSeeOnlineIcon      = getChild<LLIconCtrl>("cant_see_online"); +    mCanSeeOnMapIcon        = getChild<LLIconCtrl>("can_see_on_map"); +    mCantSeeOnMapIcon       = getChild<LLIconCtrl>("cant_see_on_map"); +    mCanEditObjectsIcon     = getChild<LLIconCtrl>("can_edit_objects"); +    mCantEditObjectsIcon    = getChild<LLIconCtrl>("cant_edit_objects"); + +    mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); +    mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); }); +    mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); }); +    mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); +    mDiscardDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); +    mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + +    getChild<LLButton>("open_notes")->setCommitCallback([this](LLUICtrl*, void*) { onOpenNotes(); }, nullptr); + +    mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); +    mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); + +    return TRUE; +} + +void LLPanelProfileSecondLife::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    LLUUID avatar_id = getAvatarId(); + +    BOOL own_profile = getSelfProfile(); + +    mGroupList->setShowNone(!own_profile); + +    childSetVisible("notes_panel", !own_profile); +    childSetVisible("settings_panel", own_profile); +    childSetVisible("about_buttons_panel", own_profile); + +    if (own_profile) +    { +        // Group list control cannot toggle ForAgent loading +        // Less than ideal, but viewing own profile via search is edge case +        mGroupList->enableForAgent(false); +    } + +    // Init menu, menu needs to be created in scope of a registar to work correctly. +    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; +    commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); + +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; +    enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); +    enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); + +    if (own_profile) +    { +        mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); +    } +    else +    { +        // Todo: use PeopleContextMenu instead? +        mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); +    } + +    mDescriptionEdit->setParseHTML(!own_profile); + +    if (!own_profile) +    { +        mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : TRUE); +        updateOnlineStatus(); +        fillRightsData(); +    } + +    mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); +} + +void LLPanelProfileSecondLife::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getStarted() && avatar_id.notNull()) +    { +        setIsLoading(); + +        std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +        if (!cap_url.empty()) +        { +            LLCoros::instance().launch("requestAgentUserInfoCoro", +                boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); +        } +        else +        { +            LL_WARNS() << "Failed to update profile data, no cap found" << LL_ENDL; +        } +    } +} + +void LLPanelProfileSecondLife::refreshName() +{ +    if (!mAvatarNameCacheConnection.connected()) +    { +        mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); +    } +} + +void LLPanelProfileSecondLife::resetData() +{ +    resetLoading(); + +    // Set default image and 1:1 dimensions for it +    mSecondLifePic->setValue("Generic_Person_Large"); +    mImageId = LLUUID::null; + +    LLRect imageRect = mSecondLifePicLayout->getRect(); +    mSecondLifePicLayout->reshape(imageRect.getHeight(), imageRect.getHeight()); + +    setDescriptionText(LLStringUtil::null); +    mGroups.clear(); +    mGroupList->setGroups(mGroups); + +    bool own_profile = getSelfProfile(); +    mCanSeeOnlineIcon->setVisible(false); +    mCantSeeOnlineIcon->setVisible(!own_profile); +    mCanSeeOnMapIcon->setVisible(false); +    mCantSeeOnMapIcon->setVisible(!own_profile); +    mCanEditObjectsIcon->setVisible(false); +    mCantEditObjectsIcon->setVisible(!own_profile); + +    mCanSeeOnlineIcon->setEnabled(false); +    mCantSeeOnlineIcon->setEnabled(false); +    mCanSeeOnMapIcon->setEnabled(false); +    mCantSeeOnMapIcon->setEnabled(false); +    mCanEditObjectsIcon->setEnabled(false); +    mCantEditObjectsIcon->setEnabled(false); + +    childSetVisible("partner_layout", FALSE); +} + +void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) +{ +    LLUUID avatar_id = getAvatarId(); +    const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) +    { +        // Relies onto friend observer to get information about online status updates. +        // Once SL-17506 gets implemented, condition might need to become: +        // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) +        processOnlineStatus(relationship != NULL, +                            gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), +                            (avatar_data->flags & AVATAR_ONLINE)); +    } + +    fillCommonData(avatar_data); + +    fillPartnerData(avatar_data); + +    fillAccountStatus(avatar_data); + +    setLoaded(); +} + +void LLPanelProfileSecondLife::processGroupProperties(const LLAvatarGroups* avatar_groups) +{ + +    LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); +    const LLAvatarGroups::group_list_t::const_iterator it_end = avatar_groups->group_list.end(); + +    for (; it_end != it; ++it) +    { +        LLAvatarGroups::LLGroupData group_data = *it; +        mGroups[group_data.group_name] = group_data.group_id; +    } + +    mGroupList->setGroups(mGroups); +} + +void LLPanelProfileSecondLife::openGroupProfile() +{ +    LLUUID group_id = mGroupList->getSelectedUUID(); +    LLGroupActions::show(group_id); +} + +void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mAvatarNameCacheConnection.disconnect(); +    getChild<LLUICtrl>("display_name")->setValue(av_name.getDisplayName()); +    getChild<LLUICtrl>("user_name")->setValue(av_name.getAccountName()); +} + +void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) +{ +    LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("image_upload_indicator"); +    indicator->setVisible(loading); +    if (loading) +    { +        indicator->start(); +    } +    else +    { +        indicator->stop(); +    } +    mWaitingForImageUpload = loading; +} + +void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ +    mSecondLifePic->setValue(image_asset_id); +    mImageId = image_asset_id; + +    LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(image_asset_id); +    if (imagep->getFullHeight()) +    { +        onImageLoaded(true, imagep); +    } +    else +    { +        imagep->setLoadedCallback(onImageLoaded, +            MAX_DISCARD_LEVEL, +            FALSE, +            FALSE, +            new LLHandle<LLPanel>(getHandle()), +            NULL, +            FALSE); +    } + +    LLFloater *floater = mFloaterProfileTextureHandle.get(); +    if (floater) +    { +        LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); +        if (mImageId.notNull()) +        { +            texture_view->loadAsset(mImageId); +        } +        else +        { +            texture_view->resetAsset(); +        } +    } + +    setProfileImageUploading(false); +} + +bool LLPanelProfileSecondLife::hasUnsavedChanges() +{ +    LLFloater *floater = mFloaterPermissionsHandle.get(); +    if (floater) +    { +        LLFloaterProfilePermissions* perm = dynamic_cast<LLFloaterProfilePermissions*>(floater); +        if (perm && perm->hasUnsavedChanges()) +        { +            return true; +        } +    } +    // if floater +    return mHasUnsavedDescriptionChanges; +} + +void LLPanelProfileSecondLife::commitUnsavedChanges() +{ +    LLFloater *floater = mFloaterPermissionsHandle.get(); +    if (floater) +    { +        LLFloaterProfilePermissions* perm = dynamic_cast<LLFloaterProfilePermissions*>(floater); +        if (perm && perm->hasUnsavedChanges()) +        { +            perm->onApplyRights(); +        } +    } +    if (mHasUnsavedDescriptionChanges) +    { +        onSaveDescriptionChanges(); +    } +} + +void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) +{ +    // Refresh avatar id in cache with new info to prevent re-requests +    // and to make sure icons in text will be up to date +    LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); + +    fillAgeData(avatar_data->born_on); + +    setDescriptionText(avatar_data->about_text); + +    if (avatar_data->image_id.notNull()) +    { +        mSecondLifePic->setValue(avatar_data->image_id); +        mImageId = avatar_data->image_id; +    } +    else +    { +        mSecondLifePic->setValue("Generic_Person_Large"); +        mImageId = LLUUID::null; +    } + +    // Will be loaded as a LLViewerFetchedTexture::BOOST_UI due to mSecondLifePic +    LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(avatar_data->image_id); +    if (imagep->getFullHeight()) +    { +        onImageLoaded(true, imagep); +    } +    else +    { +        imagep->setLoadedCallback(onImageLoaded, +                                  MAX_DISCARD_LEVEL, +                                  FALSE, +                                  FALSE, +                                  new LLHandle<LLPanel>(getHandle()), +                                  NULL, +                                  FALSE); +    } + +    if (getSelfProfile()) +    { +        mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; +        mShowInSearchCombo->setValue((BOOL)mAllowPublish); +    } +} + +void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) +{ +    LLTextBox* partner_text_ctrl = getChild<LLTextBox>("partner_link"); +    if (avatar_data->partner_id.notNull()) +    { +        childSetVisible("partner_layout", TRUE); +        LLStringUtil::format_map_t args; +        args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); +        std::string partner_text = getString("partner_text", args); +        partner_text_ctrl->setText(partner_text); +    } +    else +    { +        childSetVisible("partner_layout", FALSE); +    } +} + +void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) +{ +    LLStringUtil::format_map_t args; +    args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); +    args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + +    std::string caption_text = getString("CaptionTextAcctInfo", args); +    getChild<LLUICtrl>("account_info")->setValue(caption_text); +} + +void LLPanelProfileSecondLife::fillRightsData() +{ +    if (getSelfProfile()) +    { +        return; +    } + +    const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    // If true - we are viewing friend's profile, enable check boxes and set values. +    if (relation) +    { +        S32 rights = relation->getRightsGrantedTo(); +        bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; +        bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; +        bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; + +        mCanSeeOnlineIcon->setVisible(can_see_online); +        mCantSeeOnlineIcon->setVisible(!can_see_online); +        mCanSeeOnMapIcon->setVisible(can_see_on_map); +        mCantSeeOnMapIcon->setVisible(!can_see_on_map); +        mCanEditObjectsIcon->setVisible(can_edit_objects); +        mCantEditObjectsIcon->setVisible(!can_edit_objects); + +        mCanSeeOnlineIcon->setEnabled(true); +        mCantSeeOnlineIcon->setEnabled(true); +        mCanSeeOnMapIcon->setEnabled(true); +        mCantSeeOnMapIcon->setEnabled(true); +        mCanEditObjectsIcon->setEnabled(true); +        mCantEditObjectsIcon->setEnabled(true); +    } +    else +    { +        mCanSeeOnlineIcon->setVisible(false); +        mCantSeeOnlineIcon->setVisible(false); +        mCanSeeOnMapIcon->setVisible(false); +        mCantSeeOnMapIcon->setVisible(false); +        mCanEditObjectsIcon->setVisible(false); +        mCantEditObjectsIcon->setVisible(false); +    } +} + +void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) +{ +    std::string name_and_date = getString("date_format"); +    LLSD args_name; +    args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); +    LLStringUtil::format(name_and_date, args_name); +    getChild<LLUICtrl>("sl_birth_date")->setValue(name_and_date); + +    std::string register_date = getString("age_format"); +    LLSD args_age; +    args_age["[AGE]"] = LLDateUtil::ageFromDate(born_on, LLDate::now()); +    LLStringUtil::format(register_date, args_age); +    getChild<LLUICtrl>("user_age")->setValue(register_date); +} + +void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep) +{ +    LLRect imageRect = mSecondLifePicLayout->getRect(); +    if (!success || imagep->getFullWidth() == imagep->getFullHeight()) +    { +        mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); +    } +    else +    { +        // assume 3:4, for sake of firestorm +        mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); +    } +} + +//static +void LLPanelProfileSecondLife::onImageLoaded(BOOL success, +                                             LLViewerFetchedTexture *src_vi, +                                             LLImageRaw* src, +                                             LLImageRaw* aux_src, +                                             S32 discard_level, +                                             BOOL final, +                                             void* userdata) +{ +    if (!userdata) return; + +    LLHandle<LLPanel>* handle = (LLHandle<LLPanel>*)userdata; + +    if (!handle->isDead()) +    { +        LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get()); +        if (panel) +        { +            panel->onImageLoaded(success, src_vi); +        } +    } + +    if (final || !success) +    { +        delete handle; +    } +} + +// virtual, called by LLAvatarTracker +void LLPanelProfileSecondLife::changed(U32 mask) +{ +    updateOnlineStatus(); +    if (mask != LLFriendObserver::ONLINE) +    { +        fillRightsData(); +    } +} + +// virtual, called by LLVoiceClient +void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +    if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +    { +        return; +    } + +    mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : TRUE); +} + +void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.notNull()) +    { +        if (getAvatarId().notNull()) +        { +            LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +        } + +        LLPanelProfileTab::setAvatarId(avatar_id); + +        if (LLAvatarActions::isFriend(getAvatarId())) +        { +            LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); +        } +    } +} + +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 +void LLPanelProfileSecondLife::updateOnlineStatus() +{ +    const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); +    if (relationship != NULL) +    { +        // For friend let check if he allowed me to see his status +        bool online = relationship->isOnline(); +        bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); +        processOnlineStatus(true, perm_granted, online); +    } +    else +    { +        childSetVisible("frind_layout", false); +        childSetVisible("online_layout", false); +        childSetVisible("offline_layout", false); +    } +} + +void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) +{ +    childSetVisible("frind_layout", is_friend); +    childSetVisible("online_layout", online && show_online); +    childSetVisible("offline_layout", !online && show_online); +} + +void LLPanelProfileSecondLife::setLoaded() +{ +    LLPanelProfileTab::setLoaded(); + +    if (getSelfProfile()) +    { +        mShowInSearchCombo->setEnabled(TRUE); +        mDescriptionEdit->setEnabled(TRUE); +    } +} + + + +class LLProfileImagePicker : public LLFilePickerThread +{ +public: +    LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle); +    ~LLProfileImagePicker(); +    void notify(const std::vector<std::string>& filenames) override; + +private: +    LLHandle<LLPanel> *mHandle; +    EProfileImageType mType; +}; + +LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle) +    : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), +    mHandle(handle), +    mType(type) +{ +} + +LLProfileImagePicker::~LLProfileImagePicker() +{ +    delete mHandle; +} + +void LLProfileImagePicker::notify(const std::vector<std::string>& filenames) +{ +    if (mHandle->isDead()) +    { +        return; +    } +    if (filenames.empty()) +    { +        return; +    } +    std::string file_path = filenames[0]; +    if (file_path.empty()) +    { +        return; +    } + +    // generate a temp texture file for coroutine +    std::string temp_file = gDirUtilp->getTempFilename(); +    U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); +    const S32 MAX_DIM = 256; +    if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) +    { +        //todo: image not supported notification +        LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", failed to open image" << LL_ENDL; +        return; +    } + +    std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); +    if (cap_url.empty()) +    { +        LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL; +        return; +    } + +    switch (mType) +    { +    case PROFILE_IMAGE_SL: +        { +            LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(mHandle->get()); +            panel->setProfileImageUploading(true); +        } +        break; +    case PROFILE_IMAGE_FL: +        { +            LLPanelProfileFirstLife* panel = static_cast<LLPanelProfileFirstLife*>(mHandle->get()); +            panel->setProfileImageUploading(true); +        } +        break; +    } + +    LLCoros::instance().launch("postAgentUserImageCoro", +        boost::bind(post_profile_image_coro, cap_url, mType, temp_file, mHandle)); + +    mHandle = nullptr; // transferred to post_profile_image_coro +} + +void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) +{ +    const std::string item_name = userdata.asString(); +    const LLUUID agent_id = getAvatarId(); +    // todo: consider moving this into LLAvatarActions::onCommit(name, id) +    // and making all other flaoters, like people menu do the same +    if (item_name == "im") +    { +        LLAvatarActions::startIM(agent_id); +    } +    else if (item_name == "offer_teleport") +    { +        LLAvatarActions::offerTeleport(agent_id); +    } +    else if (item_name == "request_teleport") +    { +        LLAvatarActions::teleportRequest(agent_id); +    } +    else if (item_name == "voice_call") +    { +        LLAvatarActions::startCall(agent_id); +    } +    else if (item_name == "chat_history") +    { +        LLAvatarActions::viewChatHistory(agent_id); +    } +    else if (item_name == "add_friend") +    { +        LLAvatarActions::requestFriendshipDialog(agent_id); +    } +    else if (item_name == "remove_friend") +    { +        LLAvatarActions::removeFriendDialog(agent_id); +    } +    else if (item_name == "invite_to_group") +    { +        LLAvatarActions::inviteToGroup(agent_id); +    } +    else if (item_name == "can_show_on_map") +    { +        LLAvatarActions::showOnMap(agent_id); +    } +    else if (item_name == "share") +    { +        LLAvatarActions::share(agent_id); +    } +    else if (item_name == "pay") +    { +        LLAvatarActions::pay(agent_id); +    } +    else if (item_name == "toggle_block_agent") +    { +        LLAvatarActions::toggleBlock(agent_id); +    } +    else if (item_name == "copy_user_id") +    { +        LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); +        LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); +    } +    else if (item_name == "agent_permissions") +    { +        onShowAgentPermissionsDialog(); +    } +    else if (item_name == "copy_display_name" +        || item_name == "copy_username") +    { +        LLAvatarName av_name; +        if (!LLAvatarNameCache::get(getAvatarId(), &av_name)) +        { +            // shouldn't happen, option is supposed to be invisible while name is fetching +            LL_WARNS() << "Failed to get agent data" << LL_ENDL; +            return; +        } +        LLWString wstr; +        if (item_name == "copy_display_name") +        { +            wstr = utf8str_to_wstring(av_name.getDisplayName(true)); +        } +        else if (item_name == "copy_username") +        { +            wstr = utf8str_to_wstring(av_name.getUserName()); +        } +        LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); +    } +    else if (item_name == "edit_display_name") +    { +        LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2)); +        LLFirstUse::setDisplayName(false); +    } +    else if (item_name == "edit_partner") +    { +        std::string url = "https://[GRID]/my/account/partners.php"; +        LLSD subs; +        url = LLWeb::expandURLSubstitutions(url, subs); +        LLUrlAction::openURL(url); +    } +    else if (item_name == "upload_photo") +    { +        (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle<LLPanel>(getHandle())))->getFile(); + +        LLFloater* floaterp = mFloaterTexturePickerHandle.get(); +        if (floaterp) +        { +            floaterp->closeFloater(); +        } +    } +    else if (item_name == "change_photo") +    { +        onShowTexturePicker(); +    } +    else if (item_name == "remove_photo") +    { +        onCommitProfileImage(LLUUID::null); + +        LLFloater* floaterp = mFloaterTexturePickerHandle.get(); +        if (floaterp) +        { +            floaterp->closeFloater(); +        } +    } +} + +bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) +{ +    const std::string item_name = userdata.asString(); +    const LLUUID agent_id = getAvatarId(); +    if (item_name == "offer_teleport" || item_name == "request_teleport") +    { +        return LLAvatarActions::canOfferTeleport(agent_id); +    } +    else if (item_name == "voice_call") +    { +        return mVoiceStatus; +    } +    else if (item_name == "chat_history") +    { +        return LLLogChat::isTranscriptExist(agent_id); +    } +    else if (item_name == "add_friend") +    { +        return !LLAvatarActions::isFriend(agent_id); +    } +    else if (item_name == "remove_friend") +    { +        return LLAvatarActions::isFriend(agent_id); +    } +    else if (item_name == "can_show_on_map") +    { +        return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) +        || gAgent.isGodlike(); +    } +    else if (item_name == "toggle_block_agent") +    { +        return LLAvatarActions::canBlock(agent_id); +    } +    else if (item_name == "agent_permissions") +    { +        return LLAvatarActions::isFriend(agent_id); +    } +    else if (item_name == "copy_display_name" +        || item_name == "copy_username") +    { +        return !mAvatarNameCacheConnection.connected(); +    } +    else if (item_name == "upload_photo" +        || item_name == "change_photo") +    { +        std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); +        return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); +    } +    else if (item_name == "remove_photo") +    { +        std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +        return mImageId.notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); +    } + +    return false; +} + +bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) +{ +    const std::string item_name = userdata.asString(); +    const LLUUID agent_id = getAvatarId(); +    if (item_name == "toggle_block_agent") +    { +        return LLAvatarActions::isBlocked(agent_id); +    } +    return false; +} + +void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    if (av_name.getDisplayName().empty()) +    { +        // something is wrong, tell user to try again later +        LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); +        return; +    } + +    LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " +        << LLDate(av_name.mNextUpdate) << LL_ENDL; +    F64 now_secs = LLDate::now().secondsSinceEpoch(); + +    if (now_secs < av_name.mNextUpdate) +    { +        // if the update time is more than a year in the future, it means updates have been blocked +        // show a more general message +        static const S32 YEAR = 60*60*24*365; +        if (now_secs + YEAR < av_name.mNextUpdate) +        { +            LLNotificationsUtil::add("SetDisplayNameBlocked"); +            return; +        } +    } + +    LLFloaterReg::showInstance("display_name"); +} + +void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) +{ +    mSaveDescriptionChanges->setEnabled(FALSE); +    mDiscardDescriptionChanges->setEnabled(FALSE); +    mHasUnsavedDescriptionChanges = false; + +    mDescriptionText = text; +    mDescriptionEdit->setValue(mDescriptionText); +} + +void LLPanelProfileSecondLife::onSetDescriptionDirty() +{ +    mSaveDescriptionChanges->setEnabled(TRUE); +    mDiscardDescriptionChanges->setEnabled(TRUE); +    mHasUnsavedDescriptionChanges = true; +} + +void LLPanelProfileSecondLife::onShowInSearchCallback() +{ +    S32 value = mShowInSearchCombo->getValue().asInteger(); +    if (mAllowPublish == (bool)value) +    { +        return; +    } +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        mAllowPublish = value; +        LLSD data; +        data["allow_publish"] = mAllowPublish; +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), data)); +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } +} + +void LLPanelProfileSecondLife::onSaveDescriptionChanges() +{ +    mDescriptionText = mDescriptionEdit->getValue().asString(); +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("sl_about_text", mDescriptionText))); +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } + +    mSaveDescriptionChanges->setEnabled(FALSE); +    mDiscardDescriptionChanges->setEnabled(FALSE); +    mHasUnsavedDescriptionChanges = false; +} + +void LLPanelProfileSecondLife::onDiscardDescriptionChanges() +{ +    setDescriptionText(mDescriptionText); +} + +void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() +{ +    LLFloater *floater = mFloaterPermissionsHandle.get(); +    if (!floater) +    { +        LLFloater* parent_floater = gFloaterView->getParentFloater(this); +        if (parent_floater) +        { +            LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); +            mFloaterPermissionsHandle = perms->getHandle(); +            perms->openFloater(); +            perms->setVisibleAndFrontmost(TRUE); + +            parent_floater->addDependentFloater(mFloaterPermissionsHandle); +        } +    } +    else // already open +    { +        floater->setMinimized(FALSE); +        floater->setVisibleAndFrontmost(TRUE); +    } +} + +void LLPanelProfileSecondLife::onShowAgentProfileTexture() +{ +    if (!getIsLoaded()) +    { +        return; +    } + +    LLFloater *floater = mFloaterProfileTextureHandle.get(); +    if (!floater) +    { +        LLFloater* parent_floater = gFloaterView->getParentFloater(this); +        if (parent_floater) +        { +            LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); +            mFloaterProfileTextureHandle = texture_view->getHandle(); +            if (mImageId.notNull()) +            { +                texture_view->loadAsset(mImageId); +            } +            else +            { +                texture_view->resetAsset(); +            } +            texture_view->openFloater(); +            texture_view->setVisibleAndFrontmost(TRUE); + +            parent_floater->addDependentFloater(mFloaterProfileTextureHandle); +        } +    } +    else // already open +    { +        LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); +        texture_view->setMinimized(FALSE); +        texture_view->setVisibleAndFrontmost(TRUE); +        if (mImageId.notNull()) +        { +            texture_view->loadAsset(mImageId); +        } +        else +        { +            texture_view->resetAsset(); +        } +    } +} + +void LLPanelProfileSecondLife::onShowTexturePicker() +{ +    LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + +    // Show the dialog +    if (!floaterp) +    { +        LLFloater* parent_floater = gFloaterView->getParentFloater(this); +        if (parent_floater) +        { +            // because inventory construction is somewhat slow +            getWindow()->setCursor(UI_CURSOR_WAIT); +            LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( +                this, +                mImageId, +                LLUUID::null, +                mImageId, +                FALSE, +                FALSE, +                "SELECT PHOTO", +                PERM_NONE, +                PERM_NONE, +                PERM_NONE, +                FALSE, +                NULL); + +            mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + +            texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) +            { +                if (op == LLTextureCtrl::TEXTURE_SELECT) +                { +                    LLUUID image_asset_id; +                    LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); +                    if (floaterp) +                    { +                        if (id.notNull()) +                        { +                            image_asset_id = id; +                        } +                        else +                        { +                            image_asset_id = floaterp->getAssetID(); +                        } +                    } + +                    onCommitProfileImage(image_asset_id); +                } +            }); +            texture_floaterp->setLocalTextureEnabled(FALSE); +            texture_floaterp->setBakeTextureEnabled(FALSE); +            texture_floaterp->setCanApply(false, true); + +            parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + +            texture_floaterp->openFloater(); +            texture_floaterp->setFocus(TRUE); +        } +    } +    else +    { +        floaterp->setMinimized(FALSE); +        floaterp->setVisibleAndFrontmost(TRUE); +    } +} + +void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) +{ +    if (mImageId == id) +    { +        return; +    } + +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        LLSD params; +        params["sl_image_id"] = id; +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params)); + +        mImageId = id; +        if (mImageId == LLUUID::null) +        { +            mSecondLifePic->setValue("Generic_Person_Large"); +        } +        else +        { +            mSecondLifePic->setValue(mImageId); +        } + +        LLFloater *floater = mFloaterProfileTextureHandle.get(); +        if (floater) +        { +            LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); +            if (mImageId == LLUUID::null) +            { +                texture_view->resetAsset(); +            } +            else +            { +                texture_view->loadAsset(mImageId); +            } +        } +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } +} + +void LLPanelProfileSecondLife::onOpenNotes() +{ +    LLFloater* parent_floater = gFloaterView->getParentFloater(this); +    if (!parent_floater) +    { +        return; +    } + +    LLTabContainer* tab_container = parent_floater->findChild<LLTabContainer>("panel_profile_tabs", TRUE); +    if (!tab_container) +    { +        return; +    } + +    tab_container->selectTabByName(PANEL_NOTES); +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileWeb + +LLPanelProfileWeb::LLPanelProfileWeb() + : LLPanelProfileTab() + , mWebBrowser(NULL) + , mAvatarNameCacheConnection() +{ +} + +LLPanelProfileWeb::~LLPanelProfileWeb() +{ +    if (mAvatarNameCacheConnection.connected()) +    { +        mAvatarNameCacheConnection.disconnect(); +    } +} + +void LLPanelProfileWeb::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); + +    mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); +} + +BOOL LLPanelProfileWeb::postBuild() +{ +    mWebBrowser = getChild<LLMediaCtrl>("profile_html"); +    mWebBrowser->addObserver(this); +    mWebBrowser->setHomePageUrl("about:blank"); + +    return TRUE; +} + +void LLPanelProfileWeb::resetData() +{ +    mWebBrowser->navigateHome(); +} + +void LLPanelProfileWeb::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) +    { +        setIsLoading(); + +        mWebBrowser->setVisible(TRUE); +        mPerformanceTimer.start(); +        mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); +    } +} + +void LLPanelProfileWeb::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ +    mAvatarNameCacheConnection.disconnect(); + +    std::string username = av_name.getAccountName(); +    if (username.empty()) +    { +        username = LLCacheName::buildUsername(av_name.getDisplayName()); +    } +    else +    { +        LLStringUtil::replaceChar(username, ' ', '.'); +    } + +    mURLWebProfile = getProfileURL(username, true); +    if (mURLWebProfile.empty()) +    { +        return; +    } + +    //if the tab was opened before name was resolved, load the panel now +    updateData(); +} + +void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) +{ +    if (!mURLHome.empty()) +    { +        LLSD::String valstr = ctrl->getValue().asString(); +        if (valstr.empty()) +        { +            mWebBrowser->setVisible(TRUE); +            mPerformanceTimer.start(); +            mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); +        } +        else if (valstr == "popout") +        { +            // open in viewer's browser, new window +            LLWeb::loadURLInternal(mURLHome); +        } +        else if (valstr == "external") +        { +            // open in external browser +            LLWeb::loadURLExternal(mURLHome); +        } +    } +} + +void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ +    switch(event) +    { +        case MEDIA_EVENT_STATUS_TEXT_CHANGED: +            childSetValue("status_text", LLSD( self->getStatusText() ) ); +        break; + +        case MEDIA_EVENT_NAVIGATE_BEGIN: +        { +            if (mFirstNavigate) +            { +                mFirstNavigate = false; +            } +            else +            { +                mPerformanceTimer.start(); +            } +        } +        break; + +        case MEDIA_EVENT_NAVIGATE_COMPLETE: +        { +            LLStringUtil::format_map_t args; +            args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); +            childSetValue("status_text", LLSD( getString("LoadTime", args)) ); +        } +        break; + +        default: +            // Having a default case makes the compiler happy. +        break; +    } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileFirstLife::LLPanelProfileFirstLife() + : LLPanelProfileTab() + , mHasUnsavedChanges(false) +{ +} + +LLPanelProfileFirstLife::~LLPanelProfileFirstLife() +{ +} + +BOOL LLPanelProfileFirstLife::postBuild() +{ +    mDescriptionEdit = getChild<LLTextEditor>("fl_description_edit"); +    mPicture = getChild<LLIconCtrl>("real_world_pic"); + +    mUploadPhoto = getChild<LLButton>("fl_upload_image"); +    mChangePhoto = getChild<LLButton>("fl_change_image"); +    mRemovePhoto = getChild<LLButton>("fl_remove_image"); +    mSaveChanges = getChild<LLButton>("fl_save_changes"); +    mDiscardChanges = getChild<LLButton>("fl_discard_changes"); + +    mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); +    mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); +    mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); +    mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); +    mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); +    mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + +    return TRUE; +} + +void LLPanelProfileFirstLife::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    if (!getSelfProfile()) +    { +        // Otherwise as the only focusable element it will be selected +        mDescriptionEdit->setTabStop(FALSE); +    } + +    resetData(); +} + +void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) +{ +    mUploadPhoto->setEnabled(!loading); +    mChangePhoto->setEnabled(!loading); +    mRemovePhoto->setEnabled(!loading && mImageId.notNull()); + +    LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("image_upload_indicator"); +    indicator->setVisible(loading); +    if (loading) +    { +        indicator->start(); +    } +    else +    { +        indicator->stop(); +    } +} + +void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ +    mPicture->setValue(image_asset_id); +    mImageId = image_asset_id; +    setProfileImageUploading(false); +} + +void LLPanelProfileFirstLife::commitUnsavedChanges() +{ +    if (mHasUnsavedChanges) +    { +        onSaveDescriptionChanges(); +    } +} + +void LLPanelProfileFirstLife::onUploadPhoto() +{ +    (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle<LLPanel>(getHandle())))->getFile(); + +    LLFloater* floaterp = mFloaterTexturePickerHandle.get(); +    if (floaterp) +    { +        floaterp->closeFloater(); +    } +} + +void LLPanelProfileFirstLife::onChangePhoto() +{ +    LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + +    // Show the dialog +    if (!floaterp) +    { +        LLFloater* parent_floater = gFloaterView->getParentFloater(this); +        if (parent_floater) +        { +            // because inventory construction is somewhat slow +            getWindow()->setCursor(UI_CURSOR_WAIT); +            LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( +                this, +                mImageId, +                LLUUID::null, +                mImageId, +                FALSE, +                FALSE, +                "SELECT PHOTO", +                PERM_NONE, +                PERM_NONE, +                PERM_NONE, +                FALSE, +                NULL); + +            mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + +            texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) +            { +                if (op == LLTextureCtrl::TEXTURE_SELECT) +                { +                    LLUUID image_asset_id; +                    LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); +                    if (floaterp) +                    { +                        if (id.notNull()) +                        { +                            image_asset_id = id; +                        } +                        else +                        { +                            image_asset_id = floaterp->getAssetID(); +                        } +                    } + +                    onCommitPhoto(image_asset_id); +                } +            }); +            texture_floaterp->setLocalTextureEnabled(FALSE); +            texture_floaterp->setCanApply(false, true); + +            parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + +            texture_floaterp->openFloater(); +            texture_floaterp->setFocus(TRUE); +        } +    } +    else +    { +        floaterp->setMinimized(FALSE); +        floaterp->setVisibleAndFrontmost(TRUE); +    } +} + +void LLPanelProfileFirstLife::onRemovePhoto() +{ +    onCommitPhoto(LLUUID::null); + +    LLFloater* floaterp = mFloaterTexturePickerHandle.get(); +    if (floaterp) +    { +        floaterp->closeFloater(); +    } +} + +void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) +{ +    if (mImageId == id) +    { +        return; +    } + +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        LLSD params; +        params["fl_image_id"] = id; +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params)); + +        mImageId = id; +        if (mImageId.notNull()) +        { +            mPicture->setValue(mImageId); +        } +        else +        { +            mPicture->setValue("Generic_Person_Large"); +        } + +        mRemovePhoto->setEnabled(mImageId.notNull()); +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } +} + +void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) +{ +    mSaveChanges->setEnabled(FALSE); +    mDiscardChanges->setEnabled(FALSE); +    mHasUnsavedChanges = false; + +    mCurrentDescription = text; +    mDescriptionEdit->setValue(mCurrentDescription); +} + +void LLPanelProfileFirstLife::onSetDescriptionDirty() +{ +    mSaveChanges->setEnabled(TRUE); +    mDiscardChanges->setEnabled(TRUE); +    mHasUnsavedChanges = true; +} + +void LLPanelProfileFirstLife::onSaveDescriptionChanges() +{ +    mCurrentDescription = mDescriptionEdit->getValue().asString(); +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("fl_about_text", mCurrentDescription))); +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } + +    mSaveChanges->setEnabled(FALSE); +    mDiscardChanges->setEnabled(FALSE); +    mHasUnsavedChanges = false; +} + +void LLPanelProfileFirstLife::onDiscardDescriptionChanges() +{ +    setDescriptionText(mCurrentDescription); +} + +void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) +{ +    setDescriptionText(avatar_data->fl_about_text); + +    mImageId = avatar_data->fl_image_id; + +    if (mImageId.notNull()) +    { +        mPicture->setValue(mImageId); +    } +    else +    { +        mPicture->setValue("Generic_Person_Large"); +    } + +    setLoaded(); +} + +void LLPanelProfileFirstLife::resetData() +{ +    setDescriptionText(std::string()); +    mPicture->setValue("Generic_Person_Large"); +    mImageId = LLUUID::null; + +    mUploadPhoto->setVisible(getSelfProfile()); +    mChangePhoto->setVisible(getSelfProfile()); +    mRemovePhoto->setVisible(getSelfProfile()); +    mSaveChanges->setVisible(getSelfProfile()); +    mDiscardChanges->setVisible(getSelfProfile()); +} + +void LLPanelProfileFirstLife::setLoaded() +{ +    LLPanelProfileTab::setLoaded(); + +    if (getSelfProfile()) +    { +        mDescriptionEdit->setEnabled(TRUE); +        mPicture->setEnabled(TRUE); +        mRemovePhoto->setEnabled(mImageId.notNull()); +    } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileNotes::LLPanelProfileNotes() +: LLPanelProfileTab() + , mHasUnsavedChanges(false) +{ + +} + +LLPanelProfileNotes::~LLPanelProfileNotes() +{ +} + +void LLPanelProfileNotes::updateData() +{ +    LLUUID avatar_id = getAvatarId(); +    if (!getStarted() && avatar_id.notNull()) +    { +        setIsLoading(); + +        std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +        if (!cap_url.empty()) +        { +            LLCoros::instance().launch("requestAgentUserInfoCoro", +                boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); +        } +    } +} + +void LLPanelProfileNotes::commitUnsavedChanges() +{ +    if (mHasUnsavedChanges) +    { +        onSaveNotesChanges(); +    } +} + +BOOL LLPanelProfileNotes::postBuild() +{ +    mNotesEditor = getChild<LLTextEditor>("notes_edit"); +    mSaveChanges = getChild<LLButton>("notes_save_changes"); +    mDiscardChanges = getChild<LLButton>("notes_discard_changes"); + +    mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); +    mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); +    mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); + +    return TRUE; +} + +void LLPanelProfileNotes::onOpen(const LLSD& key) +{ +    LLPanelProfileTab::onOpen(key); + +    resetData(); +} + +void LLPanelProfileNotes::setNotesText(const std::string &text) +{ +    mSaveChanges->setEnabled(FALSE); +    mDiscardChanges->setEnabled(FALSE); +    mHasUnsavedChanges = false; + +    mCurrentNotes = text; +    mNotesEditor->setValue(mCurrentNotes); +} + +void LLPanelProfileNotes::onSetNotesDirty() +{ +    mSaveChanges->setEnabled(TRUE); +    mDiscardChanges->setEnabled(TRUE); +    mHasUnsavedChanges = true; +} + +void LLPanelProfileNotes::onSaveNotesChanges() +{ +    mCurrentNotes = mNotesEditor->getValue().asString(); +    std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +    if (!cap_url.empty()) +    { +        LLCoros::instance().launch("putAgentUserInfoCoro", +            boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("notes", mCurrentNotes))); +    } +    else +    { +        LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; +    } + +    mSaveChanges->setEnabled(FALSE); +    mDiscardChanges->setEnabled(FALSE); +    mHasUnsavedChanges = false; +} + +void LLPanelProfileNotes::onDiscardNotesChanges() +{ +    setNotesText(mCurrentNotes); +} + +void LLPanelProfileNotes::processProperties(LLAvatarNotes* avatar_notes) +{ +    setNotesText(avatar_notes->notes); +    mNotesEditor->setEnabled(TRUE); +    setLoaded(); +} + +void LLPanelProfileNotes::resetData() +{ +    resetLoading(); +    setNotesText(std::string()); +} + +void LLPanelProfileNotes::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.notNull()) +    { +        LLPanelProfileTab::setAvatarId(avatar_id); +    } +} + + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfile + +LLPanelProfile::LLPanelProfile() + : LLPanelProfileTab() +{ +} + +LLPanelProfile::~LLPanelProfile() +{ +} + +BOOL LLPanelProfile::postBuild() +{ +    return TRUE; +} + +void LLPanelProfile::onTabChange() +{ +    LLPanelProfileTab* active_panel = dynamic_cast<LLPanelProfileTab*>(mTabContainer->getCurrentPanel()); +    if (active_panel) +    { +        active_panel->updateData(); +    }  }  void LLPanelProfile::onOpen(const LLSD& key)  { -	getTabContainer()[PANEL_PICKS]->onOpen(getAvatarId()); +    LLUUID avatar_id = key["id"].asUUID(); -	// support commands to open further pieces of UI -	if (key.has("show_tab_panel")) -	{ -		std::string panel = key["show_tab_panel"].asString(); -		if (panel == "create_classified") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				picks->createNewClassified(); -			} -		} -		else if (panel == "classified_details") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openClassifiedInfo(params); -			} -		} -		else if (panel == "edit_classified") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openClassifiedEdit(params); -			} -		} -		else if (panel == "create_pick") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				picks->createNewPick(); -			} -		} -		else if (panel == "edit_pick") -		{ -			LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); -			if (picks) -			{ -				LLSD params = key; -				params.erase("show_tab_panel"); -				params.erase("open_tab_name"); -				picks->openPickEdit(params); -			} -		} -	} +    // Don't reload the same profile +    if (getAvatarId() == avatar_id) +    { +        return; +    } + +    LLPanelProfileTab::onOpen(avatar_id); + +    mTabContainer       = getChild<LLTabContainer>("panel_profile_tabs"); +    mPanelSecondlife    = findChild<LLPanelProfileSecondLife>(PANEL_SECONDLIFE); +    mPanelWeb           = findChild<LLPanelProfileWeb>(PANEL_WEB); +    mPanelPicks         = findChild<LLPanelProfilePicks>(PANEL_PICKS); +    mPanelClassifieds   = findChild<LLPanelProfileClassifieds>(PANEL_CLASSIFIEDS); +    mPanelFirstlife     = findChild<LLPanelProfileFirstLife>(PANEL_FIRSTLIFE); +    mPanelNotes         = findChild<LLPanelProfileNotes>(PANEL_NOTES); + +    mPanelSecondlife->onOpen(avatar_id); +    mPanelWeb->onOpen(avatar_id); +    mPanelPicks->onOpen(avatar_id); +    mPanelClassifieds->onOpen(avatar_id); +    mPanelFirstlife->onOpen(avatar_id); +    mPanelNotes->onOpen(avatar_id); + +    // Always request the base profile info +    resetLoading(); +    updateData(); + +    // Some tabs only request data when opened +    mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this));  } -void LLPanelProfile::onTabSelected(const LLSD& param) +void LLPanelProfile::updateData()  { -	std::string tab_name = param.asString(); -	if (NULL != getTabContainer()[tab_name]) -	{ -		getTabContainer()[tab_name]->onOpen(getAvatarId()); -	} +    LLUUID avatar_id = getAvatarId(); +    // Todo: getIsloading functionality needs to be expanded to +    // include 'inited' or 'data_provided' state to not rerequest +    if (!getStarted() && avatar_id.notNull()) +    { +        setIsLoading(); + +        mPanelSecondlife->setIsLoading(); +        mPanelPicks->setIsLoading(); +        mPanelFirstlife->setIsLoading(); +        mPanelNotes->setIsLoading(); + +        std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); +        if (!cap_url.empty()) +        { +            LLCoros::instance().launch("requestAgentUserInfoCoro", +                boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); +        } +    }  } -void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params) +void LLPanelProfile::refreshName()  { -	// Hide currently visible panel (STORM-690). -	mChildStack.push(); +    mPanelSecondlife->refreshName(); +} -	// Add the panel or bring it to front. -	if (panel->getParent() != this) -	{ -		addChild(panel); -	} -	else -	{ -		sendChildToFront(panel); -	} +void LLPanelProfile::createPick(const LLPickData &data) +{ +    mTabContainer->selectTabPanel(mPanelPicks); +    mPanelPicks->createPick(data); +} -	panel->setVisible(TRUE); -	panel->setFocus(TRUE); // prevent losing focus by the floater -	panel->onOpen(params); +void LLPanelProfile::showPick(const LLUUID& pick_id) +{ +    if (pick_id.notNull()) +    { +        mPanelPicks->selectPick(pick_id); +    } +    mTabContainer->selectTabPanel(mPanelPicks); +} -	LLRect new_rect = getRect(); -	panel->reshape(new_rect.getWidth(), new_rect.getHeight()); -	new_rect.setLeftTopAndSize(0, new_rect.getHeight(), new_rect.getWidth(), new_rect.getHeight()); -	panel->setRect(new_rect); +bool LLPanelProfile::isPickTabSelected() +{ +	return (mTabContainer->getCurrentPanel() == mPanelPicks);  } -void LLPanelProfile::closePanel(LLPanel* panel) +bool LLPanelProfile::isNotesTabSelected()  { -	panel->setVisible(FALSE); +	return (mTabContainer->getCurrentPanel() == mPanelNotes); +} -	if (panel->getParent() == this)  -	{ -		removeChild(panel); +bool LLPanelProfile::hasUnsavedChanges() +{ +    return mPanelSecondlife->hasUnsavedChanges() +        || mPanelPicks->hasUnsavedChanges() +        || mPanelClassifieds->hasUnsavedChanges() +        || mPanelFirstlife->hasUnsavedChanges() +        || mPanelNotes->hasUnsavedChanges(); +} -		// Make the underlying panel visible. -		mChildStack.pop(); +bool LLPanelProfile::hasUnpublishedClassifieds() +{ +    return mPanelClassifieds->hasNewClassifieds(); +} -		// Prevent losing focus by the floater -		const child_list_t* child_list = getChildList(); -		if (child_list->size() > 0) -		{ -			child_list->front()->setFocus(TRUE); -		} -		else -		{ -			LL_WARNS() << "No underlying panel to focus." << LL_ENDL; -		} -	} +void LLPanelProfile::commitUnsavedChanges() +{ +    mPanelSecondlife->commitUnsavedChanges(); +    mPanelPicks->commitUnsavedChanges(); +    mPanelClassifieds->commitUnsavedChanges(); +    mPanelFirstlife->commitUnsavedChanges(); +    mPanelNotes->commitUnsavedChanges();  } -S32 LLPanelProfile::notifyParent(const LLSD& info) +void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit)  { -	std::string action = info["action"]; -	// lets update Picks list after Pick was saved -	if("save_new_pick" == action) -	{ -		onOpen(info); -		return 1; -	} +    if (classified_id.notNull()) +    { +        mPanelClassifieds->selectClassified(classified_id, edit); +    } +    mTabContainer->selectTabPanel(mPanelClassifieds); +} -	return LLPanel::notifyParent(info); +void LLPanelProfile::createClassified() +{ +    mPanelClassifieds->createClassified(); +    mTabContainer->selectTabPanel(mPanelClassifieds);  } + diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index d97f60ed22..ca6ef3f794 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -1,25 +1,25 @@ -/**  +/**  * @file llpanelprofile.h  * @brief Profile panel  * -* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* $LicenseInfo:firstyear=2022&license=viewerlgpl$  * Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -*  +* Copyright (C) 2022, 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$  */ @@ -27,76 +27,384 @@  #ifndef LL_LLPANELPROFILE_H  #define LL_LLPANELPROFILE_H +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" +#include "llfloater.h"  #include "llpanel.h"  #include "llpanelavatar.h" +#include "llmediactrl.h" +#include "llvoiceclient.h" + +// class LLPanelProfileClassifieds; +// class LLTabContainer; +// class LLPanelProfileSecondLife; +// class LLPanelProfileWeb; +// class LLPanelProfilePicks; +// class LLPanelProfileFirstLife; +// class LLPanelProfileNotes; + +class LLAvatarName; +class LLButton; +class LLCheckBoxCtrl; +class LLComboBox; +class LLIconCtrl;  class LLTabContainer; +class LLTextBox; +class LLTextureCtrl; +class LLMediaCtrl; +class LLGroupList; +class LLTextBase; +class LLMenuButton; +class LLLineEditor; +class LLTextEditor; +class LLPanelProfileClassifieds; +class LLPanelProfilePicks; +class LLViewerFetchedTexture; -std::string getProfileURL(const std::string& agent_name);  /** -* Base class for Profile View and My Profile. +* Panel for displaying Avatar's second life related info.  */ -class LLPanelProfile : public LLPanel +class LLPanelProfileSecondLife +	: public LLPanelProfileTab +	, public LLFriendObserver +	, public LLVoiceClientStatusObserver  { -	LOG_CLASS(LLPanelProfile); +public: +	LLPanelProfileSecondLife(); +	/*virtual*/ ~LLPanelProfileSecondLife(); + +	void onOpen(const LLSD& key) override; + +	/** +	 * LLFriendObserver trigger +	 */ +	void changed(U32 mask) override; + +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	void onChange(EStatusType status, const std::string &channelURI, bool proximal) override; + +	void setAvatarId(const LLUUID& avatar_id) override; + +	BOOL postBuild() override; + +	void resetData() override; + +	/** +	 * Sends update data request to server. +	 */ +	void updateData() override; +    void refreshName(); + +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +    void setProfileImageUploading(bool loading); +    void setProfileImageUploaded(const LLUUID &image_asset_id); + +    bool hasUnsavedChanges() override; +    void commitUnsavedChanges() override; + +    friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +protected: +	/** +	 * Process profile related data received from server. +	 */ +	void processProfileProperties(const LLAvatarData* avatar_data); + +	/** +	 * Processes group related data received from server. +	 */ +	void processGroupProperties(const LLAvatarGroups* avatar_groups); + +	/** +	 * Fills common for Avatar profile and My Profile fields. +	 */ +	void fillCommonData(const LLAvatarData* avatar_data); + +	/** +	 * Fills partner data. +	 */ +	void fillPartnerData(const LLAvatarData* avatar_data); +	/** +	 * Fills account status. +	 */ +	void fillAccountStatus(const LLAvatarData* avatar_data); + +    /** +     * Sets permissions specific icon +     */ +    void fillRightsData(); + +    /** +     * Fills user name, display name, age. +     */ +    void fillAgeData(const LLDate &born_on); + +    void onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep); +    static void onImageLoaded(BOOL success, +                              LLViewerFetchedTexture *src_vi, +                              LLImageRaw* src, +                              LLImageRaw* aux_src, +                              S32 discard_level, +                              BOOL final, +                              void* userdata); + +	/** +	 * Displays avatar's online status if possible. +	 * +	 * Requirements from EXT-3880: +	 * For friends: +	 * - Online when online and privacy settings allow to show +	 * - Offline when offline and privacy settings allow to show +	 * - Else: nothing +	 * For other avatars: +	 *	- Online when online and was not set in Preferences/"Only Friends & Groups can see when I am online" +	 *	- Else: Offline +	 */ +	void updateOnlineStatus(); +	void processOnlineStatus(bool is_friend, bool show_online, bool online); + +private: +    void setLoaded() override; +    void onCommitMenu(const LLSD& userdata); +    bool onEnableMenu(const LLSD& userdata); +    bool onCheckMenu(const LLSD& userdata); +	void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name); + +    void setDescriptionText(const std::string &text); +    void onSetDescriptionDirty(); +    void onShowInSearchCallback(); +    void onSaveDescriptionChanges(); +    void onDiscardDescriptionChanges(); +    void onShowAgentPermissionsDialog(); +    void onShowAgentProfileTexture(); +    void onShowTexturePicker(); +    void onCommitProfileImage(const LLUUID& id); +    void onOpenNotes(); + +private: +	typedef std::map<std::string, LLUUID> group_map_t; +	group_map_t				mGroups; +	void					openGroupProfile(); + +	LLGroupList*		mGroupList; +    LLComboBox*			mShowInSearchCombo; +    LLIconCtrl*			mSecondLifePic; +	LLPanel*			mSecondLifePicLayout; +    LLTextEditor*		mDescriptionEdit; +    LLMenuButton*		mAgentActionMenuButton; +    LLButton*			mSaveDescriptionChanges; +    LLButton*			mDiscardDescriptionChanges; +    LLIconCtrl*			mCanSeeOnlineIcon; +    LLIconCtrl*			mCantSeeOnlineIcon; +    LLIconCtrl*			mCanSeeOnMapIcon; +    LLIconCtrl*			mCantSeeOnMapIcon; +    LLIconCtrl*			mCanEditObjectsIcon; +    LLIconCtrl*			mCantEditObjectsIcon; + +    LLHandle<LLFloater>	mFloaterPermissionsHandle; +    LLHandle<LLFloater>	mFloaterProfileTextureHandle; +    LLHandle<LLFloater>	mFloaterTexturePickerHandle; + +    bool				mHasUnsavedDescriptionChanges; +	bool				mVoiceStatus; +    bool				mWaitingForImageUpload; +    bool				mAllowPublish; +    std::string			mDescriptionText; +    LLUUID				mImageId; + +	boost::signals2::connection	mAvatarNameCacheConnection; +}; + + +/** +* Panel for displaying Avatar's web profile and home page. +*/ +class LLPanelProfileWeb +	: public LLPanelProfileTab +	, public LLViewerMediaObserver +{  public: -	/*virtual*/ BOOL postBuild(); -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); -	/*virtual*/ void onOpen(const LLSD& key); +	LLPanelProfileWeb(); +	/*virtual*/ ~LLPanelProfileWeb(); + +	void onOpen(const LLSD& key) override; + +	BOOL postBuild() override; -	virtual void openPanel(LLPanel* panel, const LLSD& params); +	void resetData() override; -	virtual void closePanel(LLPanel* panel); +	/** +	 * Loads web profile. +	 */ +	void updateData() override; -	S32 notifyParent(const LLSD& info); +	void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; + +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + +    friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id);  protected: +	void onCommitLoad(LLUICtrl* ctrl); -	LLPanelProfile(); +private: +	std::string			mURLHome; +	std::string			mURLWebProfile; +	LLMediaCtrl*		mWebBrowser; -	virtual void onTabSelected(const LLSD& param); +	LLFrameTimer		mPerformanceTimer; +	bool				mFirstNavigate; -	const LLUUID& getAvatarId() { return mAvatarId; } +	boost::signals2::connection	mAvatarNameCacheConnection; +}; + +/** +* Panel for displaying Avatar's first life related info. +*/ +class LLPanelProfileFirstLife +	: public LLPanelProfileTab +{ +public: +	LLPanelProfileFirstLife(); +	/*virtual*/ ~LLPanelProfileFirstLife(); + +	void onOpen(const LLSD& key) override; + +	BOOL postBuild() override; + +    void processProperties(const LLAvatarData* avatar_data); + +	void resetData() override; + +    void setProfileImageUploading(bool loading); +    void setProfileImageUploaded(const LLUUID &image_asset_id); + +    bool hasUnsavedChanges() override { return mHasUnsavedChanges; } +    void commitUnsavedChanges() override; + +    friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +protected: +	void setLoaded() override; + +    void onUploadPhoto(); +    void onChangePhoto(); +    void onRemovePhoto(); +    void onCommitPhoto(const LLUUID& id); +    void setDescriptionText(const std::string &text); +    void onSetDescriptionDirty(); +    void onSaveDescriptionChanges(); +    void onDiscardDescriptionChanges(); + +	LLTextEditor*	mDescriptionEdit; +    LLIconCtrl*		mPicture; +    LLButton* mUploadPhoto; +    LLButton* mChangePhoto; +    LLButton* mRemovePhoto; +    LLButton* mSaveChanges; +    LLButton* mDiscardChanges; + +    LLHandle<LLFloater>	mFloaterTexturePickerHandle; + +    std::string		mCurrentDescription; +    LLUUID			mImageId; +    bool			mHasUnsavedChanges; +}; + +/** + * Panel for displaying Avatar's notes and modifying friend's rights. + */ +class LLPanelProfileNotes +	: public LLPanelProfileTab +{ +public: +	LLPanelProfileNotes(); +	/*virtual*/ ~LLPanelProfileNotes(); -	void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } +	void setAvatarId(const LLUUID& avatar_id) override; -	typedef std::map<std::string, LLPanelProfileTab*> profile_tabs_t; +	void onOpen(const LLSD& key) override; -	profile_tabs_t& getTabContainer() { return mTabContainer; } +	BOOL postBuild() override; + +    void processProperties(LLAvatarNotes* avatar_notes); + +	void resetData() override; + +	void updateData() override; + +    bool hasUnsavedChanges() override { return mHasUnsavedChanges; } +    void commitUnsavedChanges() override; + +protected: +    void setNotesText(const std::string &text); +    void onSetNotesDirty(); +    void onSaveNotesChanges(); +    void onDiscardNotesChanges(); + +	LLTextEditor*       mNotesEditor; +    LLButton* mSaveChanges; +    LLButton* mDiscardChanges; + +    std::string		mCurrentNotes; +    bool			mHasUnsavedChanges; +}; + + +/** +* Container panel for the profile tabs +*/ +class LLPanelProfile +    : public LLPanelProfileTab +{ +public: +    LLPanelProfile(); +    /*virtual*/ ~LLPanelProfile(); + +    BOOL postBuild() override; + +    void updateData() override; +    void refreshName(); + +    void onOpen(const LLSD& key) override; + +    void createPick(const LLPickData &data); +    void showPick(const LLUUID& pick_id = LLUUID::null); +    bool isPickTabSelected(); +    bool isNotesTabSelected(); +    bool hasUnsavedChanges() override; +    bool hasUnpublishedClassifieds(); +    void commitUnsavedChanges() override; + +    void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); +    void createClassified(); + +    LLAvatarData getAvatarData() { return mAvatarData; }; + +    friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id);  private: +    void onTabChange(); + +    LLPanelProfileSecondLife*   mPanelSecondlife; +    LLPanelProfileWeb*          mPanelWeb; +    LLPanelProfilePicks*        mPanelPicks; +    LLPanelProfileClassifieds*  mPanelClassifieds; +    LLPanelProfileFirstLife*    mPanelFirstlife; +    LLPanelProfileNotes*        mPanelNotes; +    LLTabContainer*             mTabContainer; -	//-- ChildStack begins ---------------------------------------------------- -	class ChildStack -	{ -		LOG_CLASS(LLPanelProfile::ChildStack); -	public: -		ChildStack(); -		~ChildStack(); -		void setParent(LLPanel* parent); - -		bool push(); -		bool pop(); -		void preParentReshape(); -		void postParentReshape(); - -	private: -		void dump(); - -		typedef LLView::child_list_t view_list_t; -		typedef std::list<view_list_t> stack_t; - -		stack_t		mStack; -		stack_t		mSavedStack; -		LLPanel*	mParent; -	}; -	//-- ChildStack ends ------------------------------------------------------ - -	profile_tabs_t mTabContainer; -	ChildStack		mChildStack; -	LLUUID mAvatarId; +    // Todo: due to server taking minutes to update this needs a more long term storage +    // to reuse recently saved values if user opens floater again +    // Storage implementation depends onto how a cap will be implemented, if cap will be +    // enought to fully update LLAvatarPropertiesProcessor, then this storage can be +    // implemented there. +    LLAvatarData mAvatarData;  };  #endif //LL_LLPANELPROFILE_H diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp new file mode 100644 index 0000000000..a3913ddc49 --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -0,0 +1,1513 @@ +/** + * @file llpanelprofileclassifieds.cpp + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelprofileclassifieds.h" + +#include "llagent.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedflags.h" +#include "llcombobox.h" +#include "llcommandhandler.h" // for classified HTML detail page click tracking +#include "llcorehttputil.h" +#include "lldispatcher.h" +#include "llfloaterclassified.h" +#include "llfloaterreg.h" +#include "llfloatersidepanelcontainer.h" +#include "llfloaterworldmap.h" +#include "lliconctrl.h" +#include "lllineeditor.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llparcel.h" +#include "llregistry.h" +#include "llscrollcontainer.h" +#include "llstartup.h" +#include "llstatusbar.h" +#include "lltabcontainer.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewertexture.h" +#include "llviewertexture.h" + + +//*TODO: verify this limit +const S32 MAX_AVATAR_CLASSIFIEDS = 100; + +const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$ +const S32 DEFAULT_EDIT_CLASSIFIED_SCROLL_HEIGHT = 530; + +//static +LLPanelProfileClassified::panel_list_t LLPanelProfileClassified::sAllPanels; + +static LLPanelInjector<LLPanelProfileClassifieds> t_panel_profile_classifieds("panel_profile_classifieds"); +static LLPanelInjector<LLPanelProfileClassified> t_panel_profile_classified("panel_profile_classified"); + +class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesObserver +{ +public: +    // throttle calls from untrusted browsers +    LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} +	 +	std::set<LLUUID> mClassifiedIds; +	std::string mRequestVerb; +     +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +    { +        if (LLStartUp::getStartupState() < STATE_STARTED) +        { +            return true; +        } + +        if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds")) +        { +            LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); +            return true; +        } + +        // handle app/classified/create urls first +        if (params.size() == 1 && params[0].asString() == "create") +        { +            LLAvatarActions::createClassified(); +            return true; +        } + +        // then handle the general app/classified/{UUID}/{CMD} urls +        if (params.size() < 2) +        { +            return false; +        } + +        // get the ID for the classified +        LLUUID classified_id; +        if (!classified_id.set(params[0], FALSE)) +        { +            return false; +        } + +        // show the classified in the side tray. +        // need to ask the server for more info first though... +        const std::string verb = params[1].asString(); +        if (verb == "about") +        { +            mRequestVerb = verb; +            mClassifiedIds.insert(classified_id); +            LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); +            LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); +            return true; +        } +        else if (verb == "edit") +        { +            LLAvatarActions::showClassified(gAgent.getID(), classified_id, true); +            return true; +        } + +        return false; +    } + +    void openClassified(LLAvatarClassifiedInfo* c_info) +    { +        if (mRequestVerb == "about") +        { +            if (c_info->creator_id == gAgent.getID()) +            { +                LLAvatarActions::showClassified(gAgent.getID(), c_info->classified_id, false); +            } +            else +            { +                LLSD params; +                params["id"] = c_info->creator_id; +                params["classified_id"] = c_info->classified_id; +                params["classified_creator_id"] = c_info->creator_id; +                params["classified_snapshot_id"] = c_info->snapshot_id; +                params["classified_name"] = c_info->name; +                params["classified_desc"] = c_info->description; +                params["from_search"] = true; + +                LLFloaterClassified* floaterp = LLFloaterReg::getTypedInstance<LLFloaterClassified>("classified", params); +                if (floaterp) +                { +                    floaterp->openFloater(params); +                    floaterp->setVisibleAndFrontmost(); +                } +            } +        } +    } + +    void processProperties(void* data, EAvatarProcessorType type) +    { +        if (APT_CLASSIFIED_INFO != type) +        { +            return; +        } + +        // is this the classified that we asked for? +        LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); +        if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end()) +        { +            return; +        } + +        // open the detail side tray for this classified +        openClassified(c_info); + +        // remove our observer now that we're done +        mClassifiedIds.erase(c_info->classified_id); +        LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); +    } +}; +LLClassifiedHandler gClassifiedHandler; + +////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassifieds +//----------------------------------------------------------------------------- + +LLPanelProfileClassifieds::LLPanelProfileClassifieds() + : LLPanelProfilePropertiesProcessorTab() + , mClassifiedToSelectOnLoad(LLUUID::null) + , mClassifiedEditOnLoad(false) + , mSheduledClassifiedCreation(false) +{ +} + +LLPanelProfileClassifieds::~LLPanelProfileClassifieds() +{ +} + +void LLPanelProfileClassifieds::onOpen(const LLSD& key) +{ +    LLPanelProfilePropertiesProcessorTab::onOpen(key); + +    resetData(); + +    bool own_profile = getSelfProfile(); +    if (own_profile) +    { +        mNewButton->setVisible(TRUE); +        mNewButton->setEnabled(FALSE); + +        mDeleteButton->setVisible(TRUE); +        mDeleteButton->setEnabled(FALSE); +    } + +    childSetVisible("buttons_header", own_profile); + +} + +void LLPanelProfileClassifieds::selectClassified(const LLUUID& classified_id, bool edit) +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (classified_panel) +            { +                if (classified_panel->getClassifiedId() == classified_id) +                { +                    mTabContainer->selectTabPanel(classified_panel); +                    if (edit) +                    { +                        classified_panel->setEditMode(TRUE); +                    } +                    break; +                } +            } +        } +    } +    else +    { +        mClassifiedToSelectOnLoad = classified_id; +        mClassifiedEditOnLoad = edit; +    } +} + +void LLPanelProfileClassifieds::createClassified() +{ +    if (getIsLoaded()) +    { +        mNoItemsLabel->setVisible(FALSE); +        LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); +        classified_panel->onOpen(LLSD()); +        mTabContainer->addTabPanel( +            LLTabContainer::TabPanelParams(). +            panel(classified_panel). +            select_tab(true). +            label(classified_panel->getClassifiedName())); +        updateButtons(); +    } +    else +    { +        mSheduledClassifiedCreation = true; +    } +} + +BOOL LLPanelProfileClassifieds::postBuild() +{ +    mTabContainer = getChild<LLTabContainer>("tab_classifieds"); +    mNoItemsLabel = getChild<LLUICtrl>("classifieds_panel_text"); +    mNewButton = getChild<LLButton>("new_btn"); +    mDeleteButton = getChild<LLButton>("delete_btn"); + +    mNewButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickNewBtn, this)); +    mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfileClassifieds::onClickDelete, this)); + +    return TRUE; +} + +void LLPanelProfileClassifieds::onClickNewBtn() +{ +    mNoItemsLabel->setVisible(FALSE); +    LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); +    classified_panel->onOpen(LLSD()); +    mTabContainer->addTabPanel( +        LLTabContainer::TabPanelParams(). +        panel(classified_panel). +        select_tab(true). +        label(classified_panel->getClassifiedName())); +    updateButtons(); +} + +void LLPanelProfileClassifieds::onClickDelete() +{ +    LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getCurrentPanel()); +    if (classified_panel) +    { +        LLUUID classified_id = classified_panel->getClassifiedId(); +        LLSD args; +        args["CLASSIFIED"] = classified_panel->getClassifiedName(); +        LLSD payload; +        payload["classified_id"] = classified_id; +        payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); +        LLNotificationsUtil::add("ProfileDeleteClassified", args, payload, +            boost::bind(&LLPanelProfileClassifieds::callbackDeleteClassified, this, _1, _2)); +    } +} + +void LLPanelProfileClassifieds::callbackDeleteClassified(const LLSD& notification, const LLSD& response) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + +    if (0 == option) +    { +        LLUUID classified_id = notification["payload"]["classified_id"].asUUID(); +        S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + +        LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (classified_panel && classified_panel->getClassifiedId() == classified_id) +        { +            mTabContainer->removeTabPanel(classified_panel); +        } + +        if (classified_id.notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->sendClassifiedDelete(classified_id); +        } + +        updateButtons(); + +        BOOL no_data = !mTabContainer->getTabCount(); +        mNoItemsLabel->setVisible(no_data); +    } +} + +void LLPanelProfileClassifieds::processProperties(void* data, EAvatarProcessorType type) +{ +    if ((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type)) +    { +        LLUUID avatar_id = getAvatarId(); + +        LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); +        if (c_info && getAvatarId() == c_info->target_id) +        { +            // do not clear classified list in case we will receive two or more data packets. +            // list has been cleared in updateData(). (fix for EXT-6436) +            LLUUID selected_id = mClassifiedToSelectOnLoad; +            bool has_selection = false; + +            LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); +            for (; c_info->classifieds_list.end() != it; ++it) +            { +                LLAvatarClassifieds::classified_data c_data = *it; + +                LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); + +                LLSD params; +                params["classified_creator_id"] = avatar_id; +                params["classified_id"] = c_data.classified_id; +                params["classified_name"] = c_data.name; +                params["from_search"] = (selected_id == c_data.classified_id); //SLURL handling and stats tracking +                params["edit"] = (selected_id == c_data.classified_id) && mClassifiedEditOnLoad; +                classified_panel->onOpen(params); + +                mTabContainer->addTabPanel( +                    LLTabContainer::TabPanelParams(). +                    panel(classified_panel). +                    select_tab(selected_id == c_data.classified_id). +                    label(c_data.name)); + +                if (selected_id == c_data.classified_id) +                { +                    has_selection = true; +                } +            } + +            if (mSheduledClassifiedCreation) +            { +                LLPanelProfileClassified* classified_panel = LLPanelProfileClassified::create(); +                classified_panel->onOpen(LLSD()); +                mTabContainer->addTabPanel( +                    LLTabContainer::TabPanelParams(). +                    panel(classified_panel). +                    select_tab(!has_selection). +                    label(classified_panel->getClassifiedName())); +                has_selection = true; +            } + +            // reset 'do on load' values +            mClassifiedToSelectOnLoad = LLUUID::null; +            mClassifiedEditOnLoad = false; +            mSheduledClassifiedCreation = false; + +            // set even if not visible, user might delete own +            // calassified and this string will need to be shown +            if (getSelfProfile()) +            { +                mNoItemsLabel->setValue(LLTrans::getString("NoClassifiedsText")); +            } +            else +            { +                mNoItemsLabel->setValue(LLTrans::getString("NoAvatarClassifiedsText")); +            } + +            bool has_data = mTabContainer->getTabCount() > 0; +            mNoItemsLabel->setVisible(!has_data); +            if (has_data && !has_selection) +            { +                mTabContainer->selectFirstTab(); +            } + +            setLoaded(); +            updateButtons(); +        } +    } +} + +void LLPanelProfileClassifieds::resetData() +{ +    resetLoading(); +    mTabContainer->deleteAllTabs(); +} + +void LLPanelProfileClassifieds::updateButtons() +{ +    if (getSelfProfile()) +    { +        mNewButton->setEnabled(canAddNewClassified()); +        mDeleteButton->setEnabled(canDeleteClassified()); +    } +} + +void LLPanelProfileClassifieds::updateData() +{ +    // Send picks request only once +    LLUUID avatar_id = getAvatarId(); +    if (!getStarted() && avatar_id.notNull()) +    { +        setIsLoading(); +        mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); +        mNoItemsLabel->setVisible(TRUE); + +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(avatar_id); +    } +} + +bool LLPanelProfileClassifieds::hasNewClassifieds() +{ +    for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +    { +        LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (classified_panel && classified_panel->isNew()) +        { +            return true; +        } +    } +    return false; +} + +bool LLPanelProfileClassifieds::hasUnsavedChanges() +{ +    for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +    { +        LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (classified_panel && classified_panel->isDirty()) // includes 'new' +        { +            return true; +        } +    } +    return false; +} + +bool LLPanelProfileClassifieds::canAddNewClassified() +{ +    return (mTabContainer->getTabCount() < MAX_AVATAR_CLASSIFIEDS); +} + +bool LLPanelProfileClassifieds::canDeleteClassified() +{ +    return (mTabContainer->getTabCount() > 0); +} + +void LLPanelProfileClassifieds::commitUnsavedChanges() +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfileClassified* classified_panel = dynamic_cast<LLPanelProfileClassified*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (classified_panel && classified_panel->isDirty() && !classified_panel->isNew()) +            { +                classified_panel->doSave(); +            } +        } +    } +} +//----------------------------------------------------------------------------- +// LLDispatchClassifiedClickThrough +//----------------------------------------------------------------------------- + +// "classifiedclickthrough" +// strings[0] = classified_id +// strings[1] = teleport_clicks +// strings[2] = map_clicks +// strings[3] = profile_clicks +class LLDispatchClassifiedClickThrough : public LLDispatchHandler +{ +public: +    virtual bool operator()( +        const LLDispatcher* dispatcher, +        const std::string& key, +        const LLUUID& invoice, +        const sparam_t& strings) +    { +        if (strings.size() != 4) return false; +        LLUUID classified_id(strings[0]); +        S32 teleport_clicks = atoi(strings[1].c_str()); +        S32 map_clicks = atoi(strings[2].c_str()); +        S32 profile_clicks = atoi(strings[3].c_str()); + +        LLPanelProfileClassified::setClickThrough( +            classified_id, teleport_clicks, map_clicks, profile_clicks, false); + +        return true; +    } +}; +static LLDispatchClassifiedClickThrough sClassifiedClickThrough; + + +//----------------------------------------------------------------------------- +// LLPanelProfileClassified +//----------------------------------------------------------------------------- + +static const S32 CB_ITEM_MATURE = 0; +static const S32 CB_ITEM_PG    = 1; + +LLPanelProfileClassified::LLPanelProfileClassified() + : LLPanelProfilePropertiesProcessorTab() + , mInfoLoaded(false) + , mTeleportClicksOld(0) + , mMapClicksOld(0) + , mProfileClicksOld(0) + , mTeleportClicksNew(0) + , mMapClicksNew(0) + , mProfileClicksNew(0) + , mPriceForListing(0) + , mSnapshotCtrl(NULL) + , mPublishFloater(NULL) + , mIsNew(false) + , mIsNewWithErrors(false) + , mCanClose(false) + , mEditMode(false) + , mEditOnLoad(false) +{ +    sAllPanels.push_back(this); +} + +LLPanelProfileClassified::~LLPanelProfileClassified() +{ +    sAllPanels.remove(this); +    gGenericDispatcher.addHandler("classifiedclickthrough", NULL); // deregister our handler +} + +//static +LLPanelProfileClassified* LLPanelProfileClassified::create() +{ +    LLPanelProfileClassified* panel = new LLPanelProfileClassified(); +    panel->buildFromFile("panel_profile_classified.xml"); +    return panel; +} + +BOOL LLPanelProfileClassified::postBuild() +{ +    mScrollContainer    = getChild<LLScrollContainer>("profile_scroll"); +    mInfoPanel          = getChild<LLView>("info_panel"); +    mInfoScroll         = getChild<LLPanel>("info_scroll_content_panel"); +    mEditPanel          = getChild<LLPanel>("edit_panel"); + +    mSnapshotCtrl       = getChild<LLTextureCtrl>("classified_snapshot"); +    mEditIcon           = getChild<LLUICtrl>("edit_icon"); + +    //info +    mClassifiedNameText = getChild<LLUICtrl>("classified_name"); +    mClassifiedDescText = getChild<LLTextEditor>("classified_desc"); +    mLocationText       = getChild<LLUICtrl>("classified_location"); +    mCategoryText       = getChild<LLUICtrl>("category"); +    mContentTypeText    = getChild<LLUICtrl>("content_type"); +    mContentTypeM       = getChild<LLIconCtrl>("content_type_moderate"); +    mContentTypeG       = getChild<LLIconCtrl>("content_type_general"); +    mPriceText          = getChild<LLUICtrl>("price_for_listing"); +    mAutoRenewText      = getChild<LLUICtrl>("auto_renew"); + +    mMapButton          = getChild<LLButton>("show_on_map_btn"); +    mTeleportButton     = getChild<LLButton>("teleport_btn"); +    mEditButton         = getChild<LLButton>("edit_btn"); + +    //edit +    mClassifiedNameEdit = getChild<LLLineEditor>("classified_name_edit"); +    mClassifiedDescEdit = getChild<LLTextEditor>("classified_desc_edit"); +    mLocationEdit       = getChild<LLUICtrl>("classified_location_edit"); +    mCategoryCombo      = getChild<LLComboBox>("category_edit"); +    mContentTypeCombo   = getChild<LLComboBox>("content_type_edit"); +    mAutoRenewEdit      = getChild<LLUICtrl>("auto_renew_edit"); + +    mSaveButton         = getChild<LLButton>("save_changes_btn"); +    mSetLocationButton  = getChild<LLButton>("set_to_curr_location_btn"); +    mCancelButton       = getChild<LLButton>("cancel_btn"); + +    mUtilityBtnCnt = getChild<LLPanel>("util_buttons_lp"); +    mPublishBtnsCnt = getChild<LLPanel>("publish_layout_panel"); +    mCancelBtnCnt = getChild<LLPanel>("cancel_btn_lp"); +    mSaveBtnCnt = getChild<LLPanel>("save_btn_lp"); + +    mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelProfileClassified::onTextureSelected, this)); +    mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseEnter, this)); +    mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelProfileClassified::onTexturePickerMouseLeave, this)); +    mEditIcon->setVisible(false); + +    mMapButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onMapClick, this)); +    mTeleportButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onTeleportClick, this)); +    mEditButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onEditClick, this)); +    mSaveButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSaveClick, this)); +    mSetLocationButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onSetLocationClick, this)); +    mCancelButton->setCommitCallback(boost::bind(&LLPanelProfileClassified::onCancelClick, this)); + +    LLClassifiedInfo::cat_map::iterator iter; +    for (iter = LLClassifiedInfo::sCategories.begin(); +        iter != LLClassifiedInfo::sCategories.end(); +        iter++) +    { +        mCategoryCombo->add(LLTrans::getString(iter->second)); +    } + +    mClassifiedNameEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this), NULL); +    mClassifiedDescEdit->setKeystrokeCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mCategoryCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mContentTypeCombo->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); +    mAutoRenewEdit->setCommitCallback(boost::bind(&LLPanelProfileClassified::onChange, this)); + +    return TRUE; +} + +void LLPanelProfileClassified::onOpen(const LLSD& key) +{ +    mIsNew = key.isUndefined(); + +    resetData(); +    resetControls(); +    scrollToTop(); + +    // classified is not created yet +    bool is_new = isNew() || isNewWithErrors(); + +    if(is_new) +    { +        LLPanelProfilePropertiesProcessorTab::setAvatarId(gAgent.getID()); + +        setPosGlobal(gAgent.getPositionGlobal()); + +        LLUUID snapshot_id = LLUUID::null; +        std::string desc; +        LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +        if(parcel) +        { +            desc = parcel->getDesc(); +            snapshot_id = parcel->getSnapshotID(); +        } + +        std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); +        LLViewerRegion* region = gAgent.getRegion(); +        if (region) +        { +            region_name = region->getName(); +        } + +        setClassifiedName(makeClassifiedName()); +        setDescription(desc); +        setSnapshotId(snapshot_id); +        setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); +        // server will set valid parcel id +        setParcelId(LLUUID::null); + +        mSaveButton->setLabelArg("[LABEL]", getString("publish_label")); + +        setEditMode(TRUE); +        enableSave(true); +        enableEditing(true); +        resetDirty(); +        setInfoLoaded(false); +    } +    else +    { +        LLUUID avatar_id = key["classified_creator_id"]; +        if(avatar_id.isNull()) +        { +            return; +        } +        LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + +        setClassifiedId(key["classified_id"]); +        setClassifiedName(key["classified_name"]); +        setFromSearch(key["from_search"]); +        mEditOnLoad = key["edit"]; + +        LL_INFOS() << "Opening classified [" << getClassifiedName() << "] (" << getClassifiedId() << ")" << LL_ENDL; + +        LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + +        gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); + +        if (gAgent.getRegion()) +        { +            // While we're at it let's get the stats from the new table if that +            // capability exists. +            std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); +            if (!url.empty()) +            { +                LL_INFOS() << "Classified stat request via capability" << LL_ENDL; +                LLSD body; +                LLUUID classifiedId = getClassifiedId(); +                body["classified_id"] = classifiedId; +                LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, +                    boost::bind(&LLPanelProfileClassified::handleSearchStatResponse, classifiedId, _1)); +            } +        } +        // Update classified click stats. +        // *TODO: Should we do this when opening not from search? +        if (!fromSearch() ) +        { +            sendClickMessage("profile"); +        } + +        setInfoLoaded(false); +    } + + +    bool is_self = getSelfProfile(); +    getChildView("auto_renew_layout_panel")->setVisible(is_self); +    getChildView("clickthrough_layout_panel")->setVisible(is_self); + +    updateButtons(); +} + +void LLPanelProfileClassified::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_CLASSIFIED_INFO != type) +    { +        return; +    } + +    LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); +    if(c_info && getClassifiedId() == c_info->classified_id) +    { +        // see LLPanelProfileClassified::sendUpdate() for notes +        if (mIsNewWithErrors) +        { +            // We just published it +            setEditMode(FALSE); +        } +        mIsNewWithErrors = false; +        mIsNew = false; + +        setClassifiedName(c_info->name); +        setDescription(c_info->description); +        setSnapshotId(c_info->snapshot_id); +        setParcelId(c_info->parcel_id); +        setPosGlobal(c_info->pos_global); +        setSimName(c_info->sim_name); + +        setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); + +        mCategoryText->setValue(LLClassifiedInfo::sCategories[c_info->category]); +        // *HACK see LLPanelProfileClassified::sendUpdate() +        setCategory(c_info->category - 1); + +        bool mature = is_cf_mature(c_info->flags); +        setContentType(mature); + +        bool auto_renew = is_cf_auto_renew(c_info->flags); +        std::string auto_renew_str = auto_renew ? getString("auto_renew_on") : getString("auto_renew_off"); +        mAutoRenewText->setValue(auto_renew_str); +        mAutoRenewEdit->setValue(auto_renew); + +        static LLUIString  price_str = getString("l$_price"); +        price_str.setArg("[PRICE]", llformat("%d", c_info->price_for_listing)); +        mPriceText->setValue(LLSD(price_str)); + +        static std::string date_fmt = getString("date_fmt"); +        std::string date_str = date_fmt; +        LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date)); +        getChild<LLUICtrl>("creation_date")->setValue(date_str); + +        resetDirty(); +        setInfoLoaded(true); +        enableSave(false); +        enableEditing(true); + +        // for just created classified - in case user opened edit panel before processProperties() callback +        mSaveButton->setLabelArg("[LABEL]", getString("save_label")); + +        setLoaded(); +        updateButtons(); + +        if (mEditOnLoad) +        { +            setEditMode(TRUE); +        } +    } + +} + +void LLPanelProfileClassified::setEditMode(BOOL edit_mode) +{ +    mEditMode = edit_mode; + +    mInfoPanel->setVisible(!edit_mode); +    mEditPanel->setVisible(edit_mode); + +    // snapshot control is common between info and edit, +    // enable it only when in edit mode +    mSnapshotCtrl->setEnabled(edit_mode); + +    scrollToTop(); +    updateButtons(); +    updateInfoRect(); +} + +void LLPanelProfileClassified::updateButtons() +{ +    bool edit_mode = getEditMode(); +    mUtilityBtnCnt->setVisible(!edit_mode); + +    // cancel button should either delete unpublished +    // classified or not be there at all +    mCancelBtnCnt->setVisible(edit_mode && !mIsNew); +    mPublishBtnsCnt->setVisible(edit_mode); +    mSaveBtnCnt->setVisible(edit_mode); +    mEditButton->setVisible(!edit_mode && getSelfProfile()); +} + +void LLPanelProfileClassified::updateInfoRect() +{ +    if (getEditMode()) +    { +        // info_scroll_content_panel contains both info and edit panel +        // info panel can be very large and scroll bar will carry over. +        // Resize info panel to prevent scroll carry over when in edit mode. +        mInfoScroll->reshape(mInfoScroll->getRect().getWidth(), DEFAULT_EDIT_CLASSIFIED_SCROLL_HEIGHT, FALSE); +    } +    else +    { +        // Adjust text height to make description scrollable. +        S32 new_height = mClassifiedDescText->getTextBoundingRect().getHeight(); +        LLRect visible_rect = mClassifiedDescText->getVisibleDocumentRect(); +        S32 delta_height = new_height - visible_rect.getHeight() + 5; + +        LLRect rect = mInfoScroll->getRect(); +        mInfoScroll->reshape(rect.getWidth(), rect.getHeight() + delta_height, FALSE); +    } +} + +void LLPanelProfileClassified::enableEditing(bool enable) +{ +    mEditButton->setEnabled(enable); +    mClassifiedNameEdit->setEnabled(enable); +    mClassifiedDescEdit->setEnabled(enable); +    mSetLocationButton->setEnabled(enable); +    mCategoryCombo->setEnabled(enable); +    mContentTypeCombo->setEnabled(enable); +    mAutoRenewEdit->setEnabled(enable); +} + +void LLPanelProfileClassified::resetControls() +{ +    updateButtons(); + +    mCategoryCombo->setCurrentByIndex(0); +    mContentTypeCombo->setCurrentByIndex(0); +    mAutoRenewEdit->setValue(false); +    mPriceForListing = MINIMUM_PRICE_FOR_LISTING; +} + +void LLPanelProfileClassified::onEditClick() +{ +    setEditMode(TRUE); +} + +void LLPanelProfileClassified::onCancelClick() +{ +    if (isNew()) +    { +        mClassifiedNameEdit->setValue(mClassifiedNameText->getValue()); +        mClassifiedDescEdit->setValue(mClassifiedDescText->getValue()); +        mLocationEdit->setValue(mLocationText->getValue()); +        mCategoryCombo->setCurrentByIndex(0); +        mContentTypeCombo->setCurrentByIndex(0); +        mAutoRenewEdit->setValue(false); +        mPriceForListing = MINIMUM_PRICE_FOR_LISTING; +    } +    else +    { +        // Reload data to undo changes to forms +        LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); +    } + +    setInfoLoaded(false); + +    setEditMode(FALSE); +} + +void LLPanelProfileClassified::onSaveClick() +{ +    mCanClose = false; + +    if(!isValidName()) +    { +        notifyInvalidName(); +        return; +    } +    if(isNew() || isNewWithErrors()) +    { +        if(gStatusBar->getBalance() < getPriceForListing()) +        { +            LLNotificationsUtil::add("ClassifiedInsufficientFunds"); +            return; +        } + +        mPublishFloater = LLFloaterReg::findTypedInstance<LLPublishClassifiedFloater>( +            "publish_classified", LLSD()); + +        if(!mPublishFloater) +        { +            mPublishFloater = LLFloaterReg::getTypedInstance<LLPublishClassifiedFloater>( +                "publish_classified", LLSD()); + +            mPublishFloater->setPublishClickedCallback(boost::bind +                (&LLPanelProfileClassified::onPublishFloaterPublishClicked, this)); +        } + +        // set spinner value before it has focus or value wont be set +        mPublishFloater->setPrice(getPriceForListing()); +        mPublishFloater->openFloater(mPublishFloater->getKey()); +        mPublishFloater->center(); +    } +    else +    { +        doSave(); +    } +} + +/*static*/ +void LLPanelProfileClassified::handleSearchStatResponse(LLUUID classifiedId, LLSD result) +{ +    S32 teleport = result["teleport_clicks"].asInteger(); +    S32 map = result["map_clicks"].asInteger(); +    S32 profile = result["profile_clicks"].asInteger(); +    S32 search_teleport = result["search_teleport_clicks"].asInteger(); +    S32 search_map = result["search_map_clicks"].asInteger(); +    S32 search_profile = result["search_profile_clicks"].asInteger(); + +    LLPanelProfileClassified::setClickThrough(classifiedId, +        teleport + search_teleport, +        map + search_map, +        profile + search_profile, +        true); +} + +void LLPanelProfileClassified::resetData() +{ +    setClassifiedName(LLStringUtil::null); +    setDescription(LLStringUtil::null); +    setClassifiedLocation(LLStringUtil::null); +    setClassifiedId(LLUUID::null); +    setSnapshotId(LLUUID::null); +    setPosGlobal(LLVector3d::zero); +    setParcelId(LLUUID::null); +    setSimName(LLStringUtil::null); +    setFromSearch(false); + +    // reset click stats +    mTeleportClicksOld  = 0; +    mMapClicksOld       = 0; +    mProfileClicksOld   = 0; +    mTeleportClicksNew  = 0; +    mMapClicksNew       = 0; +    mProfileClicksNew   = 0; + +    mPriceForListing = MINIMUM_PRICE_FOR_LISTING; + +    mCategoryText->setValue(LLStringUtil::null); +    mContentTypeText->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null); +    mEditButton->setValue(LLStringUtil::null); +    getChild<LLUICtrl>("creation_date")->setValue(LLStringUtil::null); +    mContentTypeM->setVisible(FALSE); +    mContentTypeG->setVisible(FALSE); +} + +void LLPanelProfileClassified::setClassifiedName(const std::string& name) +{ +    mClassifiedNameText->setValue(name); +    mClassifiedNameEdit->setValue(name); +} + +std::string LLPanelProfileClassified::getClassifiedName() +{ +    return mClassifiedNameEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setDescription(const std::string& desc) +{ +    mClassifiedDescText->setValue(desc); +    mClassifiedDescEdit->setValue(desc); + +    updateInfoRect(); +} + +std::string LLPanelProfileClassified::getDescription() +{ +    return mClassifiedDescEdit->getValue().asString(); +} + +void LLPanelProfileClassified::setClassifiedLocation(const std::string& location) +{ +    mLocationText->setValue(location); +    mLocationEdit->setValue(location); +} + +std::string LLPanelProfileClassified::getClassifiedLocation() +{ +    return mLocationText->getValue().asString(); +} + +void LLPanelProfileClassified::setSnapshotId(const LLUUID& id) +{ +    mSnapshotCtrl->setValue(id); +} + +LLUUID LLPanelProfileClassified::getSnapshotId() +{ +    return mSnapshotCtrl->getValue().asUUID(); +} + +// static +void LLPanelProfileClassified::setClickThrough( +    const LLUUID& classified_id, +    S32 teleport, +    S32 map, +    S32 profile, +    bool from_new_table) +{ +    LL_INFOS() << "Click-through data for classified " << classified_id << " arrived: [" +            << teleport << ", " << map << ", " << profile << "] (" +            << (from_new_table ? "new" : "old") << ")" << LL_ENDL; + +    for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter) +    { +        LLPanelProfileClassified* self = *iter; +        if (self->getClassifiedId() != classified_id) +        { +            continue; +        } + +        // *HACK: Skip LLPanelProfileClassified instances: they don't display clicks data. +        // Those instances should not be in the list at all. +        if (typeid(*self) != typeid(LLPanelProfileClassified)) +        { +            continue; +        } + +        LL_INFOS() << "Updating classified info panel" << LL_ENDL; + +        // We need to check to see if the data came from the new stat_table +        // or the old classified table. We also need to cache the data from +        // the two separate sources so as to display the aggregate totals. + +        if (from_new_table) +        { +            self->mTeleportClicksNew = teleport; +            self->mMapClicksNew = map; +            self->mProfileClicksNew = profile; +        } +        else +        { +            self->mTeleportClicksOld = teleport; +            self->mMapClicksOld = map; +            self->mProfileClicksOld = profile; +        } + +        static LLUIString ct_str = self->getString("click_through_text_fmt"); + +        ct_str.setArg("[TELEPORT]", llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld)); +        ct_str.setArg("[MAP]",      llformat("%d", self->mMapClicksNew + self->mMapClicksOld)); +        ct_str.setArg("[PROFILE]",  llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld)); + +        self->getChild<LLUICtrl>("click_through_text")->setValue(ct_str.getString()); +        // *HACK: remove this when there is enough room for click stats in the info panel +        self->getChildView("click_through_text")->setToolTip(ct_str.getString()); + +        LL_INFOS() << "teleport: " << llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld) +                << ", map: "    << llformat("%d", self->mMapClicksNew + self->mMapClicksOld) +                << ", profile: " << llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld) +                << LL_ENDL; +    } +} + +// static +std::string LLPanelProfileClassified::createLocationText( +    const std::string& original_name, +    const std::string& sim_name, +    const LLVector3d& pos_global) +{ +    std::string location_text; + +    location_text.append(original_name); + +    if (!sim_name.empty()) +    { +        if (!location_text.empty()) +            location_text.append(", "); +        location_text.append(sim_name); +    } + +    if (!location_text.empty()) +        location_text.append(" "); + +    if (!pos_global.isNull()) +    { +        S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; +        S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; +        S32 region_z = ll_round((F32)pos_global.mdV[VZ]); +        location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); +    } + +    return location_text; +} + +void LLPanelProfileClassified::scrollToTop() +{ +    if (mScrollContainer) +    { +        mScrollContainer->goToTop(); +    } +} + +//info +// static +// *TODO: move out of the panel +void LLPanelProfileClassified::sendClickMessage( +        const std::string& type, +        bool from_search, +        const LLUUID& classified_id, +        const LLUUID& parcel_id, +        const LLVector3d& global_pos, +        const std::string& sim_name) +{ +    if (gAgent.getRegion()) +    { +        // You're allowed to click on your own ads to reassure yourself +        // that the system is working. +        LLSD body; +        body["type"]            = type; +        body["from_search"]     = from_search; +        body["classified_id"]   = classified_id; +        body["parcel_id"]       = parcel_id; +        body["dest_pos_global"] = global_pos.getValue(); +        body["region_name"]     = sim_name; + +        std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); +        LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; +        LL_INFOS() << "body: [" << body << "]" << LL_ENDL; +        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, +            "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); +    } +} + +void LLPanelProfileClassified::sendClickMessage(const std::string& type) +{ +    sendClickMessage( +        type, +        fromSearch(), +        getClassifiedId(), +        getParcelId(), +        getPosGlobal(), +        getSimName()); +} + +void LLPanelProfileClassified::onMapClick() +{ +    sendClickMessage("map"); +    LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfileClassified::onTeleportClick() +{ +    if (!getPosGlobal().isExactlyZero()) +    { +        sendClickMessage("teleport"); +        gAgent.teleportViaLocation(getPosGlobal()); +        LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    } +} + +BOOL LLPanelProfileClassified::isDirty() const +{ +    if(mIsNew) +    { +        return TRUE; +    } + +    BOOL dirty = false; +    dirty |= mSnapshotCtrl->isDirty(); +    dirty |= mClassifiedNameEdit->isDirty(); +    dirty |= mClassifiedDescEdit->isDirty(); +    dirty |= mCategoryCombo->isDirty(); +    dirty |= mContentTypeCombo->isDirty(); +    dirty |= mAutoRenewEdit->isDirty(); + +    return dirty; +} + +void LLPanelProfileClassified::resetDirty() +{ +    mSnapshotCtrl->resetDirty(); +    mClassifiedNameEdit->resetDirty(); + +    // call blockUndo() to really reset dirty(and make isDirty work as intended) +    mClassifiedDescEdit->blockUndo(); +    mClassifiedDescEdit->resetDirty(); + +    mCategoryCombo->resetDirty(); +    mContentTypeCombo->resetDirty(); +    mAutoRenewEdit->resetDirty(); +} + +bool LLPanelProfileClassified::canClose() +{ +    return mCanClose; +} + +U32 LLPanelProfileClassified::getContentType() +{ +    return mContentTypeCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setContentType(bool mature) +{ +    static std::string mature_str = getString("type_mature"); +    static std::string pg_str = getString("type_pg"); +    mContentTypeText->setValue(mature ? mature_str : pg_str); +    mContentTypeM->setVisible(mature); +    mContentTypeG->setVisible(!mature); +    mContentTypeCombo->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG); +    mContentTypeCombo->resetDirty(); +} + +bool LLPanelProfileClassified::getAutoRenew() +{ +    return mAutoRenewEdit->getValue().asBoolean(); +} + +void LLPanelProfileClassified::sendUpdate() +{ +    LLAvatarClassifiedInfo c_data; + +    if(getClassifiedId().isNull()) +    { +        setClassifiedId(LLUUID::generateNewID()); +    } + +    c_data.agent_id = gAgent.getID(); +    c_data.classified_id = getClassifiedId(); +    // *HACK +    // Categories on server start with 1 while combo-box index starts with 0 +    c_data.category = getCategory() + 1; +    c_data.name = getClassifiedName(); +    c_data.description = getDescription(); +    c_data.parcel_id = getParcelId(); +    c_data.snapshot_id = getSnapshotId(); +    c_data.pos_global = getPosGlobal(); +    c_data.flags = getFlags(); +    c_data.price_for_listing = getPriceForListing(); + +    LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); + +    if(isNew()) +    { +        // Lets assume there will be some error. +        // Successful sendClassifiedInfoUpdate will trigger processProperties and +        // let us know there was no error. +        mIsNewWithErrors = true; +    } +} + +U32 LLPanelProfileClassified::getCategory() +{ +    return mCategoryCombo->getCurrentIndex(); +} + +void LLPanelProfileClassified::setCategory(U32 category) +{ +    mCategoryCombo->setCurrentByIndex(category); +    mCategoryCombo->resetDirty(); +} + +U8 LLPanelProfileClassified::getFlags() +{ +    bool auto_renew = mAutoRenewEdit->getValue().asBoolean(); + +    bool mature = mContentTypeCombo->getCurrentIndex() == CB_ITEM_MATURE; + +    return pack_classified_flags_request(auto_renew, false, mature, false); +} + +void LLPanelProfileClassified::enableSave(bool enable) +{ +    mSaveButton->setEnabled(enable); +} + +std::string LLPanelProfileClassified::makeClassifiedName() +{ +    std::string name; + +    LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +    if(parcel) +    { +        name = parcel->getName(); +    } + +    if(!name.empty()) +    { +        return name; +    } + +    LLViewerRegion* region = gAgent.getRegion(); +    if(region) +    { +        name = region->getName(); +    } + +    return name; +} + +void LLPanelProfileClassified::onSetLocationClick() +{ +    setPosGlobal(gAgent.getPositionGlobal()); +    setParcelId(LLUUID::null); + +    std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); +    LLViewerRegion* region = gAgent.getRegion(); +    if (region) +    { +        region_name = region->getName(); +    } + +    setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + +    // mark classified as dirty +    setValue(LLSD()); + +    onChange(); +} + +void LLPanelProfileClassified::onChange() +{ +    enableSave(isDirty()); +} + +void LLPanelProfileClassified::doSave() +{ +    //*TODO: Fix all of this + +    mCanClose = true; +    sendUpdate(); +    updateTabLabel(getClassifiedName()); +    resetDirty(); + +    if (!canClose()) +    { +        return; +    } + +    if (!isNew() && !isNewWithErrors()) +    { +        setEditMode(FALSE); +        return; +    } + +    updateButtons(); +} + +void LLPanelProfileClassified::onPublishFloaterPublishClicked() +{ +    setPriceForListing(mPublishFloater->getPrice()); + +    doSave(); +} + +std::string LLPanelProfileClassified::getLocationNotice() +{ +    static std::string location_notice = getString("location_notice"); +    return location_notice; +} + +bool LLPanelProfileClassified::isValidName() +{ +    std::string name = getClassifiedName(); +    if (name.empty()) +    { +        return false; +    } +    if (!isalnum(name[0])) +    { +        return false; +    } + +    return true; +} + +void LLPanelProfileClassified::notifyInvalidName() +{ +    std::string name = getClassifiedName(); +    if (name.empty()) +    { +        LLNotificationsUtil::add("BlankClassifiedName"); +    } +    else if (!isalnum(name[0])) +    { +        LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); +    } +} + +void LLPanelProfileClassified::onTexturePickerMouseEnter() +{ +    mEditIcon->setVisible(TRUE); +} + +void LLPanelProfileClassified::onTexturePickerMouseLeave() +{ +    mEditIcon->setVisible(FALSE); +} + +void LLPanelProfileClassified::onTextureSelected() +{ +    setSnapshotId(mSnapshotCtrl->getValue().asUUID()); +    onChange(); +} + +void LLPanelProfileClassified::updateTabLabel(const std::string& title) +{ +    setLabel(title); +    LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); +    if (parent) +    { +        parent->setCurrentTabName(title); +    } +} + + +//----------------------------------------------------------------------------- +// LLPublishClassifiedFloater +//----------------------------------------------------------------------------- + +LLPublishClassifiedFloater::LLPublishClassifiedFloater(const LLSD& key) + : LLFloater(key) +{ +} + +LLPublishClassifiedFloater::~LLPublishClassifiedFloater() +{ +} + +BOOL LLPublishClassifiedFloater::postBuild() +{ +    LLFloater::postBuild(); + +    childSetAction("publish_btn", boost::bind(&LLFloater::closeFloater, this, false)); +    childSetAction("cancel_btn", boost::bind(&LLFloater::closeFloater, this, false)); + +    return TRUE; +} + +void LLPublishClassifiedFloater::setPrice(S32 price) +{ +    getChild<LLUICtrl>("price_for_listing")->setValue(price); +} + +S32 LLPublishClassifiedFloater::getPrice() +{ +    return getChild<LLUICtrl>("price_for_listing")->getValue().asInteger(); +} + +void LLPublishClassifiedFloater::setPublishClickedCallback(const commit_signal_t::slot_type& cb) +{ +    getChild<LLButton>("publish_btn")->setClickedCallback(cb); +} + +void LLPublishClassifiedFloater::setCancelClickedCallback(const commit_signal_t::slot_type& cb) +{ +    getChild<LLButton>("cancel_btn")->setClickedCallback(cb); +} diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h new file mode 100644 index 0000000000..912819e86b --- /dev/null +++ b/indra/newview/llpanelprofileclassifieds.h @@ -0,0 +1,340 @@ +/** + * @file llpanelprofileclassifieds.h + * @brief LLPanelProfileClassifieds and related class implementations + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_PANELPROFILECLASSIFIEDS_H +#define LL_PANELPROFILECLASSIFIEDS_H + +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedinfo.h" +#include "llfloater.h" +#include "llpanel.h" +#include "llpanelavatar.h" +#include "llrect.h" +#include "lluuid.h" +#include "v3dmath.h" +#include "llcoros.h" +#include "lleventcoro.h" + +class LLCheckBoxCtrl; +class LLLineEditor; +class LLMediaCtrl; +class LLScrollContainer; +class LLTabContainer; +class LLTextEditor; +class LLTextureCtrl; +class LLUICtrl; + + +class LLPublishClassifiedFloater : public LLFloater +{ +public: +    LLPublishClassifiedFloater(const LLSD& key); +    virtual ~LLPublishClassifiedFloater(); + +    BOOL postBuild() override; + +    void setPrice(S32 price); +    S32 getPrice(); + +    void setPublishClickedCallback(const commit_signal_t::slot_type& cb); +    void setCancelClickedCallback(const commit_signal_t::slot_type& cb); +}; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfileClassifieds +    : public LLPanelProfilePropertiesProcessorTab +{ +public: +    LLPanelProfileClassifieds(); +    /*virtual*/ ~LLPanelProfileClassifieds(); + +    BOOL postBuild() override; + +    void onOpen(const LLSD& key) override; + +    void selectClassified(const LLUUID& classified_id, bool edit); + +    void createClassified(); + +    void processProperties(void* data, EAvatarProcessorType type) override; + +    void resetData() override; + +    void updateButtons(); + +    void updateData() override; + +    bool hasNewClassifieds(); +    bool hasUnsavedChanges() override; +    // commits changes to existing classifieds, but does not publish new classified! +    void commitUnsavedChanges() override; + +private: +    void onClickNewBtn(); +    void onClickDelete(); +    void callbackDeleteClassified(const LLSD& notification, const LLSD& response); + +    bool canAddNewClassified(); +    bool canDeleteClassified(); + +    LLTabContainer* mTabContainer; +    LLUICtrl*       mNoItemsLabel; +    LLButton*       mNewButton; +    LLButton*       mDeleteButton; + +    LLUUID          mClassifiedToSelectOnLoad; +    bool            mClassifiedEditOnLoad; +    bool            mSheduledClassifiedCreation; +}; + + +class LLPanelProfileClassified +    : public LLPanelProfilePropertiesProcessorTab +{ +public: + +    static LLPanelProfileClassified* create(); + +    LLPanelProfileClassified(); + +    /*virtual*/ ~LLPanelProfileClassified(); + +    BOOL postBuild() override; + +    void onOpen(const LLSD& key) override; + +    void processProperties(void* data, EAvatarProcessorType type) override; + +    void setSnapshotId(const LLUUID& id); + +    LLUUID getSnapshotId(); + +    void setClassifiedId(const LLUUID& id) { mClassifiedId = id; } + +    LLUUID& getClassifiedId() { return mClassifiedId; } + +    void setClassifiedName(const std::string& name); + +    std::string getClassifiedName(); + +    void setDescription(const std::string& desc); + +    std::string getDescription(); + +    void setClassifiedLocation(const std::string& location); + +    std::string getClassifiedLocation(); + +    void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + +    LLVector3d& getPosGlobal() { return mPosGlobal; } + +    void setParcelId(const LLUUID& id) { mParcelId = id; } + +    LLUUID getParcelId() { return mParcelId; } + +    void setSimName(const std::string& sim_name) { mSimName = sim_name; } + +    std::string getSimName() { return mSimName; } + +    void setFromSearch(bool val) { mFromSearch = val; } + +    bool fromSearch() { return mFromSearch; } + +    bool getInfoLoaded() { return mInfoLoaded; } + +    void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } + +    BOOL isDirty() const override; + +    void resetDirty() override; + +    bool isNew() { return mIsNew; } + +    bool isNewWithErrors() { return mIsNewWithErrors; } + +    bool canClose(); + +    U32 getCategory(); + +    void setCategory(U32 category); + +    U32 getContentType(); + +    void setContentType(bool mature); + +    bool getAutoRenew(); + +    S32 getPriceForListing() { return mPriceForListing; } + +    void setEditMode(BOOL edit_mode); +    bool getEditMode() {return mEditMode;} + +    static void setClickThrough( +        const LLUUID& classified_id, +        S32 teleport, +        S32 map, +        S32 profile, +        bool from_new_table); + +    static void sendClickMessage( +            const std::string& type, +            bool from_search, +            const LLUUID& classified_id, +            const LLUUID& parcel_id, +            const LLVector3d& global_pos, +            const std::string& sim_name); + +    void doSave(); + +protected: + +    void resetData() override; + +    void resetControls(); + +    void updateButtons(); +    void updateInfoRect(); + +    static std::string createLocationText( +        const std::string& original_name, +        const std::string& sim_name, +        const LLVector3d& pos_global); + +    void sendClickMessage(const std::string& type); + +    void scrollToTop(); + +    void onEditClick(); +    void onCancelClick(); +    void onSaveClick(); +    void onMapClick(); +    void onTeleportClick(); + +    void sendUpdate(); + +    void enableSave(bool enable); + +    void enableEditing(bool enable); + +    std::string makeClassifiedName(); + +    void setPriceForListing(S32 price) { mPriceForListing = price; } + +    U8 getFlags(); + +    std::string getLocationNotice(); + +    bool isValidName(); + +    void notifyInvalidName(); + +    void onSetLocationClick(); +    void onChange(); + +    void onPublishFloaterPublishClicked(); + +    void onTexturePickerMouseEnter(); +    void onTexturePickerMouseLeave(); + +    void onTextureSelected(); + +    void updateTabLabel(const std::string& title); + +private: + +    LLTextureCtrl*      mSnapshotCtrl; +    LLUICtrl*           mEditIcon; +    LLUICtrl*           mClassifiedNameText; +    LLTextEditor*       mClassifiedDescText; +    LLLineEditor*       mClassifiedNameEdit; +    LLTextEditor*       mClassifiedDescEdit; +    LLUICtrl*           mLocationText; +    LLUICtrl*           mLocationEdit; +    LLUICtrl*           mCategoryText; +    LLComboBox*         mCategoryCombo; +    LLUICtrl*           mContentTypeText; +    LLIconCtrl*         mContentTypeM; +    LLIconCtrl*         mContentTypeG; +    LLComboBox*         mContentTypeCombo; +    LLUICtrl*           mPriceText; +    LLUICtrl*           mAutoRenewText; +    LLUICtrl*           mAutoRenewEdit; + +    LLButton*           mMapButton; +    LLButton*           mTeleportButton; +    LLButton*           mEditButton; +    LLButton*           mSaveButton; +    LLButton*           mSetLocationButton; +    LLButton*           mCancelButton; + +    LLPanel*            mUtilityBtnCnt; +    LLPanel*            mPublishBtnsCnt; +    LLPanel*            mSaveBtnCnt; +    LLPanel*            mCancelBtnCnt; + +    LLScrollContainer*  mScrollContainer; +    LLView*             mInfoPanel; +    LLPanel*            mInfoScroll; +    LLPanel*            mEditPanel; + + +    LLUUID mClassifiedId; +    LLVector3d mPosGlobal; +    LLUUID mParcelId; +    std::string mSimName; +    bool mFromSearch; +    bool mInfoLoaded; +    bool mEditMode; + +    // Needed for stat tracking +    S32 mTeleportClicksOld; +    S32 mMapClicksOld; +    S32 mProfileClicksOld; +    S32 mTeleportClicksNew; +    S32 mMapClicksNew; +    S32 mProfileClicksNew; + +    S32 mPriceForListing; + +    static void handleSearchStatResponse(LLUUID classifiedId, LLSD result); + +    typedef std::list<LLPanelProfileClassified*> panel_list_t; +    static panel_list_t sAllPanels; + + +    bool mIsNew; +    bool mIsNewWithErrors; +    bool mCanClose; +    bool mEditOnLoad; + +    LLPublishClassifiedFloater* mPublishFloater; +}; + +#endif // LL_PANELPROFILECLASSIFIEDS_H diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp new file mode 100644 index 0000000000..774119f169 --- /dev/null +++ b/indra/newview/llpanelprofilepicks.cpp @@ -0,0 +1,883 @@ +/** + * @file llpanelprofilepicks.cpp + * @brief LLPanelProfilePicks and related class implementations + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelprofilepicks.h" + +#include "llagent.h" +#include "llagentpicksinfo.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llcommandhandler.h" +#include "lldispatcher.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llpanelavatar.h" +#include "llpanelprofile.h" +#include "llparcel.h" +#include "llstartup.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltexturectrl.h" +#include "lltrans.h" +#include "llviewergenericmessage.h" // send_generic_message +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" + +static LLPanelInjector<LLPanelProfilePicks> t_panel_profile_picks("panel_profile_picks"); +static LLPanelInjector<LLPanelProfilePick> t_panel_profile_pick("panel_profile_pick"); + + +class LLPickHandler : public LLCommandHandler +{ +public: + +    // requires trusted browser to trigger +    LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + +    bool handle(const LLSD& params, const LLSD& query_map, +        LLMediaCtrl* web) +    { +        if (LLStartUp::getStartupState() < STATE_STARTED) +        { +            return true; +        } + +        if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnablePicks")) +        { +            LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); +            return true; +        } + +        // handle app/pick/create urls first +        if (params.size() == 1 && params[0].asString() == "create") +        { +            LLAvatarActions::createPick(); +            return true; +        } + +        // then handle the general app/pick/{UUID}/{CMD} urls +        if (params.size() < 2) +        { +            return false; +        } + +        // get the ID for the pick_id +        LLUUID pick_id; +        if (!pick_id.set(params[0], FALSE)) +        { +            return false; +        } + +        // edit the pick in the side tray. +        // need to ask the server for more info first though... +        const std::string verb = params[1].asString(); +        if (verb == "edit") +        { +            LLAvatarActions::showPick(gAgent.getID(), pick_id); +            return true; +        } +        else +        { +            LL_WARNS() << "unknown verb " << verb << LL_ENDL; +            return false; +        } +    } +}; +LLPickHandler gPickHandler; + + +//----------------------------------------------------------------------------- +// LLPanelProfilePicks +//----------------------------------------------------------------------------- + +LLPanelProfilePicks::LLPanelProfilePicks() + : LLPanelProfilePropertiesProcessorTab() + , mPickToSelectOnLoad(LLUUID::null) +{ +} + +LLPanelProfilePicks::~LLPanelProfilePicks() +{ +} + +void LLPanelProfilePicks::onOpen(const LLSD& key) +{ +    LLPanelProfilePropertiesProcessorTab::onOpen(key); + +    resetData(); + +    bool own_profile = getSelfProfile(); +    if (own_profile) +    { +        mNewButton->setVisible(TRUE); +        mNewButton->setEnabled(FALSE); + +        mDeleteButton->setVisible(TRUE); +        mDeleteButton->setEnabled(FALSE); +    } + +    childSetVisible("buttons_header", own_profile); +} + +void LLPanelProfilePicks::createPick(const LLPickData &data) +{ +    if (getIsLoaded()) +    { +        if (canAddNewPick()) +        { +            mNoItemsLabel->setVisible(FALSE); +            LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); +            pick_panel->setAvatarId(getAvatarId()); +            pick_panel->processProperties(&data); +            mTabContainer->addTabPanel( +                LLTabContainer::TabPanelParams(). +                panel(pick_panel). +                select_tab(true). +                label(pick_panel->getPickName())); +            updateButtons(); +        } +        else +        { +            // This means that something doesn't properly check limits +            // before creating a pick +            LL_WARNS() << "failed to add pick" << LL_ENDL; +        } +    } +    else +    { +        mSheduledPickCreation.push_back(data); +    } +} + +void LLPanelProfilePicks::selectPick(const LLUUID& pick_id) +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (pick_panel) +            { +                if (pick_panel->getPickId() == pick_id) +                { +                    mTabContainer->selectTabPanel(pick_panel); +                    break; +                } +            } +        } +    } +    else +    { +        mPickToSelectOnLoad = pick_id; +    } +} + +BOOL LLPanelProfilePicks::postBuild() +{ +    mTabContainer = getChild<LLTabContainer>("tab_picks"); +    mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text"); +    mNewButton = getChild<LLButton>("new_btn"); +    mDeleteButton = getChild<LLButton>("delete_btn"); + +    mNewButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickNewBtn, this)); +    mDeleteButton->setCommitCallback(boost::bind(&LLPanelProfilePicks::onClickDelete, this)); + +    return TRUE; +} + +void LLPanelProfilePicks::onClickNewBtn() +{ +    mNoItemsLabel->setVisible(FALSE); +    LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); +    pick_panel->setAvatarId(getAvatarId()); +    mTabContainer->addTabPanel( +        LLTabContainer::TabPanelParams(). +        panel(pick_panel). +        select_tab(true). +        label(pick_panel->getPickName())); +    updateButtons(); +} + +void LLPanelProfilePicks::onClickDelete() +{ +    LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); +    if (pick_panel) +    { +        LLUUID pick_id = pick_panel->getPickId(); +        LLSD args; +        args["PICK"] = pick_panel->getPickName(); +        LLSD payload; +        payload["pick_id"] = pick_id; +        payload["tab_idx"] = mTabContainer->getCurrentPanelIndex(); +        LLNotificationsUtil::add("ProfileDeletePick", args, payload, +            boost::bind(&LLPanelProfilePicks::callbackDeletePick, this, _1, _2)); +    } +} + +void LLPanelProfilePicks::callbackDeletePick(const LLSD& notification, const LLSD& response) +{ +    S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + +    if (0 == option) +    { +        LLUUID pick_id = notification["payload"]["pick_id"].asUUID(); +        S32 tab_idx = notification["payload"]["tab_idx"].asInteger(); + +        LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (pick_panel && pick_panel->getPickId() == pick_id) +        { +            mTabContainer->removeTabPanel(pick_panel); +        } + +        if (pick_id.notNull()) +        { +            LLAvatarPropertiesProcessor::getInstance()->sendPickDelete(pick_id); +        } + +        updateButtons(); +    } +} + +void LLPanelProfilePicks::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PICKS == type) +    { +        LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); +        if (avatar_picks && getAvatarId() == avatar_picks->target_id) +        { +            processProperties(avatar_picks); +        } +    } +} + +void LLPanelProfilePicks::processProperties(const LLAvatarPicks* avatar_picks) +{ +    LLUUID selected_id = mPickToSelectOnLoad; +    bool has_selection = false; +    if (mPickToSelectOnLoad.isNull()) +    { +        if (mTabContainer->getTabCount() > 0) +        { +            LLPanelProfilePick* active_pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getCurrentPanel()); +            if (active_pick_panel) +            { +                selected_id = active_pick_panel->getPickId(); +            } +        } +    } + +    mTabContainer->deleteAllTabs(); + +    LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); +    for (; avatar_picks->picks_list.end() != it; ++it) +    { +        LLUUID pick_id = it->first; +        std::string pick_name = it->second; + +        LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); + +        pick_panel->setPickId(pick_id); +        pick_panel->setPickName(pick_name); +        pick_panel->setAvatarId(getAvatarId()); + +        mTabContainer->addTabPanel( +            LLTabContainer::TabPanelParams(). +            panel(pick_panel). +            select_tab(selected_id == pick_id). +            label(pick_name)); + +        if (selected_id == pick_id) +        { +            has_selection = true; +        } +    } + +    while (!mSheduledPickCreation.empty() && canAddNewPick()) +    { +        const LLPickData data = +            mSheduledPickCreation.back(); + +        LLPanelProfilePick* pick_panel = LLPanelProfilePick::create(); +        pick_panel->setAvatarId(getAvatarId()); +        pick_panel->processProperties(&data); +        mTabContainer->addTabPanel( +            LLTabContainer::TabPanelParams(). +            panel(pick_panel). +            select_tab(!has_selection). +            label(pick_panel->getPickName())); + +        mSheduledPickCreation.pop_back(); +        has_selection = true; +    } + +    // reset 'do on load' values +    mPickToSelectOnLoad = LLUUID::null; +    mSheduledPickCreation.clear(); + +    if (getSelfProfile()) +    { +        mNoItemsLabel->setValue(LLTrans::getString("NoPicksText")); +    } +    else +    { +        mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksText")); +    } + +    bool has_data = mTabContainer->getTabCount() > 0; +    mNoItemsLabel->setVisible(!has_data); +    if (has_data && !has_selection) +    { +        mTabContainer->selectFirstTab(); +    } + +    setLoaded(); +    updateButtons(); +} + +void LLPanelProfilePicks::resetData() +{ +    resetLoading(); +    mTabContainer->deleteAllTabs(); +} + +void LLPanelProfilePicks::updateButtons() +{ +    if (getSelfProfile()) +    { +        mNewButton->setEnabled(canAddNewPick()); +        mDeleteButton->setEnabled(canDeletePick()); +    } +} + +void LLPanelProfilePicks::apply() +{ +    if (getIsLoaded()) +    { +        for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +        { +            LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +            if (pick_panel) +            { +                pick_panel->apply(); +            } +        } +    } +} + +void LLPanelProfilePicks::updateData() +{ +    // Send picks request only once +    LLUUID avatar_id = getAvatarId(); +    if (!getStarted() && avatar_id.notNull()) +    { +        setIsLoading(); + +        LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(avatar_id); +    } +    if (!getIsLoaded()) +    { +        mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText")); +        mNoItemsLabel->setVisible(TRUE); +    } +} + +bool LLPanelProfilePicks::hasUnsavedChanges() +{ +    for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +    { +        LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (pick_panel && (pick_panel->isDirty() || pick_panel->isDirty())) +        { +            return true; +        } +    } +    return false; +} + +void LLPanelProfilePicks::commitUnsavedChanges() +{ +    for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +    { +        LLPanelProfilePick* pick_panel = dynamic_cast<LLPanelProfilePick*>(mTabContainer->getPanelByIndex(tab_idx)); +        if (pick_panel) +        { +            pick_panel->apply(); +        } +    } +} + +bool LLPanelProfilePicks::canAddNewPick() +{ +    return (!LLAgentPicksInfo::getInstance()->isPickLimitReached() && +        mTabContainer->getTabCount() < LLAgentPicksInfo::getInstance()->getMaxNumberOfPicks()); +} + +bool LLPanelProfilePicks::canDeletePick() +{ +    return (mTabContainer->getTabCount() > 0); +} + + +//----------------------------------------------------------------------------- +// LLPanelProfilePick +//----------------------------------------------------------------------------- + +LLPanelProfilePick::LLPanelProfilePick() + : LLPanelProfilePropertiesProcessorTab() + , LLRemoteParcelInfoObserver() + , mSnapshotCtrl(NULL) + , mPickId(LLUUID::null) + , mParcelId(LLUUID::null) + , mRequestedId(LLUUID::null) + , mLocationChanged(false) + , mNewPick(false) + , mIsEditing(false) +{ +} + +//static +LLPanelProfilePick* LLPanelProfilePick::create() +{ +    LLPanelProfilePick* panel = new LLPanelProfilePick(); +    panel->buildFromFile("panel_profile_pick.xml"); +    return panel; +} + +LLPanelProfilePick::~LLPanelProfilePick() +{ +    if (mParcelId.notNull()) +    { +        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +    } +} + +void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) +{ +    if (avatar_id.isNull()) +    { +        return; +    } +    LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + +    // creating new Pick +    if (getPickId().isNull() && getSelfProfile()) +    { +        mNewPick = true; + +        setPosGlobal(gAgent.getPositionGlobal()); + +        LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null; +        std::string pick_name, pick_desc, region_name; + +        LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +        if (parcel) +        { +            parcel_id = parcel->getID(); +            pick_name = parcel->getName(); +            pick_desc = parcel->getDesc(); +            snapshot_id = parcel->getSnapshotID(); +        } + +        LLViewerRegion* region = gAgent.getRegion(); +        if (region) +        { +            region_name = region->getName(); +        } + +        setParcelID(parcel_id); +        setPickName(pick_name.empty() ? region_name : pick_name); +        setPickDesc(pick_desc); +        setSnapshotId(snapshot_id); +        setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal())); + +        enableSaveButton(TRUE); +    } +    else +    { +        LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(getAvatarId(), getPickId()); + +        enableSaveButton(FALSE); +    } + +    resetDirty(); + +    if (getSelfProfile()) +    { +        mPickName->setEnabled(TRUE); +        mPickDescription->setEnabled(TRUE); +        mSetCurrentLocationButton->setVisible(TRUE); +    } +    else +    { +        mSnapshotCtrl->setEnabled(FALSE); +    } +} + +BOOL LLPanelProfilePick::postBuild() +{ +    mPickName = getChild<LLLineEditor>("pick_name"); +    mPickDescription = getChild<LLTextEditor>("pick_desc"); +    mSaveButton = getChild<LLButton>("save_changes_btn"); +    mCreateButton = getChild<LLButton>("create_changes_btn"); +    mCancelButton = getChild<LLButton>("cancel_changes_btn"); +    mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn"); + +    mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot"); +    mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); + +    childSetAction("teleport_btn", boost::bind(&LLPanelProfilePick::onClickTeleport, this)); +    childSetAction("show_on_map_btn", boost::bind(&LLPanelProfilePick::onClickMap, this)); + +    mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); +    mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); +    mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this)); +    mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); + +    mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); +    mPickName->setEnabled(FALSE); + +    mPickDescription->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1)); +    mPickDescription->setFocusReceivedCallback(boost::bind(&LLPanelProfilePick::onDescriptionFocusReceived, this)); + +    getChild<LLUICtrl>("pick_location")->setEnabled(FALSE); + +    return TRUE; +} + +void LLPanelProfilePick::onDescriptionFocusReceived() +{ +    if (!mIsEditing && getSelfProfile()) +    { +        mIsEditing = true; +        mPickDescription->setParseHTML(false); +    } +} + +void LLPanelProfilePick::processProperties(void* data, EAvatarProcessorType type) +{ +    if (APT_PICK_INFO != type) +    { +        return; +    } + +    LLPickData* pick_info = static_cast<LLPickData*>(data); +    if (!pick_info +        || pick_info->creator_id != getAvatarId() +        || pick_info->pick_id != getPickId()) +    { +        return; +    } + +    processProperties(pick_info); +} + +void LLPanelProfilePick::processProperties(const LLPickData* pick_info) +{ +    mIsEditing = false; +    mPickDescription->setParseHTML(true); +    mParcelId = pick_info->parcel_id; +    setSnapshotId(pick_info->snapshot_id); +    if (!getSelfProfile()) +    { +        mSnapshotCtrl->setEnabled(FALSE); +    } +    setPickName(pick_info->name); +    setPickDesc(pick_info->desc); +    setPosGlobal(pick_info->pos_global); + +    // Send remote parcel info request to get parcel name and sim (region) name. +    sendParcelInfoRequest(); + +    // *NOTE dzaporozhan +    // We want to keep listening to APT_PICK_INFO because user may +    // edit the Pick and we have to update Pick info panel. +    // revomeObserver is called from onClickBack + +    setLoaded(); +} + +void LLPanelProfilePick::apply() +{ +    if ((mNewPick || getIsLoaded()) && isDirty()) +    { +        sendUpdate(); +    } +} + +void LLPanelProfilePick::setSnapshotId(const LLUUID& id) +{ +    mSnapshotCtrl->setImageAssetID(id); +    mSnapshotCtrl->setValid(TRUE); +} + +void LLPanelProfilePick::setPickName(const std::string& name) +{ +    mPickName->setValue(name); +} + +const std::string LLPanelProfilePick::getPickName() +{ +    return mPickName->getValue().asString(); +} + +void LLPanelProfilePick::setPickDesc(const std::string& desc) +{ +    mPickDescription->setValue(desc); +} + +void LLPanelProfilePick::setPickLocation(const std::string& location) +{ +    getChild<LLUICtrl>("pick_location")->setValue(location); +} + +void LLPanelProfilePick::onClickMap() +{ +    LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelProfilePick::onClickTeleport() +{ +    if (!getPosGlobal().isExactlyZero()) +    { +        gAgent.teleportViaLocation(getPosGlobal()); +        LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); +    } +} + +void LLPanelProfilePick::enableSaveButton(BOOL enable) +{ +    childSetVisible("save_changes_lp", enable); + +    childSetVisible("save_btn_lp", enable && !mNewPick); +    childSetVisible("create_btn_lp", enable && mNewPick); +    childSetVisible("cancel_btn_lp", enable && !mNewPick); +} + +void LLPanelProfilePick::onSnapshotChanged() +{ +    enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onPickChanged(LLUICtrl* ctrl) +{ +    if (ctrl && ctrl == mPickName) +    { +        updateTabLabel(mPickName->getText()); +    } + +    enableSaveButton(isDirty()); +} + +void LLPanelProfilePick::resetDirty() +{ +    LLPanel::resetDirty(); + +    mPickName->resetDirty(); +    mPickDescription->resetDirty(); +    mSnapshotCtrl->resetDirty(); +    mLocationChanged = false; +} + +BOOL LLPanelProfilePick::isDirty() const +{ +    if (mNewPick +        || LLPanel::isDirty() +        || mLocationChanged +        || mSnapshotCtrl->isDirty() +        || mPickName->isDirty() +        || mPickDescription->isDirty()) +    { +        return TRUE; +    } +    return FALSE; +} + +void LLPanelProfilePick::onClickSetLocation() +{ +    // Save location for later use. +    setPosGlobal(gAgent.getPositionGlobal()); + +    std::string parcel_name, region_name; + +    LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); +    if (parcel) +    { +        mParcelId = parcel->getID(); +        parcel_name = parcel->getName(); +    } + +    LLViewerRegion* region = gAgent.getRegion(); +    if (region) +    { +        region_name = region->getName(); +    } + +    setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); + +    mLocationChanged = true; +    enableSaveButton(TRUE); +} + +void LLPanelProfilePick::onClickSave() +{ +    sendUpdate(); + +    mLocationChanged = false; +} + +void LLPanelProfilePick::onClickCancel() +{ +    LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(getAvatarId(), getPickId()); +    mLocationChanged = false; +    enableSaveButton(FALSE); +} + +std::string LLPanelProfilePick::getLocationNotice() +{ +    static const std::string notice = getString("location_notice"); +    return notice; +} + +void LLPanelProfilePick::sendParcelInfoRequest() +{ +    if (mParcelId != mRequestedId) +    { +        if (mRequestedId.notNull()) +        { +            LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedId, this); +        } +        LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this); +        LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId); + +        mRequestedId = mParcelId; +    } +} + +void LLPanelProfilePick::processParcelInfo(const LLParcelData& parcel_data) +{ +    setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name, parcel_data.sim_name, getPosGlobal())); + +    // We have received parcel info for the requested ID so clear it now. +    mRequestedId.setNull(); + +    if (mParcelId.notNull()) +    { +        LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); +    } +} + +void LLPanelProfilePick::sendUpdate() +{ +    LLPickData pick_data; + +    // If we don't have a pick id yet, we'll need to generate one, +    // otherwise we'll keep overwriting pick_id 00000 in the database. +    if (getPickId().isNull()) +    { +        getPickId().generate(); +    } + +    pick_data.agent_id = gAgentID; +    pick_data.session_id = gAgent.getSessionID(); +    pick_data.pick_id = getPickId(); +    pick_data.creator_id = gAgentID;; + +    //legacy var  need to be deleted +    pick_data.top_pick = FALSE; +    pick_data.parcel_id = mParcelId; +    pick_data.name = getPickName(); +    pick_data.desc = mPickDescription->getValue().asString(); +    pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); +    pick_data.pos_global = getPosGlobal(); +    pick_data.sort_order = 0; +    pick_data.enabled = TRUE; + +    LLAvatarPropertiesProcessor::getInstance()->sendPickInfoUpdate(&pick_data); + +    if(mNewPick) +    { +        // Assume a successful create pick operation, make new number of picks +        // available immediately. Actual number of picks will be requested in +        // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond. +        LLAgentPicksInfo::getInstance()->incrementNumberOfPicks(); +    } +} + +// static +std::string LLPanelProfilePick::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global) +{ +    std::string location_text(owner_name); +    if (!original_name.empty()) +    { +        if (!location_text.empty()) +        { +            location_text.append(", "); +        } +        location_text.append(original_name); + +    } + +    if (!sim_name.empty()) +    { +        if (!location_text.empty()) +        { +            location_text.append(", "); +        } +        location_text.append(sim_name); +    } + +    if (!location_text.empty()) +    { +        location_text.append(" "); +    } + +    if (!pos_global.isNull()) +    { +        S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; +        S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; +        S32 region_z = ll_round((F32)pos_global.mdV[VZ]); +        location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); +    } +    return location_text; +} + +void LLPanelProfilePick::updateTabLabel(const std::string& title) +{ +    setLabel(title); +    LLTabContainer* parent = dynamic_cast<LLTabContainer*>(getParent()); +    if (parent) +    { +        parent->setCurrentTabName(title); +    } +} + diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h new file mode 100644 index 0000000000..f84463cc9b --- /dev/null +++ b/indra/newview/llpanelprofilepicks.h @@ -0,0 +1,248 @@ +/** + * @file llpanelprofilepicks.h + * @brief LLPanelProfilePicks and related class definitions + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LLPANELPICKS_H +#define LL_LLPANELPICKS_H + +#include "llpanel.h" +#include "lluuid.h" +#include "llavatarpropertiesprocessor.h" +#include "llpanelavatar.h" +#include "llremoteparcelrequest.h" + +class LLTabContainer; +class LLTextureCtrl; +class LLMediaCtrl; +class LLLineEditor; +class LLTextEditor; + + +/** +* Panel for displaying Avatar's picks. +*/ +class LLPanelProfilePicks +    : public LLPanelProfilePropertiesProcessorTab +{ +public: +    LLPanelProfilePicks(); +    /*virtual*/ ~LLPanelProfilePicks(); + +    BOOL postBuild() override; + +    void onOpen(const LLSD& key) override; + +    void createPick(const LLPickData &data); +    void selectPick(const LLUUID& pick_id); + +    void processProperties(void* data, EAvatarProcessorType type) override; +    void processProperties(const LLAvatarPicks* avatar_picks); + +    void resetData() override; + +    void updateButtons(); + +    /** +     * Saves changes. +     */ +    virtual void apply(); + +    /** +     * Sends update data request to server. +     */ +    void updateData() override; + +    bool hasUnsavedChanges() override; +    void commitUnsavedChanges() override; + +    friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + +private: +    void onClickNewBtn(); +    void onClickDelete(); +    void callbackDeletePick(const LLSD& notification, const LLSD& response); + +    bool canAddNewPick(); +    bool canDeletePick(); + +    LLTabContainer* mTabContainer; +    LLUICtrl*       mNoItemsLabel; +    LLButton*       mNewButton; +    LLButton*       mDeleteButton; + +    LLUUID          mPickToSelectOnLoad; +    std::list<LLPickData> mSheduledPickCreation; +}; + + +class LLPanelProfilePick +    : public LLPanelProfilePropertiesProcessorTab +    , public LLRemoteParcelInfoObserver +{ +public: + +    // Creates new panel +    static LLPanelProfilePick* create(); + +    LLPanelProfilePick(); + +    /*virtual*/ ~LLPanelProfilePick(); + +    BOOL postBuild() override; + +    void setAvatarId(const LLUUID& avatar_id) override; + +    void setPickId(const LLUUID& id) { mPickId = id; } +    virtual LLUUID& getPickId() { return mPickId; } + +    virtual void setPickName(const std::string& name); +    const std::string getPickName(); + +    void processProperties(void* data, EAvatarProcessorType type) override; +    void processProperties(const LLPickData* pick_data); + +    /** +     * Returns true if any of Pick properties was changed by user. +     */ +    BOOL isDirty() const override; + +    /** +     * Saves changes. +     */ +    virtual void apply(); + +    void updateTabLabel(const std::string& title); + +    //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing +    void processParcelInfo(const LLParcelData& parcel_data) override; +    void setParcelID(const LLUUID& parcel_id) override { mParcelId = parcel_id; } +    void setErrorStatus(S32 status, const std::string& reason) override {}; + +protected: + +    /** +     * Sends remote parcel info request to resolve parcel name from its ID. +     */ +    void sendParcelInfoRequest(); + +    /** +    * "Location text" is actually the owner name, the original +    * name that owner gave the parcel, and the location. +    */ +    static std::string createLocationText( +        const std::string& owner_name, +        const std::string& original_name, +        const std::string& sim_name, +        const LLVector3d& pos_global); + +    /** +     * Sets snapshot id. +     * +     * Will mark snapshot control as valid if id is not null. +     * Will mark snapshot control as invalid if id is null. If null id is a valid value, +     * you have to manually mark snapshot is valid. +     */ +    virtual void setSnapshotId(const LLUUID& id); +    virtual void setPickDesc(const std::string& desc); +    virtual void setPickLocation(const std::string& location); + +    virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } +    virtual LLVector3d& getPosGlobal() { return mPosGlobal; } + +    /** +     * Callback for "Map" button, opens Map +     */ +    void onClickMap(); + +    /** +     * Callback for "Teleport" button, teleports user to Pick location. +     */ +    void onClickTeleport(); + +    /** +     * Enables/disables "Save" button +     */ +    void enableSaveButton(BOOL enable); + +    /** +     * Called when snapshot image changes. +     */ +    void onSnapshotChanged(); + +    /** +     * Callback for Pick snapshot, name and description changed event. +     */ +    void onPickChanged(LLUICtrl* ctrl); + +    /** +     * Resets panel and all cantrols to unedited state +     */ +    void resetDirty() override; + +    /** +     * Callback for "Set Location" button click +     */ +    void onClickSetLocation(); + +    /** +     * Callback for "Save" and "Create" button click +     */ +    void onClickSave(); + +    /** +     * Callback for "Save" button click +     */ +    void onClickCancel(); + +    std::string getLocationNotice(); + +    /** +     * Sends Pick properties to server. +     */ +    void sendUpdate(); + +protected: + +    LLTextureCtrl*      mSnapshotCtrl; +    LLLineEditor*       mPickName; +    LLTextEditor*       mPickDescription; +    LLButton*           mSetCurrentLocationButton; +    LLButton*           mSaveButton; +    LLButton*           mCreateButton; +    LLButton*           mCancelButton; + +    LLVector3d mPosGlobal; +    LLUUID mParcelId; +    LLUUID mPickId; +    LLUUID mRequestedId; + +    bool mLocationChanged; +    bool mNewPick; +    bool                mIsEditing; + +    void onDescriptionFocusReceived(); +}; + +#endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 956539cd98..5c93271446 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -51,6 +51,7 @@  #include "llfocusmgr.h"  #include "llmanipscale.h"  #include "llinventorymodel.h" +#include "llmenubutton.h"  #include "llpreviewscript.h"  #include "llresmgr.h"  #include "llselectmgr.h" @@ -177,6 +178,9 @@ BOOL	LLPanelVolume::postBuild()  		mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution));  	} +    mMenuClipboardFeatures = getChild<LLMenuButton>("clipboard_features_params_btn"); +    mMenuClipboardLight = getChild<LLMenuButton>("clipboard_light_params_btn"); +  	std::map<std::string, std::string> material_name_map;  	material_name_map["Stone"]= LLTrans::getString("Stone");  	material_name_map["Metal"]= LLTrans::getString("Metal");	 @@ -217,6 +221,8 @@ LLPanelVolume::LLPanelVolume()  {  	setMouseOpaque(FALSE); +    mCommitCallbackRegistrar.add("PanelVolume.menuDoToSelected", boost::bind(&LLPanelVolume::menuDoToSelected, this, _2)); +    mEnableCallbackRegistrar.add("PanelVolume.menuEnable", boost::bind(&LLPanelVolume::menuEnableItem, this, _2));  } @@ -455,7 +461,6 @@ void LLPanelVolume::getState( )  			gAgentAvatarp->updateMeshVisibility();  		}  	} -	  	// Flexible properties  	BOOL is_flexible = volobjp && volobjp->isFlexible(); @@ -610,6 +615,9 @@ void LLPanelVolume::getState( )  	mObject = objectp;  	mRootObject = root_objectp; + +    mMenuClipboardFeatures->setEnabled(editable && single_volume && volobjp); // Note: physics doesn't need to be limited by single volume +    mMenuClipboardLight->setEnabled(editable && single_volume && volobjp);  }  // static @@ -896,6 +904,290 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data)  	}  } +void LLPanelVolume::onCopyFeatures() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp) +    { +        return; +    } + +    LLSD clipboard; + +    LLVOVolume *volobjp = NULL; +    if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) +    { +        volobjp = (LLVOVolume *)objectp; +    } + +    // Flexi Prim +    if (volobjp && volobjp->isFlexible()) +    { +        LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); +        if (attributes) +        { +            clipboard["flex"]["lod"] = attributes->getSimulateLOD(); +            clipboard["flex"]["gav"] = attributes->getGravity(); +            clipboard["flex"]["ten"] = attributes->getTension(); +            clipboard["flex"]["fri"] = attributes->getAirFriction(); +            clipboard["flex"]["sen"] = attributes->getWindSensitivity(); +            LLVector3 force = attributes->getUserForce(); +            clipboard["flex"]["forx"] = force.mV[0]; +            clipboard["flex"]["fory"] = force.mV[1]; +            clipboard["flex"]["forz"] = force.mV[2]; +        } +    } + +    // Physics +    { +        clipboard["physics"]["shape"] = objectp->getPhysicsShapeType(); +        clipboard["physics"]["gravity"] = objectp->getPhysicsGravity(); +        clipboard["physics"]["friction"] = objectp->getPhysicsFriction(); +        clipboard["physics"]["density"] = objectp->getPhysicsDensity(); +        clipboard["physics"]["restitution"] = objectp->getPhysicsRestitution(); + +        U8 material_code = 0; +        struct f : public LLSelectedTEGetFunctor<U8> +        { +            U8 get(LLViewerObject* object, S32 te) +            { +                return object->getMaterial(); +            } +        } func; +        bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, material_code); +        // This should always be true since material should be per object. +        if (material_same) +        { +            clipboard["physics"]["material"] = material_code; +        } +    } + +    mClipboardParams["features"] = clipboard; +} + +void LLPanelVolume::onPasteFeatures() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp && mClipboardParams.has("features")) +    { +        return; +    } + +    LLSD &clipboard = mClipboardParams["features"]; + +    LLVOVolume *volobjp = NULL; +    if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) +    { +        volobjp = (LLVOVolume *)objectp; +    } + +    // Physics +    bool is_root = objectp->isRoot(); + +    // Not sure if phantom should go under physics, but doesn't fit elsewhere +    BOOL is_phantom = clipboard["is_phantom"].asBoolean() && is_root; +    LLSelectMgr::getInstance()->selectionUpdatePhantom(is_phantom); + +    BOOL is_physical = clipboard["is_physical"].asBoolean() && is_root; +    LLSelectMgr::getInstance()->selectionUpdatePhysics(is_physical); + +    if (clipboard.has("physics")) +    { +        objectp->setPhysicsShapeType((U8)clipboard["physics"]["shape"].asInteger()); +        U8 cur_material = objectp->getMaterial(); +        U8 material = (U8)clipboard["physics"]["material"].asInteger() | (cur_material & ~LL_MCODE_MASK); + +        objectp->setMaterial(material); +        objectp->sendMaterialUpdate(); +        objectp->setPhysicsGravity(clipboard["physics"]["gravity"].asReal()); +        objectp->setPhysicsFriction(clipboard["physics"]["friction"].asReal()); +        objectp->setPhysicsDensity(clipboard["physics"]["density"].asReal()); +        objectp->setPhysicsRestitution(clipboard["physics"]["restitution"].asReal()); +        objectp->updateFlags(TRUE); +    } + +    // Flexible +    bool is_flexible = clipboard.has("flex"); +    if (is_flexible && volobjp->canBeFlexible()) +    { +        LLVOVolume *volobjp = (LLVOVolume *)objectp; +        BOOL update_shape = FALSE; + +        // do before setParameterEntry or it will think that it is already flexi +        update_shape = volobjp->setIsFlexible(is_flexible); + +        if (objectp->getClickAction() == CLICK_ACTION_SIT) +        { +            objectp->setClickAction(CLICK_ACTION_NONE); +        } + +        LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); +        if (attributes) +        { +            LLFlexibleObjectData new_attributes; +            new_attributes = *attributes; +            new_attributes.setSimulateLOD(clipboard["flex"]["lod"].asInteger()); +            new_attributes.setGravity(clipboard["flex"]["gav"].asReal()); +            new_attributes.setTension(clipboard["flex"]["ten"].asReal()); +            new_attributes.setAirFriction(clipboard["flex"]["fri"].asReal()); +            new_attributes.setWindSensitivity(clipboard["flex"]["sen"].asReal()); +            F32 fx = (F32)clipboard["flex"]["forx"].asReal(); +            F32 fy = (F32)clipboard["flex"]["fory"].asReal(); +            F32 fz = (F32)clipboard["flex"]["forz"].asReal(); +            LLVector3 force(fx, fy, fz); +            new_attributes.setUserForce(force); +            objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); +        } + +        if (update_shape) +        { +            mObject->sendShapeUpdate(); +            LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); +        } +    } +    else +    { +        LLVOVolume *volobjp = (LLVOVolume *)objectp; +        if (volobjp->setIsFlexible(false)) +        { +            mObject->sendShapeUpdate(); +            LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); +        } +    } +} + +void LLPanelVolume::onCopyLight() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp) +    { +        return; +    } + +    LLSD clipboard; + +    LLVOVolume *volobjp = NULL; +    if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) +    { +        volobjp = (LLVOVolume *)objectp; +    } + +    // Light Source +    if (volobjp && volobjp->getIsLight()) +    { +        clipboard["light"]["intensity"] = volobjp->getLightIntensity(); +        clipboard["light"]["radius"] = volobjp->getLightRadius(); +        clipboard["light"]["falloff"] = volobjp->getLightFalloff(); +        LLColor3 color = volobjp->getLightSRGBColor(); +        clipboard["light"]["r"] = color.mV[0]; +        clipboard["light"]["g"] = color.mV[1]; +        clipboard["light"]["b"] = color.mV[2]; + +        // Spotlight +        if (volobjp->isLightSpotlight()) +        { +            LLUUID id = volobjp->getLightTextureID(); +            if (id.notNull() && get_can_copy_texture(id)) +            { +                clipboard["spot"]["id"] = id; +                LLVector3 spot_params = volobjp->getSpotLightParams(); +                clipboard["spot"]["fov"] = spot_params.mV[0]; +                clipboard["spot"]["focus"] = spot_params.mV[1]; +                clipboard["spot"]["ambiance"] = spot_params.mV[2]; +            } +        } +    } + +    mClipboardParams["light"] = clipboard; +} + +void LLPanelVolume::onPasteLight() +{ +    LLViewerObject* objectp = mObject; +    if (!objectp && mClipboardParams.has("light")) +    { +        return; +    } + +    LLSD &clipboard = mClipboardParams["light"]; + +    LLVOVolume *volobjp = NULL; +    if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) +    { +        volobjp = (LLVOVolume *)objectp; +    } + +    // Light Source +    if (volobjp) +    { +        if (clipboard.has("light")) +        { +            volobjp->setIsLight(TRUE); +            volobjp->setLightIntensity((F32)clipboard["light"]["intensity"].asReal()); +            volobjp->setLightRadius((F32)clipboard["light"]["radius"].asReal()); +            volobjp->setLightFalloff((F32)clipboard["light"]["falloff"].asReal()); +            F32 r = (F32)clipboard["light"]["r"].asReal(); +            F32 g = (F32)clipboard["light"]["g"].asReal(); +            F32 b = (F32)clipboard["light"]["b"].asReal(); +            volobjp->setLightSRGBColor(LLColor3(r, g, b)); +        } +        else +        { +            volobjp->setIsLight(FALSE); +        } + +        if (clipboard.has("spot")) +        { +            volobjp->setLightTextureID(clipboard["spot"]["id"].asUUID()); +            LLVector3 spot_params; +            spot_params.mV[0] = (F32)clipboard["spot"]["fov"].asReal(); +            spot_params.mV[1] = (F32)clipboard["spot"]["focus"].asReal(); +            spot_params.mV[2] = (F32)clipboard["spot"]["ambiance"].asReal(); +            volobjp->setSpotLightParams(spot_params); +        } +    } +} + +void LLPanelVolume::menuDoToSelected(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste +    if (command == "features_paste") +    { +        onPasteFeatures(); +    } +    else if (command == "light_paste") +    { +        onPasteLight(); +    } +    // copy +    else if (command == "features_copy") +    { +        onCopyFeatures(); +    } +    else if (command == "light_copy") +    { +        onCopyLight(); +    } +} + +bool LLPanelVolume::menuEnableItem(const LLSD& userdata) +{ +    std::string command = userdata.asString(); + +    // paste options +    if (command == "features_paste") +    { +        return mClipboardParams.has("features"); +    } +    else if (command == "light_paste") +    { +        return mClipboardParams.has("light"); +    } +    return false; +} +  // static  void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )  { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 16d9ac292d..62a6d01b21 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -37,6 +37,7 @@ class LLCheckBoxCtrl;  class LLTextBox;  class LLUICtrl;  class LLButton; +class LLMenuButton;  class LLViewerObject;  class LLComboBox;  class LLColorSwatchCtrl; @@ -79,6 +80,13 @@ public:      static void    setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp); +    void            onCopyFeatures(); +    void            onPasteFeatures(); +    void            onCopyLight(); +    void            onPasteLight(); +  +    void        menuDoToSelected(const LLSD& userdata); +    bool        menuEnableItem(const LLSD& userdata);  protected:  	void			getState(); @@ -126,6 +134,11 @@ protected:  	LLSpinCtrl*     mSpinPhysicsFriction;  	LLSpinCtrl*     mSpinPhysicsDensity;  	LLSpinCtrl*     mSpinPhysicsRestitution; + +    LLMenuButton*   mMenuClipboardFeatures; +    LLMenuButton*   mMenuClipboardLight; + +    LLSD            mClipboardParams;  };  #endif diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index 5629438415..3c27964ec5 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -40,7 +40,7 @@ public:  	{  		Params()  		{ -           filter_asset_type = "landmark"; +           filter_asset_types = "landmark";         }  	}; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a32dc8beda..e4b4b597ca 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1199,7 +1199,7 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)  void LLScriptEdCore::onBtnLoadFromFile( void* data )  { -	(new LLFilePickerReplyThread(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false))->getFile(); +	LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::loadScriptFromFile, _1, data), LLFilePicker::FFLOAD_SCRIPT, false);  }  void LLScriptEdCore::loadScriptFromFile(const std::vector<std::string>& filenames, void* data) @@ -1240,7 +1240,7 @@ void LLScriptEdCore::onBtnSaveToFile( void* userdata )  	if( self->mSaveCallback )  	{ -		(new LLFilePickerReplyThread(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&LLScriptEdCore::saveScriptToFile, _1, userdata), LLFilePicker::FFSAVE_SCRIPT, self->mScriptName);  	}  } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index cd7b93aba7..975e2bb910 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -296,7 +296,7 @@ void LLPreviewTexture::saveAs()  		return;  	std::string filename = getItem() ? LLDir::getScrubbedFileName(getItem()->getName()) : LLStringUtil::null; -	(new LLFilePickerReplyThread(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename))->getFile(); +	LLFilePickerReplyThread::startPicker(boost::bind(&LLPreviewTexture::saveTextureToFile, this, _1), LLFilePicker::FFSAVE_TGAPNG, filename);  }  void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenames) @@ -367,7 +367,10 @@ void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent)  	// add space for dimensions and aspect ratio  	S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD; - +	if (getChild<LLLayoutPanel>("buttons_panel")->getVisible()) +	{ +		info_height += getChild<LLLayoutPanel>("buttons_panel")->getRect().getHeight(); +	}  	LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);  	client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);  	client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ; @@ -412,6 +415,16 @@ void LLPreviewTexture::openToSave()  	mPreviewToSave = TRUE;  } +void LLPreviewTexture::hideCtrlButtons() +{ +	getChildView("desc txt")->setVisible(false); +	getChildView("desc")->setVisible(false); +	getChild<LLLayoutStack>("preview_stack")->collapsePanel(getChild<LLLayoutPanel>("buttons_panel"), true); +	getChild<LLLayoutPanel>("buttons_panel")->setVisible(false); +	getChild<LLComboBox>("combo_aspect_ratio")->setCurrentByIndex(0); //unconstrained +	reshape(getRect().getWidth(), getRect().getHeight()); +} +  // static  void LLPreviewTexture::onFileLoadedForSave(BOOL success,   					   LLViewerFetchedTexture *src_vi, diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 9b6a843875..16db51332e 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -67,6 +67,8 @@ public:  	static void			onSaveAsBtn(void* data); +	void				hideCtrlButtons(); +  	/*virtual*/ void setObjectID(const LLUUID& object_id);  protected:  	void				init(); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 583c6de77b..d349b7e024 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -40,7 +40,7 @@ extern BOOL gTeleportDisplay;  LLReflectionMapManager::LLReflectionMapManager()  { -    for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i) +    for (int i = 0; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)      {          mCubeFree[i] = true;      } @@ -76,16 +76,7 @@ void LLReflectionMapManager::update()      }      // =============== TODO -- move to an init function  ================= - -    if (mTexture.isNull()) -    { -        mTexture = new LLCubeMapArray(); -        // store LL_REFLECTION_PROBE_COUNT+2 cube maps, final two cube maps are used for render target and radiance map generation source) -        mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT+2); - -        mIrradianceMaps = new LLCubeMapArray(); -        mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); -    } +    initReflectionMaps();      if (!mRenderTarget.isComplete())      { @@ -167,7 +158,7 @@ void LLReflectionMapManager::update()          LLVector4a d;          if (!did_update &&  -            i < LL_REFLECTION_PROBE_COUNT && +            i < mReflectionProbeCount &&              (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))          {              oldestProbe = probe; @@ -175,7 +166,7 @@ void LLReflectionMapManager::update()          if (realtime &&               closestDynamic == nullptr &&  -            probe->mCubeArray.notNull() && +            probe->mCubeIndex != -1 &&              probe->getIsDynamic())          {              closestDynamic = probe; @@ -317,7 +308,7 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo  S32 LLReflectionMapManager::allocateCubeIndex()  { -    for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i) +    for (int i = 0; i < mReflectionProbeCount; ++i)      {          if (mCubeFree[i])          { @@ -327,12 +318,13 @@ S32 LLReflectionMapManager::allocateCubeIndex()      }      // no cubemaps free, steal one from the back of the probe list -    for (int i = mProbes.size() - 1; i >= LL_REFLECTION_PROBE_COUNT; --i) +    for (int i = mProbes.size() - 1; i >= mReflectionProbeCount; --i)      {          if (mProbes[i]->mCubeIndex != -1)          {              S32 ret = mProbes[i]->mCubeIndex;              mProbes[i]->mCubeIndex = -1; +            mProbes[i]->mCubeArray = nullptr;              return ret;          }      } @@ -392,7 +384,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)      gPipeline.mRT = &gPipeline.mMainRT;      mRenderTarget.flush(); -    S32 targetIdx = LL_REFLECTION_PROBE_COUNT; +    S32 targetIdx = mReflectionProbeCount;      if (probe != mUpdatingProbe)      { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel @@ -625,15 +617,15 @@ void LLReflectionMapManager::updateUniforms()      // see class3/deferred/reflectionProbeF.glsl      struct ReflectionProbeData      { -        LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed -        LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space -        LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) -        GLint refIndex[LL_REFLECTION_PROBE_COUNT][4]; +        LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; // object bounding box as needed +        LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space +        LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) +        GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];          GLint refNeighbor[4096];          GLint refmapCount;      }; -    mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT); +    mReflectionMaps.resize(mReflectionProbeCount);      getReflectionMaps(mReflectionMaps);      ReflectionProbeData rpd; @@ -830,3 +822,19 @@ void LLReflectionMapManager::renderDebug()      gDebugProgram.unbind();  } + +void LLReflectionMapManager::initReflectionMaps() +{ +    if (mTexture.isNull()) +    { +        mReflectionProbeCount = llclamp(gSavedSettings.getS32("RenderReflectionProbeCount"), 1, LL_MAX_REFLECTION_PROBE_COUNT); + +        mTexture = new LLCubeMapArray(); + +        // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) +        mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, mReflectionProbeCount + 2); + +        mIrradianceMaps = new LLCubeMapArray(); +        mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount); +    } +} diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 5f0b11ec17..29a9ece2f8 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -35,7 +35,7 @@ class LLSpatialGroup;  class LLViewerObject;  // number of reflection probes to keep in vram -#define LL_REFLECTION_PROBE_COUNT 256 +#define LL_MAX_REFLECTION_PROBE_COUNT 256  // reflection probe resolution  #define LL_REFLECTION_PROBE_RESOLUTION 256 @@ -88,6 +88,9 @@ public:      // probe debug display is active      void renderDebug(); +    // call once at startup to allocate cubemap arrays +    void initReflectionMaps(); +  private:      friend class LLPipeline; @@ -120,7 +123,7 @@ private:      LLPointer<LLCubeMapArray> mIrradianceMaps;      // array indicating if a particular cubemap is free -    bool mCubeFree[LL_REFLECTION_PROBE_COUNT]; +    bool mCubeFree[LL_MAX_REFLECTION_PROBE_COUNT];      // start tracking the given spatial group      void trackGroup(LLSpatialGroup* group); @@ -148,5 +151,8 @@ private:      LLReflectionMap* mUpdatingProbe = nullptr;      U32 mUpdatingFace = 0; + +    // number of reflection probes to use for rendering (based on saved setting RenderReflectionProbeCount) +    U32 mReflectionProbeCount;  }; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 055ccd5818..f4ace52faa 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -213,7 +213,12 @@ void LLRemoteParcelInfoProcessor::regionParcelInfoCoro(std::string url,      if (!status)      { -        observer->setErrorStatus(status.getStatus(), status.getMessage()); +        std::string message = status.getMessage(); +        if (message.empty()) +        { +            message = status.toString(); +        } +        observer->setErrorStatus(status.getStatus(), message);      }      else       { diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 853703b4d5..fc5b1c60e2 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1936,6 +1936,32 @@ BOOL LLSelectMgr::selectionRevertTextures()  	return revert_successful;  } +void LLSelectMgr::selectionRevertGLTFMaterials() +{ +    struct f : public LLSelectedTEFunctor +    { +        LLObjectSelectionHandle mSelectedObjects; +        f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} +        bool apply(LLViewerObject* object, S32 te) +        { +            if (object->permModify()) +            { +                LLSelectNode* nodep = mSelectedObjects->findNode(object); +                if (nodep && te < (S32)nodep->mSavedGLTFMaterials.size()) +                { +                    LLUUID id = nodep->mSavedGLTFMaterials[te]; +                    object->setRenderMaterialID(te, id); +                } +            } +            return true; +        } +    } setfunc(mSelectedObjects); +    getSelection()->applyToTEs(&setfunc); + +    LLSelectMgrSendFunctor sendfunc; +    getSelection()->applyToObjects(&sendfunc); +} +  void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)  {  	struct f : public LLSelectedTEFunctor @@ -5526,6 +5552,17 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data  					// this should be the only place that saved textures is called  					node->saveTextures(texture_ids);  				} + +                if (can_copy && can_transfer && node->getObject()->getVolume()) +                { +                    uuid_vec_t material_ids; +                    LLVOVolume* vobjp = (LLVOVolume*)node->getObject(); +                    for (int i = 0; i < vobjp->getNumTEs(); ++i) +                    { +                        material_ids.push_back(vobjp->getRenderMaterialID(i)); +                    } +                    node->savedGLTFMaterials(material_ids); +                }  			}  			node->mValid = TRUE; @@ -6277,6 +6314,7 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep)  	}  	saveTextures(nodep.mSavedTextures); +    savedGLTFMaterials(nodep.mSavedGLTFMaterials);  }  LLSelectNode::~LLSelectNode() @@ -6392,6 +6430,20 @@ void LLSelectNode::saveTextures(const uuid_vec_t& textures)  	}  } +void LLSelectNode::savedGLTFMaterials(const uuid_vec_t& materials) +{ +    if (mObject.notNull()) +    { +        mSavedGLTFMaterials.clear(); + +        for (uuid_vec_t::const_iterator materials_it = materials.begin(); +            materials_it != materials.end(); ++materials_it) +        { +            mSavedGLTFMaterials.push_back(*materials_it); +        } +    } +} +  void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)  {  	mTextureScaleRatios.clear(); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index ce0316e610..aec2baa6a7 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -187,6 +187,7 @@ public:  	void saveColors();  	void saveShinyColors();  	void saveTextures(const uuid_vec_t& textures); +    void savedGLTFMaterials(const uuid_vec_t& materials);  	void saveTextureScaleRatios(LLRender::eTexIndex index_to_query);  	BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const; @@ -224,6 +225,7 @@ public:  	std::vector<LLColor4>	mSavedColors;  	std::vector<LLColor4>	mSavedShinyColors;  	uuid_vec_t		mSavedTextures; +    uuid_vec_t		mSavedGLTFMaterials;  	std::vector<LLVector3>  mTextureScaleRatios;  	std::vector<LLVector3>	mSilhouetteVertices;	// array of vertices to render silhouette of object  	std::vector<LLVector3>	mSilhouetteNormals;	// array of normals to render silhouette of object @@ -609,6 +611,7 @@ public:  	void selectionRevertColors();  	void selectionRevertShinyColors();  	BOOL selectionRevertTextures(); +    void selectionRevertGLTFMaterials();  	void selectionSetBumpmap( U8 bumpmap, const LLUUID &image_id );  	void selectionSetTexGen( U8 texgen );  	void selectionSetShiny( U8 shiny, const LLUUID &image_id ); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f445bc98eb..10b3683cc8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3367,10 +3367,10 @@ public:  				}  			}	 -			if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) +			/*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))  			{  				renderTexturePriority(drawable); -			} +			}*/  			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS))  			{ @@ -3697,7 +3697,7 @@ void LLSpatialPartition::renderDebug()  									  LLPipeline::RENDER_DEBUG_BBOXES |  									  LLPipeline::RENDER_DEBUG_NORMALS |  									  LLPipeline::RENDER_DEBUG_POINTS | -									  LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | +									  //LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |  									  LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |  									  LLPipeline::RENDER_DEBUG_RAYCAST |  									  LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0829b1a213..142dc4c46e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -97,6 +97,7 @@  #include "llfloateravatarpicker.h"  #include "llcallbacklist.h"  #include "llcallingcard.h" +#include "llclassifiedinfo.h"  #include "llconsole.h"  #include "llcontainerview.h"  #include "llconversationlog.h" @@ -124,8 +125,6 @@  #include "llpanellogin.h"  #include "llmutelist.h"  #include "llavatarpropertiesprocessor.h" -#include "llpanelclassified.h" -#include "llpanelpick.h"  #include "llpanelgrouplandmoney.h"  #include "llpanelgroupnotices.h"  #include "llparcel.h" @@ -194,6 +193,7 @@  #include "llavatariconctrl.h"  #include "llvoicechannel.h"  #include "llpathfindingmanager.h" +#include "llremoteparcelrequest.h"  #include "lllogin.h"  #include "llevents.h" @@ -2652,7 +2652,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)  	msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply);  	msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); -//	msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);  	msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply);  	msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply);  	msg->setHandlerFunc("ScriptDialog", process_script_dialog); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d4fc6f3de2..8f4eb9438b 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -95,14 +95,13 @@ private:  	};  public: -	LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, +	LLTextureCacheWorker(LLTextureCache* cache, const LLUUID& id,  						 U8* data, S32 datasize, S32 offset,  						 S32 imagesize, // for writes  						 LLTextureCache::Responder* responder)  		: LLWorkerClass(cache, "LLTextureCacheWorker"),  		  mID(id),  		  mCache(cache), -		  mPriority(priority),  		  mReadData(NULL),  		  mWriteData(data),  		  mDataSize(datasize), @@ -115,7 +114,6 @@ public:  		  mBytesToRead(0),  		  mBytesRead(0)  	{ -		mPriority &= LLWorkerThread::PRIORITY_LOWBITS;  	}  	~LLTextureCacheWorker()  	{ @@ -129,13 +127,12 @@ public:  	virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() -	handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } -	handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } +	handle_t read() { addWork(0); return mRequestHandle; } +	handle_t write() { addWork(1); return mRequestHandle; }  	bool complete() { return checkWork(); }  	void ioComplete(S32 bytes)  	{  		mBytesRead = bytes; -		setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority);  	}  private: @@ -145,7 +142,6 @@ private:  protected:  	LLTextureCache* mCache; -	U32 mPriority;  	LLUUID	mID;  	U8* mReadData; @@ -164,11 +160,11 @@ protected:  class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker  {  public: -	LLTextureCacheLocalFileWorker(LLTextureCache* cache, U32 priority, const std::string& filename, const LLUUID& id, +	LLTextureCacheLocalFileWorker(LLTextureCache* cache, const std::string& filename, const LLUUID& id,  						 U8* data, S32 datasize, S32 offset,  						 S32 imagesize, // for writes  						 LLTextureCache::Responder* responder)  -			: LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), +			: LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder),  			mFileName(filename)  	{ @@ -183,6 +179,7 @@ private:  bool LLTextureCacheLocalFileWorker::doRead()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool());  	if (local_size > 0 && mFileName.size() > 4) @@ -207,50 +204,6 @@ bool LLTextureCacheLocalFileWorker::doRead()  		return true;  	} -#if USE_LFS_READ -	if (mFileHandle == LLLFSThread::nullHandle()) -	{ -		mImageLocal = TRUE; -		mImageSize = local_size; -		if (!mDataSize || mDataSize + mOffset > local_size) -		{ -			mDataSize = local_size - mOffset; -		} -		if (mDataSize <= 0) -		{ -			// no more data to read -			mDataSize = 0; -			return true; -		} -		mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); -		mBytesRead = -1; -		mBytesToRead = mDataSize; -		setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); -		mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, -												new ReadResponder(mCache, mRequestHandle)); -		return false; -	} -	else -	{ -		if (mBytesRead >= 0) -		{ -			if (mBytesRead != mBytesToRead) -			{ -// 				LL_WARNS() << "Error reading file from local cache: " << local_filename -// 						<< " Bytes: " << mDataSize << " Offset: " << mOffset -// 						<< " / " << mDataSize << LL_ENDL; -				mDataSize = 0; // failed -				ll_aligned_free_16(mReadData); -				mReadData = NULL; -			} -			return true; -		} -		else -		{ -			return false; -		} -	} -#else  	if (!mDataSize || mDataSize > local_size)  	{  		mDataSize = local_size; @@ -274,7 +227,6 @@ bool LLTextureCacheLocalFileWorker::doRead()  		mImageLocal = TRUE;  	}  	return true; -#endif  }  bool LLTextureCacheLocalFileWorker::doWrite() @@ -286,12 +238,12 @@ bool LLTextureCacheLocalFileWorker::doWrite()  class LLTextureCacheRemoteWorker : public LLTextureCacheWorker  {  public: -	LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, +	LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id,  						 U8* data, S32 datasize, S32 offset,  						 S32 imagesize, // for writes  						 LLPointer<LLImageRaw> raw, S32 discardlevel,  						 LLTextureCache::Responder* responder)  -			: LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), +			: LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder),  			mState(INIT),  			mRawImage(raw),  			mRawDiscardLevel(discardlevel) @@ -329,6 +281,7 @@ void LLTextureCacheWorker::startWork(S32 param)  // - the code supports offset reading but this is actually never exercised in the viewer  bool LLTextureCacheRemoteWorker::doRead()  { +    LL_PROFILE_ZONE_SCOPED;  	bool done = false;  	S32 idx = -1; @@ -580,6 +533,7 @@ bool LLTextureCacheRemoteWorker::doRead()  // - the code *does not* support offset writing so there are no difference between buffer addresses and start of data  bool LLTextureCacheRemoteWorker::doWrite()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	bool done = false;  	S32 idx = -1;	 @@ -756,6 +710,7 @@ bool LLTextureCacheRemoteWorker::doWrite()  //virtual  bool LLTextureCacheWorker::doWork(S32 param)  { +    LL_PROFILE_ZONE_SCOPED;  	bool res = false;  	if (param == 0) // read  	{ @@ -775,11 +730,13 @@ bool LLTextureCacheWorker::doWork(S32 param)  //virtual (WORKER THREAD)  void LLTextureCacheWorker::finishWork(S32 param, bool completed)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if (mResponder.notNull())  	{  		bool success = (completed && mDataSize > 0);  		if (param == 0)  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read");  			// read  			if (success)  			{ @@ -789,12 +746,14 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)  			}  			else  			{ +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read fail");  				ll_aligned_free_16(mReadData);  				mReadData = NULL;  			}  		}  		else  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - write");  			// write  			mWriteData = NULL; // we never owned data  			mDataSize = 0; @@ -806,6 +765,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)  //virtual (MAIN THREAD)  void LLTextureCacheWorker::endWork(S32 param, bool aborted)  { +    LL_PROFILE_ZONE_SCOPED;  	if (aborted)  	{  		// Let the destructor handle any cleanup @@ -861,6 +821,7 @@ LLTextureCache::~LLTextureCache()  //virtual  S32 LLTextureCache::update(F32 max_time_ms)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	static LLFrameTimer timer ;  	static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds. @@ -874,22 +835,6 @@ S32 LLTextureCache::update(F32 max_time_ms)  	mCompletedList.clear();  	mListMutex.unlock(); -	lockWorkers(); -	 -	for (handle_list_t::iterator iter1 = priorty_list.begin(); -		 iter1 != priorty_list.end(); ++iter1) -	{ -		handle_t handle = *iter1; -		handle_map_t::iterator iter2 = mWriters.find(handle); -		if(iter2 != mWriters.end()) -		{ -			LLTextureCacheWorker* worker = iter2->second; -			worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority); -		} -	} - -	unlockWorkers();  -	  	// call 'completed' with workers list unlocked (may call readComplete() or writeComplete()  	for (responder_list_t::iterator iter1 = completed_list.begin();  		 iter1 != completed_list.end(); ++iter1) @@ -1323,6 +1268,7 @@ void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry)  //update an existing entry, write to header file immediately.  bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_data_size)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ;  	if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize) @@ -1872,6 +1818,7 @@ void LLTextureCache::purgeTextures(bool validate)  // call lockWorkers() first!  LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	LLTextureCacheWorker* res = NULL;  	handle_map_t::iterator iter = mReaders.find(handle);  	if (iter != mReaders.end()) @@ -1883,6 +1830,7 @@ LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)  LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	LLTextureCacheWorker* res = NULL;  	handle_map_t::iterator iter = mWriters.find(handle);  	if (iter != mWriters.end()) @@ -1898,6 +1846,7 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)  // Reads imagesize from the header, updates timestamp  S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	LLMutexLock lock(&mHeaderMutex);	  	S32 idx = openAndReadEntry(id, entry, false);  	if (idx >= 0) @@ -1910,6 +1859,7 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry)  // Writes imagesize to the header, updates timestamp  S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	mHeaderMutex.lock();  	S32 idx = openAndReadEntry(id, entry, true); // read or create  	mHeaderMutex.unlock(); @@ -1942,13 +1892,14 @@ S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imag  // Calls from texture pipeline thread (i.e. LLTextureFetch) -LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id,  													   S32 offset, S32 size, ReadResponder* responder)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	// Note: checking to see if an entry exists can cause a stall,  	//  so let the thread handle it  	LLMutexLock lock(&mWorkersMutex); -	LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, +	LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, filename, id,  																	 NULL, size, offset, 0,  																	 responder);  	handle_t handle = worker->read(); @@ -1956,13 +1907,14 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena  	return handle;  } -LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id,  													   S32 offset, S32 size, ReadResponder* responder)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	// Note: checking to see if an entry exists can cause a stall,  	//  so let the thread handle it  	LLMutexLock lock(&mWorkersMutex); -	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, +	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id,  																  NULL, size, offset,  																  0, NULL, 0, responder);  	handle_t handle = worker->read(); @@ -1973,6 +1925,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri  bool LLTextureCache::readComplete(handle_t handle, bool abort)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	lockWorkers();  	handle_map_t::iterator iter = mReaders.find(handle);  	LLTextureCacheWorker* worker = NULL; @@ -2000,7 +1953,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)  	return (complete || abort);  } -LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id,  													  U8* data, S32 datasize, S32 imagesize,  													  LLPointer<LLImageRaw> rawimage, S32 discardlevel,  													  WriteResponder* responder) @@ -2018,7 +1971,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio  		mDoPurge = !mPurgeEntryList.empty();  	}  	LLMutexLock lock(&mWorkersMutex); -	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, +	LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id,  																  data, datasize, 0,  																  imagesize, rawimage, discardlevel, responder);  	handle_t handle = worker->write(); @@ -2086,6 +2039,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d  //return the fast cache location  bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	//rescale image if needed  	if (raw.isNull() || raw->isBufferInvalid() || !raw->getData())  	{ diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index e1c752b58e..f2a5978a7c 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -119,13 +119,13 @@ public:  	void setReadOnly(BOOL read_only) ;  	S64 initCache(ELLPath location, S64 maxsize, BOOL texture_cache_mismatch); -	handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size, +	handle_t readFromCache(const std::string& local_filename, const LLUUID& id, S32 offset, S32 size,  						   ReadResponder* responder); -	handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size, +	handle_t readFromCache(const LLUUID& id, S32 offset, S32 size,  						   ReadResponder* responder);  	bool readComplete(handle_t handle, bool abort); -	handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel, +	handle_t writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,  						  WriteResponder* responder);  	LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);  	bool writeComplete(handle_t handle, bool abort = false); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ee83d9eb57..a26ac446c6 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -41,13 +41,17 @@  #include "llfolderviewmodel.h"  #include "llinventory.h"  #include "llinventoryfunctions.h" +#include "llinventoryicon.h"  #include "llinventorymodelbackgroundfetch.h"  #include "llinventoryobserver.h"  #include "llinventorypanel.h"  #include "lllineeditor.h" +#include "llmaterialeditor.h"  #include "llui.h"  #include "llviewerinventory.h" +#include "llviewermenufile.h"	// LLFilePickerReplyThread  #include "llpermissions.h" +#include "llpreviewtexture.h"  #include "llsaleinfo.h"  #include "llassetstorage.h"  #include "lltextbox.h" @@ -69,16 +73,70 @@  #include "llradiogroup.h"  #include "llfloaterreg.h"  #include "lllocalbitmaps.h" +#include "lllocalgltfmaterials.h"  #include "llerror.h"  #include "llavatarappearancedefines.h" -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"; +//static +bool get_is_predefined_texture(LLUUID asset_id) +{ +    if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture")) +        || asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) +        || asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) +        || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE)) +    { +        return true; +    } +    return false; +} + +LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm) +{ +    LLViewerInventoryCategory::cat_array_t cats; +    LLViewerInventoryItem::item_array_t items; +    LLAssetIDMatches asset_id_matches(asset_id); +    gInventory.collectDescendentsIf(LLUUID::null, +        cats, +        items, +        LLInventoryModel::INCLUDE_TRASH, +        asset_id_matches); +     +    LLUUID res; +    if (items.size()) +    { +        for (S32 i = 0; i < items.size(); i++) +        { +            LLViewerInventoryItem* itemp = items[i]; +            if (itemp) +            { +                LLPermissions item_permissions = itemp->getPermissions(); +                if (item_permissions.allowOperationBy(PERM_COPY, +                    gAgent.getID(), +                    gAgent.getGroupID())) +                { +                    bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()); +                    if (allow_trans != no_trans_perm) +                    { +                        return itemp->getUUID(); +                    } +                    res = itemp->getUUID(); +                } +            } +        } +    } +    return res; +} + +bool get_can_copy_texture(LLUUID asset_id) +{ +    // User is allowed to copy a texture if: +    // library asset or default texture, +    // or copy perm asset exists in user's inventory + +    return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull(); +}  LLFloaterTexturePicker::LLFloaterTexturePicker(	  	LLView* owner, @@ -356,23 +414,29 @@ BOOL LLFloaterTexturePicker::postBuild()  	childSetCommitCallback("show_folders_check", onShowFolders, this);  	getChildView("show_folders_check")->setVisible( FALSE); -	mFilterEdit = getChild<LLFilterEditor>("inventory search editor"); -	mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2)); +    mFilterEdit = getChild<LLFilterEditor>("inventory search editor"); +    mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));  	mInventoryPanel = getChild<LLInventoryPanel>("inventory panel"); +    mTextureMaterialsCombo = getChild<LLComboBox>("textures_material_combo"); +    mTextureMaterialsCombo->setCommitCallback(onSelectTextureMaterials, this); + +    // set the combo box to the first entry in the list (currently textures and materials) +    mTextureMaterialsCombo->selectByValue(0); +  	mModeSelector = getChild<LLComboBox>("mode_selection");  	mModeSelector->setCommitCallback(onModeSelect, this);  	mModeSelector->selectByValue(0);  	if(mInventoryPanel)  	{ -		U32 filter_types = 0x0; -		filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; -		filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; +        // to avoid having to make an assumption about which option is +        // selected at startup, we call the same function that is triggered +        // when a texture/materials/both choice is made and let it take care +        // of setting the filters +        onSelectTextureMaterials(0, this); -		mInventoryPanel->setFilterTypes(filter_types); -		//mInventoryPanel->setFilterPermMask(getFilterPermMask());  //Commented out due to no-copy texture loss.  		mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);  		mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));  		mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); @@ -405,7 +469,9 @@ BOOL LLFloaterTexturePicker::postBuild()  	mLocalScrollCtrl = getChild<LLScrollListCtrl>("l_name_list");  	mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this); +    mLocalScrollCtrl->clearRows();  	LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl); +    LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl);  	mNoCopyTextureSelected = FALSE; @@ -682,8 +748,18 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)  	{  		if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty())  		{ -			LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); -			local_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id); +            LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); +            LLUUID temp_id = data["id"]; +            S32 asset_type = data["type"].asInteger(); + +            if (LLAssetType::AT_MATERIAL == asset_type) +            { +                local_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(temp_id); +            } +            else +            { +                local_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id); +            }  		}  	} @@ -756,6 +832,7 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)  	self->getChild<LLButton>("Blank")->setVisible(index == 0 ? TRUE : FALSE);  	self->getChild<LLButton>("None")->setVisible(index == 0 ? TRUE : FALSE);  	self->getChild<LLButton>("Pipette")->setVisible(index == 0 ? TRUE : FALSE); +    self->getChild<LLComboBox>("textures_material_combo")->setVisible(index == 0 ? TRUE : FALSE);  	self->getChild<LLFilterEditor>("inventory search editor")->setVisible(index == 0 ? TRUE : FALSE);  	self->getChild<LLInventoryPanel>("inventory panel")->setVisible(index == 0 ? TRUE : FALSE); @@ -830,11 +907,13 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)  // static  void LLFloaterTexturePicker::onBtnAdd(void* userdata)  { -	if (LLLocalBitmapMgr::getInstance()->addUnit() == true) -	{ -		LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; -		LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); -	} +    LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata; + +    // todo: there will be changes to texture picker to forbid +    // selection of materials in some cases, like landmarks, once +    // it gets implemented, update code to select FLOAD_* filter +    // based on picker's material/texture mode. +    LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true);  }  // static @@ -845,22 +924,34 @@ void LLFloaterTexturePicker::onBtnRemove(void* userdata)  	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::getInstance()->delUnit(tracking_id); +                LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); +                LLUUID tracking_id = data["id"]; +                S32 asset_type = data["type"].asInteger(); + +                if (LLAssetType::AT_MATERIAL == asset_type) +                { +                    LLLocalGLTFMaterialMgr::getInstance()->delUnit(tracking_id); +                } +                else +                { +                    LLLocalBitmapMgr::getInstance()->delUnit(tracking_id); +                }  			}  		}  		self->getChild<LLButton>("l_rem_btn")->setEnabled(false);  		self->getChild<LLButton>("l_upl_btn")->setEnabled(false); +        self->mLocalScrollCtrl->clearRows();  		LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); +        LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl);  	} -  }  // static @@ -876,15 +967,31 @@ void LLFloaterTexturePicker::onBtnUpload(void* userdata)  	/* 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::getInstance()->getFilename(tracking_id); - -	if (!filename.empty()) -	{ -		LLFloaterReg::showInstance("upload_image", LLSD(filename)); -	} +    LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); +    LLUUID tracking_id = data["id"]; +    S32 asset_type = data["type"].asInteger(); + +    if (LLAssetType::AT_MATERIAL == asset_type) +    { +        std::string filename = LLLocalGLTFMaterialMgr::getInstance()->getFilename(tracking_id); +        if (!filename.empty()) +        { +            LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor"); +            if (me) +            { +                me->loadMaterialFromFile(filename); +            } +        } +    } +    else +    { +        std::string filename = LLLocalBitmapMgr::getInstance()->getFilename(tracking_id); +        if (!filename.empty()) +        { +            LLFloaterReg::showInstance("upload_image", LLSD(filename)); +        } +    }  }  //static @@ -900,8 +1007,20 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata)  	if (has_selection)  	{ -		LLUUID tracking_id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel(LOCAL_TRACKING_ID_COLUMN);  -		LLUUID inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); +        LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); +        LLUUID tracking_id = data["id"]; +        S32 asset_type = data["type"].asInteger(); +        LLUUID inworld_id; + +        if (LLAssetType::AT_MATERIAL == asset_type) +        { +            inworld_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id); +        } +        else +        { +            inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); +        } +  		if (self->mSetImageAssetIDCallback)  		{  			self->mSetImageAssetIDCallback(inworld_id); @@ -1075,6 +1194,38 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  	mInventoryPanel->setFilterSubString(search_string);  } +void LLFloaterTexturePicker::onSelectTextureMaterials(LLUICtrl* ctrl, void *userdata) +{ +    LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata; +    int index = self->mTextureMaterialsCombo->getValue().asInteger(); + +    // IMPORTANT: make sure these match the entries in floater_texture_ctrl.xml  +    // for the textures_material_combo combo box +    const int textures_and_materials = 0; +    const int textures_only = 1; +    const int materials_only = 2; + +    U32 filter_types = 0x0; + +    if (index == textures_and_materials) +    { +        filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; +        filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; +        filter_types |= 0x1 << LLInventoryType::IT_MATERIAL; +    } +    else if (index == textures_only) +    { +        filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; +        filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; +    } +    else if (index == materials_only) +    { +        filter_types |= 0x1 << LLInventoryType::IT_MATERIAL; +    } + +    self->mInventoryPanel->setFilterTypes(filter_types); +} +  void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled)  {      mModeSelector->setEnabledByValue(1, enabled); @@ -1102,6 +1253,36 @@ void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled)  	onModeSelect(0, this);  } +void LLFloaterTexturePicker::onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle) +{ +    std::vector<std::string>::const_iterator iter = filenames.begin(); +    while (iter != filenames.end()) +    { +        if (!iter->empty()) +        { +            std::string temp_exten = gDirUtilp->getExtension(*iter); +            if (temp_exten == "gltf" || temp_exten == "glb") +            { +                LLLocalGLTFMaterialMgr::getInstance()->addUnit(*iter); +            } +            else +            { +                LLLocalBitmapMgr::getInstance()->addUnit(*iter); +            } +        } +        iter++; +    } + +    // Todo: this should referesh all pickers, not just a current one +    if (!handle.isDead()) +    { +        LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get(); +        self->mLocalScrollCtrl->clearRows(); +        LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); +        LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); +    } +} +  void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )  {  	LLUUID inventory_item_id = findItemID(te.getID(), TRUE); @@ -1148,6 +1329,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)  	mNeedsRawImageData( FALSE ),  	mValid( TRUE ),  	mShowLoadingPlaceholder( TRUE ), +	mOpenTexPreview(false),  	mImageAssetID(p.image_id),  	mDefaultImageAssetID(p.default_image_id),  	mDefaultImageName(p.default_image_name), @@ -1404,12 +1586,31 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)  	if (!handled && mBorder->parentPointInView(x, y))  	{ -		showPicker(FALSE); -		//grab textures first... -		LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); -		//...then start full inventory fetch. -		LLInventoryModelBackgroundFetch::instance().start(); -		handled = TRUE; +		if (!mOpenTexPreview) +		{ +			showPicker(FALSE); +			//grab textures first... +			LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); +			//...then start full inventory fetch. +			LLInventoryModelBackgroundFetch::instance().start(); +			handled = TRUE; +		} +		else +		{ +			if (getImageAssetID().notNull()) +			{ +				LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", getValue()); +				if (preview_texture && !preview_texture->isDependent()) +				{ +					LLFloater* root_floater = gFloaterView->getParentFloater(this); +					if (root_floater) +					{ +						root_floater->addDependentFloater(preview_texture); +						preview_texture->hideCtrlButtons(); +					} +				} +			} +		}  	}  	return handled; @@ -1433,9 +1634,9 @@ void LLTextureCtrl::onFloaterClose()  void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  { -	LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); +    LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); -	if( floaterp && getEnabled()) +    if( floaterp && getEnabled())  	{  		if (op == TEXTURE_CANCEL)  			mViewModel->resetDirty(); @@ -1456,15 +1657,64 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  			}  			else  			{ -			mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); -			LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL; -			mImageAssetID = floaterp->getAssetID(); -			LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL; +			    mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); +			    LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL; +			    mImageAssetID = floaterp->getAssetID(); +			    LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL;  			}  			if (op == TEXTURE_SELECT && mOnSelectCallback)  			{ -				mOnSelectCallback( this, LLSD() ); +                // determine if the selected item in inventory is a material +                // by finding the item in inventory and inspecting its (IT_) type +                LLUUID item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE); +                LLInventoryItem* item = gInventory.getItem(item_id); +                if (item) +                { +                    if (item->getInventoryType() == LLInventoryType::IT_MATERIAL) +                    { +                        // ask the selection manager for the list of selected objects +                        // to which the material will be applied. +                        LLObjectSelectionHandle selectedObjectsHandle = LLSelectMgr::getInstance()->getSelection(); +                        if (selectedObjectsHandle.notNull()) +                        { +                            LLObjectSelection* selectedObjects = selectedObjectsHandle.get(); +                            if (!selectedObjects->isEmpty()) +                            { +                                // we have a selection - iterate over it +                                for (LLObjectSelection::valid_iterator obj_iter = selectedObjects->valid_begin(); +                                        obj_iter != selectedObjects->valid_end(); +                                            ++obj_iter) +                                { +                                    LLSelectNode* object = *obj_iter; +                                    LLViewerObject* viewer_object = object->getObject(); +                                    if (viewer_object) +                                    { +                                        // the asset ID of the material we want to apply +                                        // the the selected objects +                                        LLUUID asset_id = item->getAssetUUID(); + +                                        // iterate over the faces in the object +                                        // TODO: consider the case where user has  +                                        // selected only certain faces +                                        S32 num_faces = viewer_object->getNumTEs(); +                                        for (S32 face = 0; face < num_faces; face++) +                                        { +                                            viewer_object->setRenderMaterialID(face, asset_id); +                                            dialog_refresh_all(); +                                        } +                                        viewer_object->sendTEUpdate(); +                                    } +                                } +                            } +                        } +                    } +                } +                else +                // original behavior for textures, not materials +                { +                    mOnSelectCallback(this, LLSD()); +                }  			}  			else if (op == TEXTURE_CANCEL && mOnCancelCallback)  			{ @@ -1475,8 +1725,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  				// If the "no_commit_on_selection" parameter is set  				// we commit only when user presses OK in the picker  				// (i.e. op == TEXTURE_SELECT) or texture changes via DnD. -				if (mCommitOnSelection || op == TEXTURE_SELECT) -					onCommit(); +                if (mCommitOnSelection || op == TEXTURE_SELECT) +                { +                    onCommit(); +                }  			}  		}  	} @@ -1609,7 +1861,7 @@ void LLTextureCtrl::draw()  	}  	else//mImageAssetID == LLUUID::null  	{ -		mTexturep = NULL; +		mTexturep = NULL;   	}  	// Border diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 1475c8c6fc..1bfbb0d1be 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -52,6 +52,16 @@ class LLViewerFetchedTexture;  typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback;  typedef boost::function<void (LLInventoryItem*)> texture_selected_callback; +// Helper functions for UI that work with picker +bool get_is_predefined_texture(LLUUID asset_id); + +// texture picker works by asset ids since objects normaly do +// not retain inventory ids as result these functions are looking +// for textures in inventory by asset ids +// This search can be performance unfriendly and doesn't warranty +// that the texture is original source of asset +LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); +bool get_can_copy_texture(LLUUID image_id);  //////////////////////////////////////////////////////////////////////////////////////////  // LLTextureCtrl @@ -159,6 +169,8 @@ public:  	void			setBlankImageAssetID( const LLUUID& id )	{ mBlankImageAssetID = id; }  	const LLUUID&	getBlankImageAssetID() const { return mBlankImageAssetID; } +	void			setOpenTexPreview(bool open_preview) { mOpenTexPreview = open_preview; } +  	void			setCaption(const std::string& caption);  	void			setCanApplyImmediately(BOOL b); @@ -238,6 +250,8 @@ private:  	BOOL					 	mShowLoadingPlaceholder;  	std::string				 	mLoadingPlaceholderString;  	S32						 	mLabelWidth; +	bool						mOpenTexPreview; +	BOOL						mBakeTextureEnabled;  };  ////////////////////////////////////////////////////////////////////////////////////////// @@ -330,9 +344,13 @@ public:  	static void		onBakeTextureSelect(LLUICtrl* ctrl, void *userdata);  	static void		onHideBaseMeshRegionCheck(LLUICtrl* ctrl, void *userdata); +    static void     onSelectTextureMaterials(LLUICtrl* ctrl, void *userdata); +  	void 			setLocalTextureEnabled(BOOL enabled);  	void 			setBakeTextureEnabled(BOOL enabled); +    static void		onPickerCallback(const std::vector<std::string>& filenames, LLHandle<LLFloater> handle); +  protected:  	LLPointer<LLViewerTexture> mTexturep;  	LLView*				mOwner; @@ -355,6 +373,7 @@ protected:  	BOOL				mActive;  	LLFilterEditor*		mFilterEdit; +    LLComboBox*         mTextureMaterialsCombo;  	LLInventoryPanel*	mInventoryPanel;  	PermissionMask		mImmediateFilterPermMask;  	PermissionMask		mDnDFilterPermMask; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 35e4bb03ac..dc10e42446 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -62,8 +62,6 @@  #include "llcorehttputil.h"  #include "llhttpretrypolicy.h" -bool LLTextureFetchDebugger::sDebuggerEnabled = false ; -  LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheHit("texture_cache_hit");  LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheAttempt("texture_cache_attempt");  LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheHitRate("texture_cache_hits"); @@ -213,35 +211,17 @@ const std::string sTesterName("TextureFetchTester");  //  // Worker State Machine  // -// (ASCII art needed) -// -// -// Priority Scheme -// -// [PRIORITY_LOW, PRIORITY_NORMAL)   - for WAIT_HTTP_RESOURCE state -//									   and other wait states -// [PRIORITY_HIGH, PRIORITY_URGENT)  - External event delivered, -//                                     rapidly transitioning through states, -//                                     no waiting allowed -// -// By itself, the above work queue model would fail the concurrency -// and liveness requirements of the interface.  A high priority -// request could find itself on the head and stalled for external -// reasons (see VWR-28996).  So a few additional constraints are -// required to keep things running: -// * Anything that can make forward progress must be kept at a -//   higher priority than anything that can't. -// * On completion of external events, the associated request -//   needs to be elevated beyond the normal range to handle -//   any data delivery and release any external resource. -// -// This effort is made to keep higher-priority entities moving -// forward in their state machines at every possible step of -// processing.  It's not entirely proven that this produces the -// experiencial benefits promised. +// "doWork" will be executed for a given worker on its respective +// LLQueuedThread.  If doWork returns true, the worker is treated  +// as completed.  If doWork returns false, the worker will be  +// put on the back of the work queue at the start of the next iteration +// of the mainloop.  If a worker is waiting on a resource, it should +// return false as soon as possible and not block to avoid starving +// other workers of cpu cycles.  // +  //////////////////////////////////////////////////////////////////////////////  // Tuning/Parameterization Constants @@ -262,8 +242,8 @@ static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000;  //////////////////////////////////////////////////////////////////////////////  namespace  { -    // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker and -    // the LLTextureFetchDebugger) in a smart pointer below for passage into  +    // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker) +    // in a smart pointer below for passage into       // the LLCore::Http libararies. When the smart pointer is destroyed,  no       // action will be taken since we do not in these cases want the object to       // be destroyed at the end of the call. @@ -301,7 +281,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler  {  	friend class LLTextureFetch; -	friend class LLTextureFetchDebugger;  private:  	class CacheReadResponder : public LLTextureCache::ReadResponder @@ -386,14 +365,7 @@ private:  		bool operator()(const LLTextureFetchWorker* lhs, const LLTextureFetchWorker* rhs) const  		{  			// greater priority is "less" -			const F32 lpriority = lhs->mImagePriority; -			const F32 rpriority = rhs->mImagePriority; -			if (lpriority > rpriority) // higher priority -				return true; -			else if (lpriority < rpriority) -				return false; -			else -				return lhs < rhs; +            return lhs->mImagePriority > rhs->mImagePriority;  		}  	}; @@ -484,6 +456,9 @@ private:  	// Locks:  Mw  	void resetFormattedData(); +    // get the relative priority of this worker (should map to max virtual size) +    F32 getImagePriority() const; +  	// Locks:  Mw  	void setImagePriority(F32 priority); @@ -500,9 +475,6 @@ private:  	// Locks:  Mw  	void setupPacketData(); -	// Locks:  Mw (ctor invokes without lock) -	U32 calcWorkPriority(); -	  	// Locks:  Mw  	void removeFromCache(); @@ -573,16 +545,13 @@ private:  	LLHost mHost;  	std::string mUrl;  	U8 mType; -	F32 mImagePriority; -	U32 mWorkPriority; +	F32 mImagePriority; // should map to max virtual size  	F32 mRequestedPriority;  	S32 mDesiredDiscard;  	S32 mSimRequestedDiscard;  	S32 mRequestedDiscard;      S32 mLoadedDiscard;      S32 mDecodedDiscard; -	S32 mFullWidth; -	S32 mFullHeight;  	LLFrameTimer mRequestedDeltaTimer;  	LLFrameTimer mFetchDeltaTimer;  	LLTimer mCacheReadTimer; @@ -923,7 +892,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mHost(host),  	  mUrl(url),  	  mImagePriority(priority), -	  mWorkPriority(0),  	  mRequestedPriority(0.f),  	  mDesiredDiscard(-1),  	  mSimRequestedDiscard(-1), @@ -970,17 +938,15 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mCacheReadCount(0U),  	  mCacheWriteCount(0U),  	  mResourceWaitCount(0U), -	  mFetchRetryPolicy(10.0,3600.0,2.0,10) +	  mFetchRetryPolicy(10.f,3600.f,2.f,10)  {  	mCanUseNET = mUrl.empty() ; -	calcWorkPriority();  	mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL;  // 	LL_INFOS(LOG_TXT) << "Create: " << mID << " mHost:" << host << " Discard=" << discard << LL_ENDL;  	if (!mFetcher->mDebugPause)  	{ -		U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; -		addWork(0, work_priority ); +		addWork(0);  	}  	setDesiredDiscard(discard, size);  } @@ -1071,16 +1037,6 @@ void LLTextureFetchWorker::setupPacketData()  }  // Locks:  Mw (ctor invokes without lock) -U32 LLTextureFetchWorker::calcWorkPriority() -{ - 	//llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerFetchedTexture::maxDecodePriority()); -	static const F32 PRIORITY_SCALE = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerFetchedTexture::maxDecodePriority(); - -	mWorkPriority = llmin((U32)LLWorkerThread::PRIORITY_LOWBITS, (U32)(mImagePriority * PRIORITY_SCALE)); -	return mWorkPriority; -} - -// Locks:  Mw (ctor invokes without lock)  void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)  {  	bool prioritize = false; @@ -1088,11 +1044,9 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)  	{  		if (!haveWork())  		{ -			calcWorkPriority();  			if (!mFetcher->mDebugPause)  			{ -				U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; -				addWork(0, work_priority); +				addWork(0);  			}  		}  		else if (mDesiredDiscard < discard) @@ -1111,23 +1065,13 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)  	if ((prioritize && mState == INIT) || mState == DONE)  	{  		setState(INIT); -		U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; -		setPriority(work_priority);  	}  }  // Locks:  Mw  void LLTextureFetchWorker::setImagePriority(F32 priority)  { -// 	llassert_always(priority >= 0 && priority <= LLViewerTexture::maxDecodePriority()); -	F32 delta = fabs(priority - mImagePriority); -	if (delta > (mImagePriority * .05f) || mState == DONE) -	{ -		mImagePriority = priority; -		calcWorkPriority(); -		U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS); -		setPriority(work_priority); -	} +	mImagePriority = priority; //should map to max virtual size, abort if zero  }  // Locks:  Mw @@ -1147,6 +1091,11 @@ void LLTextureFetchWorker::resetFormattedData()  	mHaveAllData = FALSE;  } +F32 LLTextureFetchWorker::getImagePriority() const +{ +    return mImagePriority; +} +  // Threads:  Tmain  void LLTextureFetchWorker::startWork(S32 param)  { @@ -1156,7 +1105,7 @@ void LLTextureFetchWorker::startWork(S32 param)  // Threads:  Ttf  bool LLTextureFetchWorker::doWork(S32 param)  { -    LL_PROFILE_ZONE_SCOPED; +    LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;  	if (gNonInteractive)  	{  		return true; @@ -1171,20 +1120,23 @@ bool LLTextureFetchWorker::doWork(S32 param)  	{  		if (mState < DECODE_IMAGE)  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state < decode");  			return true; // abort  		}  	} -	if(mImagePriority < F_ALMOST_ZERO) +	if (mImagePriority < F_ALMOST_ZERO)  	{  		if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR)  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - priority < 0");  			LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL;  			return true; // abort  		}  	}  	if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state > cache_post");  		//nowhere to get data, abort.  		LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL;  		return true ; @@ -1206,6 +1158,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == INIT)  	{		 +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - INIT");  		mStateTimer.reset();  		mFetchTimer.reset();  		for(auto i : LOGGED_STATES)  @@ -1247,15 +1200,16 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == LOAD_FROM_TEXTURE_CACHE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_TEXTURE_CACHE");  		if (mCacheReadHandle == LLTextureCache::nullHandle())  		{ -			U32 cache_priority = mWorkPriority;  			S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;  			S32 size = mDesiredSize - offset;  			if (size <= 0)  			{  				setState(CACHE_POST); -				return false; +                return doWork(param); +                // return false;  			}  			mFileSize = 0;  			mLoaded = FALSE;			 @@ -1264,35 +1218,28 @@ bool LLTextureFetchWorker::doWork(S32 param)  			if (mUrl.compare(0, 7, "file://") == 0)  			{ -				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it -  				// read file from local disk  				++mCacheReadCount;  				std::string filename = mUrl.substr(7, std::string::npos);  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadTimer.reset();   -				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, -																		  offset, size, responder); +				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, offset, size, responder);  			}  			else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache())  			{ -				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it -  				++mCacheReadCount;  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadTimer.reset(); -				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, +				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID,  																		  offset, size, responder);;  			}  			else if(!mUrl.empty() && mCanUseHTTP)  			{ -				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  				setState(WAIT_HTTP_RESOURCE);  			}  			else  			{ -				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  				setState(LOAD_FROM_NETWORK);  			}  		} @@ -1325,6 +1272,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == CACHE_POST)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - CACHE_POST");  		mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;  		// Successfully loaded  		if ((mCachedSize >= mDesiredSize) || mHaveAllData) @@ -1366,6 +1314,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == LOAD_FROM_NETWORK)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_NETWORK");  		// Check for retries to previous server failures.  		F32 wait_seconds;  		if (mFetchRetryPolicy.shouldRetry(wait_seconds)) @@ -1399,7 +1348,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				{  					if (mFTType != FTT_DEFAULT)  					{ -						LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL; +                        LL_WARNS(LOG_TXT) << "Trying to fetch a texture of non-default type by UUID. This probably won't work!" << LL_ENDL;  					}  					setUrl(http_url + "/?texture_id=" + mID.asString().c_str());  					LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; @@ -1427,7 +1376,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  		if (mCanUseHTTP && !mUrl.empty())  		{  			setState(WAIT_HTTP_RESOURCE); -			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  			if(mWriteToCacheState != NOT_WRITE)  			{  				mWriteToCacheState = CAN_WRITE ; @@ -1444,25 +1392,19 @@ bool LLTextureFetchWorker::doWork(S32 param)  			mSentRequest = QUEUED;  			mFetcher->addToNetworkQueue(this);  			recordTextureStart(false); -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); -			  			return false;  		}  		else  		{  			// Shouldn't need to do anything here -			//llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); -			// Make certain this is in the network queue -			//mFetcher->addToNetworkQueue(this); -			//recordTextureStart(false); -			//setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - +			//llassert(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());  			return false;  		}  	}  	if (mState == LOAD_FROM_SIMULATOR)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_SIMULATOR");  		if (mFormattedImage.isNull())  		{  			mFormattedImage = new LLImageJ2C; @@ -1492,7 +1434,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL;  				return true; // failed  			} -			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +  			if (mLoadedDiscard < 0)  			{  				LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1506,7 +1448,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  		else  		{  			mFetcher->addToNetworkQueue(this); // failsafe -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);  			recordTextureStart(false);  		}  		return false; @@ -1514,6 +1455,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WAIT_HTTP_RESOURCE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE");  		// NOTE:  		// control the number of the http requests issued for:  		// 1, not openning too many file descriptors at the same time; @@ -1524,7 +1466,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  		if (mFetcher->getHttpWaitersCount() || ! acquireHttpSemaphore())  		{  			setState(WAIT_HTTP_RESOURCE2); -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);  			mFetcher->addHttpWaiter(this->mID);  			++mResourceWaitCount;  			return false; @@ -1538,12 +1479,14 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WAIT_HTTP_RESOURCE2)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE2");  		// Just idle it if we make it to the head...  		return false;  	}  	if (mState == SEND_HTTP_REQ)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - SEND_HTTP_REQ");  		// Also used in llmeshrepository  		static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false); @@ -1566,7 +1509,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  				{  					// We already have all the data, just decode it  					mLoadedDiscard = mFormattedImage->getDiscardLevel(); -					setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  					if (mLoadedDiscard < 0)  					{  						LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1574,7 +1516,8 @@ bool LLTextureFetchWorker::doWork(S32 param)  					}  					setState(DECODE_IMAGE);  					releaseHttpSemaphore(); -					return false; +					//return false; +                    return doWork(param);  				}  				else  				{ @@ -1635,7 +1578,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  			// by people with questionable ISPs or networking gear that  			// doesn't handle these well.  			mHttpHandle = mFetcher->mHttpRequest->requestGet(mHttpPolicyClass, -															 mWorkPriority,  															 mUrl,  															 options,  															 mFetcher->mHttpHeaders, @@ -1644,7 +1586,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  		else  		{  			mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, -																	  mWorkPriority,  																	  mUrl,  																	  mRequestedOffset,  																	  (mRequestedOffset + mRequestedSize) > HTTP_REQUESTS_RANGE_END_MAX @@ -1669,7 +1610,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  		mHttpActive = true;  		mFetcher->addToHTTPQueue(mID);  		recordTextureStart(true); -		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);  		setState(WAIT_HTTP_REQ);	  		// fall through @@ -1677,6 +1617,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WAIT_HTTP_REQ)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_REQ");  		// *NOTE:  As stated above, all transitions out of this state should  		// call releaseHttpSemaphore().  		if (mLoaded) @@ -1708,9 +1649,9 @@ bool LLTextureFetchWorker::doWork(S32 param)  						setState(INIT);  						mCanUseHTTP = false;  						mUrl.clear(); -						setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  						releaseHttpSemaphore(); -						return false; +						//return false; +                        return doWork(param);  					}  				}  				else if (http_service_unavail == mGetStatus) @@ -1730,7 +1671,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  									  << LL_ENDL;  				} -				if (mFTType != FTT_SERVER_BAKE) +                if (mFTType != FTT_SERVER_BAKE && mFTType != FTT_MAP_TILE)  				{  					mUrl.clear();  				} @@ -1738,7 +1679,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  				{  					// Use available data  					mLoadedDiscard = mFormattedImage->getDiscardLevel(); -					setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  					if (mLoadedDiscard < 0)  					{  						LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1746,7 +1686,8 @@ bool LLTextureFetchWorker::doWork(S32 param)  					}  					setState(DECODE_IMAGE);  					releaseHttpSemaphore(); -					return false;  +					//return false;  +                    return doWork(param);  				}  				// Fail harder @@ -1863,9 +1804,9 @@ bool LLTextureFetchWorker::doWork(S32 param)  			{  				mWriteToCacheState = SHOULD_WRITE ;  			} -			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  			releaseHttpSemaphore(); -			return false; +			//return false; +            return doWork(param);  		}  		else  		{ @@ -1875,17 +1816,16 @@ bool LLTextureFetchWorker::doWork(S32 param)  			// an enormous amount of time to load textures.  We'll revisit the  			// various possible timeout components (total request time, connection  			// time, I/O time, with and without retries, etc.) in the future. - -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); +			  			return false;  		}  	}  	if (mState == DECODE_IMAGE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE");  		static LLCachedControl<bool> textures_decode_disabled(gSavedSettings, "TextureDecodeDisabled", false); -		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it  		if (textures_decode_disabled)  		{  			// for debug use, don't decode @@ -1924,25 +1864,20 @@ bool LLTextureFetchWorker::doWork(S32 param)  		mAuxImage = NULL;  		llassert_always(mFormattedImage.notNull());  		S32 discard = mHaveAllData ? 0 : mLoadedDiscard; -		U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;  		mDecoded  = FALSE;  		setState(DECODE_IMAGE_UPDATE);  		LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard  						   << " All Data: " << mHaveAllData << LL_ENDL; -		mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, +		mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux,  																  new DecodeResponder(mFetcher, mID, this));  		// fall though  	}  	if (mState == DECODE_IMAGE_UPDATE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE_UPDATE");  		if (mDecoded)  		{ -			if(mFetcher->getFetchDebugger() && !mInLocalCache) -			{ -				mFetcher->getFetchDebugger()->addHistoryEntry(this); -			} -              mDecodeTime = mDecodeTimer.getElapsedTimeF32();  			if (mDecodedDiscard < 0) @@ -1954,9 +1889,9 @@ bool LLTextureFetchWorker::doWork(S32 param)  					llassert_always(mDecodeHandle == 0);  					mFormattedImage = NULL;  					++mRetryAttempt; -					setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  					setState(INIT); -					return false; +					//return false; +                    return doWork(param);  				}  				else  				{ @@ -1969,7 +1904,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  				llassert_always(mRawImage.notNull());  				LL_DEBUGS(LOG_TXT) << mID << ": Decoded. Discard: " << mDecodedDiscard  								   << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; -				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  				setState(WRITE_TO_CACHE);  			}  			// fall through @@ -1982,12 +1916,14 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WRITE_TO_CACHE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WRITE_TO_CACHE");  		if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull())  		{  			// If we're in a local cache or we didn't actually receive any new data,  			// or we failed to load anything, skip  			setState(DONE); -			return false; +			//return false; +            return doWork(param);  		}  		S32 datasize = mFormattedImage->getDataSize();  		if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed. @@ -2002,8 +1938,6 @@ bool LLTextureFetchWorker::doWork(S32 param)  			}  		}  		llassert_always(datasize); -		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it -		U32 cache_priority = mWorkPriority;  		mWritten = FALSE;  		setState(WAIT_ON_WRITE);  		++mCacheWriteCount; @@ -2014,7 +1948,7 @@ bool LLTextureFetchWorker::doWork(S32 param)          // So make sure users of getRequestFinished() does not attempt to modify image while          // fetcher is working  		mCacheWriteTimer.reset(); -		mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority, +		mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID,  																  mFormattedImage->getData(), datasize,  																  mFileSize, mRawImage, mDecodedDiscard, responder);  		// fall through @@ -2022,6 +1956,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == WAIT_ON_WRITE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_ON_WRITE");  		if (writeToCacheComplete())  		{  			mCacheWriteTime = mCacheWriteTimer.getElapsedTimeF32(); @@ -2043,6 +1978,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  	if (mState == DONE)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DONE");  		if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard)  		{  			// More data was requested, return to INIT @@ -2050,12 +1986,11 @@ bool LLTextureFetchWorker::doWork(S32 param)  			LL_DEBUGS(LOG_TXT) << mID << " more data requested, returning to INIT: "   							   << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard  							   << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; -			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); -			return false; +			// return false; +            return doWork(param);  		}  		else  		{ -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);              mFetchTime = mFetchTimer.getElapsedTimeF32();  			return true;  		} @@ -2068,6 +2003,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  // virtual  void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)  { +    LL_PROFILE_ZONE_SCOPED;  	static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog", false);  	static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator", false);  	static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic", false) ; @@ -2177,9 +2113,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe  // Threads:  Tmain  void LLTextureFetchWorker::endWork(S32 param, bool aborted)  { +	LL_PROFILE_ZONE_SCOPED;  	if (mDecodeHandle != 0)  	{ -		mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false); +		// LL::ThreadPool has no operation to cancel a particular work item  		mDecodeHandle = 0;  	}  	mFormattedImage = NULL; @@ -2192,6 +2129,7 @@ void LLTextureFetchWorker::endWork(S32 param, bool aborted)  // virtual  void LLTextureFetchWorker::finishWork(S32 param, bool completed)  { +    LL_PROFILE_ZONE_SCOPED;  	// The following are required in case the work was aborted  	if (mCacheReadHandle != LLTextureCache::nullHandle())  	{ @@ -2445,7 +2383,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,  	}  	mLoaded = TRUE; -	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  	if (LLViewerStatsRecorder::instanceExists())  	{ @@ -2461,6 +2398,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,  void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* image,  											 S32 imagesize, BOOL islocal)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	LLMutexLock lock(&mWorkMutex);										// +Mw  	if (mState != LOAD_FROM_TEXTURE_CACHE)  	{ @@ -2480,7 +2418,6 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima  		}  	}  	mLoaded = TRUE; -	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  }																		// -Mw  // Threads:  Ttc @@ -2493,7 +2430,6 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success)  		return;  	}  	mWritten = TRUE; -	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  }																		// -Mw  ////////////////////////////////////////////////////////////////////////////// @@ -2532,7 +2468,6 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag  	}  	mDecoded = TRUE;  // 	LL_INFOS(LOG_TXT) << mID << " : DECODE COMPLETE " << LL_ENDL; -	setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  }																		// -Mw  ////////////////////////////////////////////////////////////////////////////// @@ -2595,7 +2530,17 @@ void LLTextureFetchWorker::recordTextureDone(bool is_http, F64 byte_count)  //////////////////////////////////////////////////////////////////////////////  // public -LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode) +std::string LLTextureFetch::getStateString(S32 state) +{ +    if (state < 0 || state > sizeof(e_state_name) / sizeof(char*)) +    { +        return llformat("%d", state); +    } + +    return e_state_name[state]; +} + +LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode)  	: LLWorkerThread("TextureFetch", threaded, true),  	  mDebugCount(0),  	  mDebugPause(FALSE), @@ -2604,7 +2549,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image  	  mQueueMutex(),  	  mNetworkQueueMutex(),  	  mTextureCache(cache), -	  mImageDecodeThread(imagedecodethread),  	  mTextureBandwidth(0),  	  mHTTPTextureBits(0),  	  mTotalHTTPRequests(0), @@ -2619,10 +2563,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image  	  mTotalCacheReadCount(0U),  	  mTotalCacheWriteCount(0U),  	  mTotalResourceWaitCount(0U), -	  mFetchDebugger(NULL),  	  mFetchSource(LLTextureFetch::FROM_ALL),  	  mOriginFetchSource(LLTextureFetch::FROM_ALL), -	  mFetcherLocked(FALSE),  	  mTextureInfoMainThread(false)  {  	mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); @@ -2643,21 +2585,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image  	mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER;  	mHttpSemaphore = 0; -	// Conditionally construct debugger object after 'this' is -	// fully initialized. -	LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); -	if(LLTextureFetchDebugger::isEnabled()) -	{ -		mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ; -		mFetchSource = (e_tex_source)gSavedSettings.getS32("TextureFetchSource"); -		if(mFetchSource < 0 && mFetchSource >= INVALID_SOURCE) -		{ -			mFetchSource = LLTextureFetch::FROM_ALL; -			gSavedSettings.setS32("TextureFetchSource", 0); -		} -		mOriginFetchSource = mFetchSource; -	} -  	// If that test log has ben requested but not yet created, create it  	if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))  	{ @@ -2686,19 +2613,13 @@ LLTextureFetch::~LLTextureFetch()  	delete mHttpRequest;  	mHttpRequest = NULL; -	delete mFetchDebugger; -	mFetchDebugger = NULL; -	  	// ~LLQueuedThread() called here  }  bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,  								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)  { -	if(mFetcherLocked) -	{ -		return false; -	} +    LL_PROFILE_ZONE_SCOPED;  	if (mDebugPause)  	{  		return false; @@ -2773,6 +2694,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const  			return false; // need to wait for previous aborted request to complete  		}  		worker->lockWorkMutex();										// +Mw +        if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) { +			worker->unlockWorkMutex();									// -Mw + +            return false; // similar request has failed or is in a transitional state +        }  		worker->mActiveCount++;  		worker->mNeedsAux = needs_aux;  		worker->setImagePriority(priority); @@ -2786,7 +2712,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const  			worker->setState(LLTextureFetchWorker::INIT);  			worker->unlockWorkMutex();									// -Mw -			worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); +			worker->addWork(0);  		}  		else  		{ @@ -2818,6 +2744,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const  // protected  void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)  { +    LL_PROFILE_ZONE_SCOPED;  	lockQueue();														// +Mfq  	bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ;  	unlockQueue();														// -Mfq @@ -2839,6 +2766,7 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)  // Threads:  T*  void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel)  { +    LL_PROFILE_ZONE_SCOPED;  	LLMutexLock lock(&mNetworkQueueMutex);								// +Mfnq  	size_t erased = mNetworkQueue.erase(worker->mID);  	if (cancel && erased > 0) @@ -2852,6 +2780,7 @@ void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool c  // protected  void LLTextureFetch::addToHTTPQueue(const LLUUID& id)  { +    LL_PROFILE_ZONE_SCOPED;  	LLMutexLock lock(&mNetworkQueueMutex);								// +Mfnq  	mHTTPTextureQueue.insert(id);  	mTotalHTTPRequests++; @@ -2860,6 +2789,7 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id)  // Threads:  T*  void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_size)  { +    LL_PROFILE_ZONE_SCOPED;  	LLMutexLock lock(&mNetworkQueueMutex);								// +Mfnq  	mHTTPTextureQueue.erase(id);  	mHTTPTextureBits += received_size; // Approximate - does not include header bits	 @@ -2872,6 +2802,7 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_siz  // Threads:  T*  void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)  { +    LL_PROFILE_ZONE_SCOPED;  	lockQueue();														// +Mfq  	LLTextureFetchWorker* worker = getWorkerAfterLock(id);  	if (worker) @@ -2898,6 +2829,7 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)  // Threads:  T*  void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)  { +    LL_PROFILE_ZONE_SCOPED;  	if(!worker)  	{  		return; @@ -2967,6 +2899,7 @@ U32 LLTextureFetch::getTotalNumHTTPRequests()  // Locks:  Mfq  LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)  { +    LL_PROFILE_ZONE_SCOPED;  	LLTextureFetchWorker* res = NULL;  	map_t::iterator iter = mRequestMap.find(id);  	if (iter != mRequestMap.end()) @@ -2990,6 +2923,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,  										LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,  										LLCore::HttpStatus& last_http_get_status)  { +    LL_PROFILE_ZONE_SCOPED;  	bool res = false;  	LLTextureFetchWorker* worker = getWorker(id);  	if (worker) @@ -3004,7 +2938,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,  			if (!mDebugPause)  			{  // 				LL_WARNS(LOG_TXT) << "Adding work for inactive worker: " << id << LL_ENDL; -				worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); +				worker->addWork(0);  			}  		}  		else if (worker->checkWork()) @@ -3080,16 +3014,19 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,  // Threads:  T*  bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)  { -	bool res = false; -	LLTextureFetchWorker* worker = getWorker(id); -	if (worker) -	{ -		worker->lockWorkMutex();										// +Mw -		worker->setImagePriority(priority); -		worker->unlockWorkMutex();										// -Mw -		res = true; -	} -	return res; +    LL_PROFILE_ZONE_SCOPED; +    mRequestQueue.tryPost([=]() +        { +            LLTextureFetchWorker* worker = getWorker(id); +            if (worker) +            { +                worker->lockWorkMutex();										// +Mw +                worker->setImagePriority(priority); +                worker->unlockWorkMutex();										// -Mw +            } +        }); +	 +	return true;  }  // Replicates and expands upon the base class's @@ -3106,6 +3043,7 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)  //virtual  S32 LLTextureFetch::getPending()  { +    LL_PROFILE_ZONE_SCOPED;  	S32 res;  	lockData();															// +Ct      { @@ -3139,7 +3077,7 @@ bool LLTextureFetch::runCondition()  	}																	// -Mfq  	return ! (have_no_commands -			  && (mRequestQueue.empty() && mIdleThread));		// From base class +			  && (mRequestQueue.size() == 0 && mIdleThread));		// From base class  }  ////////////////////////////////////////////////////////////////////////////// @@ -3147,6 +3085,7 @@ bool LLTextureFetch::runCondition()  // Threads:  Ttf  void LLTextureFetch::commonUpdate()  { +    LL_PROFILE_ZONE_SCOPED;  	// Update low/high water levels based on pipelining.  We pick  	// up setting eventually, so the semaphore/request level can  	// fall outside the [0..HIGH_WATER] range.  Expect that. @@ -3183,6 +3122,7 @@ void LLTextureFetch::commonUpdate()  //virtual  S32 LLTextureFetch::update(F32 max_time_ms)  { +    LL_PROFILE_ZONE_SCOPED;  	static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0);  	{ @@ -3213,11 +3153,6 @@ S32 LLTextureFetch::update(F32 max_time_ms)  		commonUpdate();  	} -	if (mFetchDebugger) -	{ -		mFetchDebugger->tryToStopDebug(); //check if need to stop debugger. -	} -  	return res;  } @@ -3233,18 +3168,6 @@ void LLTextureFetch::shutDownTextureCacheThread()  	}  } -// called in the MAIN thread after the ImageDecodeThread shuts down. -// -// Threads:  Tmain -void LLTextureFetch::shutDownImageDecodeThread()  -{ -	if(mImageDecodeThread) -	{ -		llassert_always(mImageDecodeThread->isQuitting() || mImageDecodeThread->isStopped()) ; -		mImageDecodeThread = NULL ; -	} -} -  // Threads:  Ttf  void LLTextureFetch::startThread()  { @@ -3266,6 +3189,7 @@ void LLTextureFetch::endThread()  // Threads:  Ttf  void LLTextureFetch::threadedUpdate()  { +    LL_PROFILE_ZONE_SCOPED;  	llassert_always(mHttpRequest);  #if 0 @@ -3301,6 +3225,7 @@ void LLTextureFetch::threadedUpdate()  // Threads:  Tmain  void LLTextureFetch::sendRequestListToSimulators()  { +    LL_PROFILE_ZONE_SCOPED;  	// All requests  	const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps @@ -3351,7 +3276,6 @@ void LLTextureFetch::sendRequestListToSimulators()  				req->mLastPacket >= req->mTotalPackets-1)  			{  				// We have all the packets... make sure this is high priority -// 			req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);  				continue;  			}  			F32 elapsed = req->mRequestedDeltaTimer.getElapsedTimeF32(); @@ -3499,6 +3423,7 @@ void LLTextureFetch::sendRequestListToSimulators()  // Locks:  Mw  bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)  { +    LL_PROFILE_ZONE_SCOPED;  	mRequestedDeltaTimer.reset();  	if (index >= mTotalPackets)  	{ @@ -3531,6 +3456,7 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)  void LLTextureFetchWorker::setState(e_state new_state)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if (mFTType == FTT_SERVER_BAKE)  	{  	// NOTE: turning on these log statements is a reliable way to get @@ -3552,7 +3478,7 @@ void LLTextureFetchWorker::setState(e_state new_state)  			mSkippedStatesTime += d_time;  		}  	} -	 +  	mStateTimer.reset();  	mState = new_state;  } @@ -3561,6 +3487,7 @@ void LLTextureFetchWorker::setState(e_state new_state)  bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,  										U16 data_size, U8* data)  { +    LL_PROFILE_ZONE_SCOPED;  	LLTextureFetchWorker* worker = getWorker(id);  	bool res = true; @@ -3612,7 +3539,6 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8  	llassert_always(totalbytes > 0);  	llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);  	res = worker->insertPacket(0, data, data_size); -	worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);  	worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR);  	worker->unlockWorkMutex();											// -Mw  	return res; @@ -3622,6 +3548,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8  // Threads:  T*  bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data)  { +    LL_PROFILE_ZONE_SCOPED;  	LLTextureFetchWorker* worker = getWorker(id);  	bool res = true; @@ -3662,7 +3589,6 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1  	if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) ||  		(worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK))  	{ -		worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);  		worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR);  	}  	else @@ -3707,10 +3633,23 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)  	return from_cache ;  } +S32 LLTextureFetch::getFetchState(const LLUUID& id) +{ +    S32 state = LLTextureFetchWorker::INVALID; +    LLTextureFetchWorker* worker = getWorker(id); +    if (worker && worker->haveWork()) +    { +        state = worker->mState; +    } + +    return state; +} +  // Threads:  T*  S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p,  								  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http)  { +    LL_PROFILE_ZONE_SCOPED;  	S32 state = LLTextureFetchWorker::INVALID;  	F32 data_progress = 0.0f;  	F32 requested_priority = 0.0f; @@ -3746,7 +3685,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r  		{  			requested_priority = worker->mImagePriority;  		} -		fetch_priority = worker->getPriority(); +		fetch_priority = worker->getImagePriority();  		can_use_http = worker->getCanUseHTTP() ;  		worker->unlockWorkMutex();										// -Mw  	} @@ -3760,19 +3699,6 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r  void LLTextureFetch::dump()  { -	LL_INFOS(LOG_TXT) << "LLTextureFetch REQUESTS:" << LL_ENDL; -	for (request_queue_t::iterator iter = mRequestQueue.begin(); -		 iter != mRequestQueue.end(); ++iter) -	{ -		LLQueuedThread::QueuedRequest* qreq = *iter; -		LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq; -		LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass(); -		LL_INFOS(LOG_TXT) << " ID: " << worker->mID -						  << " PRI: " << llformat("0x%08x",wreq->getPriority()) -						  << " STATE: " << sStateDescs[worker->mState] -						  << LL_ENDL; -	} -  	LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL;  	for (queue_t::const_iterator iter(mHTTPTextureQueue.begin());  		 mHTTPTextureQueue.end() != iter; @@ -3839,6 +3765,7 @@ bool LLTextureFetch::isHttpWaiter(const LLUUID & tid)  // Locks:  -Mw (must not hold any worker when called)  void LLTextureFetch::releaseHttpWaiters()  { +    LL_PROFILE_ZONE_SCOPED;  	// Use mHttpSemaphore rather than mHTTPTextureQueue.size()  	// to avoid a lock.    	if (mHttpSemaphore >= mHttpLowWater) @@ -3935,7 +3862,6 @@ void LLTextureFetch::releaseHttpWaiters()  		}  		worker->setState(LLTextureFetchWorker::SEND_HTTP_REQ); -		worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);  		worker->unlockWorkMutex();										// -Mw  		removeHttpWaiter(worker->mID); @@ -4025,6 +3951,7 @@ void LLTextureFetch::commandDataBreak()  // Threads:  T*  void LLTextureFetch::cmdEnqueue(TFRequest * req)  { +    LL_PROFILE_ZONE_SCOPED;  	lockQueue();														// +Mfq  	mCommands.push_back(req);  	unlockQueue();														// -Mfq @@ -4035,6 +3962,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req)  // Threads:  T*  LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()  { +    LL_PROFILE_ZONE_SCOPED;  	TFRequest * ret = 0;  	lockQueue();														// +Mfq @@ -4051,6 +3979,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()  // Threads:  Ttf  void LLTextureFetch::cmdDoWork()  { +    LL_PROFILE_ZONE_SCOPED;  	if (mDebugPause)  	{  		return;  // debug: don't do any work @@ -4141,7 +4070,7 @@ TFReqSendMetrics::~TFReqSendMetrics()  bool  TFReqSendMetrics::doWork(LLTextureFetch * fetcher)  { -	static const U32 report_priority(1); +    LL_PROFILE_ZONE_SCOPED;  	//if (! gViewerAssetStatsThread1)  	//	return true; @@ -4184,7 +4113,6 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)  		// Don't care about handle, this is a fire-and-forget operation.    		LLCoreHttpUtil::requestPostWithLLSD(&fetcher->getHttpRequest(),  											fetcher->getMetricsPolicyClass(), -											report_priority,  											mCapsURL,  											mStatsSD,  											LLCore::HttpOptions::ptr_t(), @@ -4246,971 +4174,6 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics)  } // end of anonymous namespace - -/////////////////////////////////////////////////////////////////////////////////////////// -//Start LLTextureFetchDebugger -/////////////////////////////////////////////////////////////////////////////////////////// -//--------------------- -class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder -{ -public: -	LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image) -		: mDebugger(debugger), mID(id) -	{ -		setImage(image); -	} -	virtual void completed(bool success) -	{ -		mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal); -	} -private: -	LLTextureFetchDebugger* mDebugger; -	S32 mID; -}; - -class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder -{ -public: -	LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id) -		: mDebugger(debugger), mID(id) -	{ -	} -	virtual void completed(bool success) -	{ -		mDebugger->callbackCacheWrite(mID, success); -	} -private: -	LLTextureFetchDebugger* mDebugger; -	S32 mID; -}; - -class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder -{ -public: -	LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id) -		: mDebugger(debugger), mID(id) -	{ -	} -	virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) -	{ -		mDebugger->callbackDecoded(mID, success, raw, aux); -	} -private: -	LLTextureFetchDebugger* mDebugger; -	S32 mID; -}; - - -LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : -	LLCore::HttpHandler(), -	mFetcher(fetcher), -	mTextureCache(cache), -	mImageDecodeThread(imagedecodethread), -	mHttpHeaders(), -	mHttpPolicyClass(fetcher->getPolicyClass()), -	mNbCurlCompleted(0), -	mTempIndex(0), -	mHistoryListIndex(0) -{ -	init(); -} -	 -LLTextureFetchDebugger::~LLTextureFetchDebugger() -{ -	mFetchingHistory.clear(); -	mStopDebug = TRUE; -	tryToStopDebug(); -} - -void LLTextureFetchDebugger::init() -{ -	setDebuggerState(IDLE); -	 -	mCacheReadTime = -1.f; -	mCacheWriteTime = -1.f; -	mDecodingTime = -1.f; -	mHTTPTime = -1.f; -	mGLCreationTime = -1.f; - -	mTotalFetchingTime = 0.f; -	mRefetchVisCacheTime = -1.f; -	mRefetchVisHTTPTime = -1.f; -	mRefetchAllCacheTime = -1.f; -	mRefetchAllHTTPTime = -1.f; - -	mNumFetchedTextures = 0; -	mNumCacheHits = 0; -	mNumVisibleFetchedTextures = 0; -	mNumVisibleFetchingRequests = 0; -	mFetchedData = 0; -	mDecodedData = 0; -	mVisibleFetchedData = 0; -	mVisibleDecodedData = 0; -	mRenderedData = 0; -	mRenderedDecodedData = 0; -	mFetchedPixels = 0; -	mRenderedPixels = 0; -	mRefetchedVisData = 0; -	mRefetchedVisPixels = 0; -	mRefetchedAllData = 0; -	mRefetchedAllPixels = 0; - -	mFreezeHistory = FALSE; -	mStopDebug = FALSE; -	mClearHistory = FALSE; -	mRefetchNonVis = FALSE; -	 -	mNbCurlRequests = 0; - -	if (! mHttpHeaders) -	{ -        mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders); -		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); -	} -} - -void LLTextureFetchDebugger::startWork(e_debug_state state) -{ -	switch(state) -	{ -		case IDLE: -			break; -		case START_DEBUG: -			startDebug(); -			break; -		case READ_CACHE:			 -			debugCacheRead(); -			break; -		case WRITE_CACHE: -			debugCacheWrite(); -			break; -		case DECODING: -			debugDecoder(); -			break; -		case HTTP_FETCHING: -			debugHTTP(); -			break; -		case GL_TEX: -			debugGLTextureCreation(); -			break; -		case REFETCH_VIS_CACHE: -			debugRefetchVisibleFromCache(); -			break; -		case REFETCH_VIS_HTTP: -			debugRefetchVisibleFromHTTP(); -			break; -		case REFETCH_ALL_CACHE: -			debugRefetchAllFromCache(); -			break; -		case REFETCH_ALL_HTTP: -			debugRefetchAllFromHTTP(); -			break; -		default: -			break; -	} -	return; -} - -void LLTextureFetchDebugger::startDebug() -{ -	//lock the fetcher -	mFetcher->lockFetcher(true); -	mFreezeHistory = TRUE; -	mFetcher->resetLoadSource(); - -	//clear the current fetching queue -	gTextureList.clearFetchingRequests(); - -	setDebuggerState(START_DEBUG); -} - -bool LLTextureFetchDebugger::processStartDebug(F32 max_time) -{ -	mTimer.reset(); - -	//wait for all works to be done -	while(1) -	{ -		S32 pending = 0; -		pending += LLAppViewer::getTextureCache()->update(1);  -		pending += LLAppViewer::getImageDecodeThread()->update(1);  -		// pending += LLAppViewer::getTextureFetch()->update(1);  // This causes infinite recursion in some cases -		pending += mNbCurlRequests; -		if(!pending) -		{ -			break; -		} - -		if(mTimer.getElapsedTimeF32() > max_time) -		{ -			return false; -		} -	} - -	//collect statistics -	mTotalFetchingTime = gTextureTimer.getElapsedTimeF32() - mTotalFetchingTime; -	 -	std::set<LLUUID> fetched_textures; -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size; i++) -	{ -		bool in_list = true; -		if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end()) -		{ -			fetched_textures.insert(mFetchingHistory[i].mID); -			in_list = false; -		} - -        std::vector<LLViewerFetchedTexture*> textures; -        LLViewerTextureManager::findFetchedTextures(mFetchingHistory[i].mID, textures); -        std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); -        while (iter != textures.end()) -        { -            LLViewerFetchedTexture* tex = *iter++; -            // fetched data will be counted for both ui and regular elements -            if (tex && tex->isJustBound()) //visible -            { -                if (!in_list) -                { -                    mNumVisibleFetchedTextures++; -                } -                mNumVisibleFetchingRequests++; - -                mVisibleFetchedData += mFetchingHistory[i].mFetchedSize; -                mVisibleDecodedData += mFetchingHistory[i].mDecodedSize; - -                if (tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel) -                { -                    mRenderedData += mFetchingHistory[i].mFetchedSize; -                    mRenderedDecodedData += mFetchingHistory[i].mDecodedSize; -                    mRenderedPixels += tex->getWidth() * tex->getHeight(); -                } -            } -        } -	} - -	mNumFetchedTextures = fetched_textures.size(); - -	return true; -} - -void LLTextureFetchDebugger::tryToStopDebug() -{ -	if(!mStopDebug) -	{ -		return; -	} - -	//clear the current debug work -	S32 size = mFetchingHistory.size(); -	switch(mDebuggerState) -	{ -	case READ_CACHE:		 -		for(S32 i = 0 ; i < size; i++) -		{ -			if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle()) -			{ -				mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true); -			} - 		}	 -		break; -	case WRITE_CACHE: -		for(S32 i = 0 ; i < size; i++) -		{ -			if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle()) -			{ -				mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true); -			} -		} -		break; -	case DECODING: -		break; -	case HTTP_FETCHING: -		break; -	case GL_TEX: -		break; -	case REFETCH_VIS_CACHE: -		break; -	case REFETCH_VIS_HTTP: -		break; -	case REFETCH_ALL_CACHE: -		mRefetchList.clear(); -		break; -	case REFETCH_ALL_HTTP: -		mRefetchList.clear(); -		break; -	default: -		break; -	} - -	if(update(0.005f)) -	{ -		//unlock the fetcher -		mFetcher->lockFetcher(false); -		mFetcher->resetLoadSource(); -		mFreezeHistory = FALSE;		 -		mStopDebug = FALSE; - -		if(mClearHistory) -		{ -			mFetchingHistory.clear(); -			mHandleToFetchIndex.clear(); -			init();	 -			mTotalFetchingTime = gTextureTimer.getElapsedTimeF32(); //reset -		} -	} -} - -//called in the main thread and when the fetching queue is empty -void LLTextureFetchDebugger::clearHistory() -{ -	mClearHistory = TRUE;	 -} - -void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker) -{ -	if(worker->mRawImage.isNull() || worker->mFormattedImage.isNull()) -	{ -		return; -	} - -	if(mFreezeHistory) -	{ -		if(mDebuggerState == REFETCH_VIS_CACHE || mDebuggerState == REFETCH_VIS_HTTP) -		{ -			mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); -			mRefetchedVisData += worker->mFormattedImage->getDataSize(); -		} -		else -		{ -			mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); -			mRefetchedAllData += worker->mFormattedImage->getDataSize(); - -			// refetch list only requests/creates normal images, so requesting ui='false' -			LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, TEX_LIST_STANDARD); -			if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end()) -			{ -				if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel) -				{ -					mRefetchList[tex].erase(mRefetchList[tex].begin()); -				} -			} -		} -		return; -	} - -	if(worker->mInCache) -	{ -		mNumCacheHits++; -	} -	mFetchedData += worker->mFormattedImage->getDataSize(); -	mDecodedData += worker->mRawImage->getDataSize(); -	mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); - -	mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard,  -		worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); -} - -void LLTextureFetchDebugger::lockCache() -{ -} -	 -void LLTextureFetchDebugger::unlockCache() -{ -} -	 -void LLTextureFetchDebugger::debugCacheRead() -{ -	lockCache(); -	llassert_always(mDebuggerState == IDLE); -	mTimer.reset(); -	setDebuggerState(READ_CACHE); -	mCacheReadTime = -1.f; - -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size ; i++) -	{		 -		mFetchingHistory[i].mFormattedImage = NULL; -		mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize,  -			new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage)); -	} -} -	 -void LLTextureFetchDebugger::clearCache() -{ -	S32 size = mFetchingHistory.size(); -	{ -		std::set<LLUUID> deleted_list; -		for(S32 i = 0 ; i < size ; i++) -		{ -			if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end()) -			{ -				deleted_list.insert(mFetchingHistory[i].mID); -				mTextureCache->removeFromCache(mFetchingHistory[i].mID); -			} -		} -	} -} - -void LLTextureFetchDebugger::debugCacheWrite() -{ -	//remove from cache -	clearCache(); - -	lockCache(); -	llassert_always(mDebuggerState == IDLE); -	mTimer.reset(); -	setDebuggerState(WRITE_CACHE); -	mCacheWriteTime = -1.f; - -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size ; i++) -	{		 -		if(mFetchingHistory[i].mFormattedImage.notNull()) -		{ -			mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL,  -				mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize, -				mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1,  -				NULL, 0, new LLDebuggerCacheWriteResponder(this, i));					 -		} -	} -} - -void LLTextureFetchDebugger::lockDecoder() -{ -} -	 -void LLTextureFetchDebugger::unlockDecoder() -{ -} - -void LLTextureFetchDebugger::debugDecoder() -{ -	lockDecoder(); -	llassert_always(mDebuggerState == IDLE); -	mTimer.reset(); -	setDebuggerState(DECODING); -	mDecodingTime = -1.f; - -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size ; i++) -	{		 -		if(mFetchingHistory[i].mFormattedImage.isNull()) -		{ -			continue; -		} - -		mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL,  -			mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux, -			new LLDebuggerDecodeResponder(this, i)); -	} -} - -void LLTextureFetchDebugger::debugHTTP() -{ -	llassert_always(mDebuggerState == IDLE); - -	LLViewerRegion* region = gAgent.getRegion(); -	if (!region) -	{ -		LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << LL_ENDL; -		return; -	} -	 -	mHTTPUrl = region->getViewerAssetUrl(); -	if (mHTTPUrl.empty()) -	{ -		LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL; -		return; -	} -	 -	mTimer.reset(); -	setDebuggerState(HTTP_FETCHING); -	mHTTPTime = -1.f; -	 -	S32 size = mFetchingHistory.size(); -	for (S32 i = 0 ; i < size ; i++) -	{ -		mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; -		mFetchingHistory[i].mCurlReceivedSize = 0; -		mFetchingHistory[i].mFormattedImage = NULL; -	} -	mNbCurlRequests = 0; -	mNbCurlCompleted = 0; -	 -	fillCurlQueue(); -} - -S32 LLTextureFetchDebugger::fillCurlQueue() -{ -	if(mStopDebug) //stop -	{ -		mNbCurlCompleted = mFetchingHistory.size(); -		return 0; -	} -	if (mNbCurlRequests > HTTP_NONPIPE_REQUESTS_LOW_WATER) -	{ -		return mNbCurlRequests; -	} -	 -	S32 size = mFetchingHistory.size(); -	for (S32 i = 0 ; i < size ; i++) -	{		 -		if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) -		{ -			continue; -		} -		std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str(); -		S32 requestedSize = mFetchingHistory[i].mRequestedSize; -		// We request the whole file if the size was not set. -		requestedSize = llmax(0,requestedSize); -		// We request the whole file if the size was set to an absurdly high value (meaning all file) -		requestedSize = (requestedSize == 33554432 ? 0 : requestedSize); - -		LLCore::HttpHandle handle = mFetcher->getHttpRequest().requestGetByteRange(mHttpPolicyClass, -																				   LLWorkerThread::PRIORITY_LOWBITS, -																				   texture_url, -																				   0, -																				   requestedSize, -																				   LLCore::HttpOptions::ptr_t(), -																				   mHttpHeaders, -                                                                                   LLCore::HttpHandler::ptr_t(this, &NoOpDeletor)); -		if (LLCORE_HTTP_HANDLE_INVALID != handle) -		{ -			mHandleToFetchIndex[handle] = i; -			mFetchingHistory[i].mHttpHandle = handle; -			mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; -			mNbCurlRequests++; -			if (mNbCurlRequests >= HTTP_NONPIPE_REQUESTS_HIGH_WATER)	// emulate normal pipeline -			{ -				break; -			} -		} -		else  -		{ -			// Failed to queue request, log it and mark it done. -			LLCore::HttpStatus status(mFetcher->getHttpRequest().getStatus()); - -			LL_WARNS(LOG_TXT) << "Couldn't issue HTTP request in debugger for texture " -							  << mFetchingHistory[i].mID -							  << ", status: " << status.toTerseString() -							  << " reason:  " << status.toString() -							  << LL_ENDL; -			mFetchingHistory[i].mCurlState = FetchEntry::CURL_DONE; -		} -	} -	//LL_INFOS(LOG_TXT) << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << LL_ENDL; -	return mNbCurlRequests; -} - -void LLTextureFetchDebugger::debugGLTextureCreation() -{ -	llassert_always(mDebuggerState == IDLE); -	setDebuggerState(GL_TEX); -	mTempTexList.clear(); - -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size ; i++) -	{ -		if(mFetchingHistory[i].mRawImage.notNull()) -		{ -            std::vector<LLViewerFetchedTexture*> textures; -            gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures); -            std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); -            while (iter != textures.end()) -            { -                LLViewerFetchedTexture* tex = *iter++; -                if (tex && !tex->isForSculptOnly()) -                { -                    tex->destroyGLTexture(); -                    mTempTexList.push_back(tex); -                } -            } -		} -	} -	 -	mGLCreationTime = -1.f; -	mTempIndex = 0; -	mHistoryListIndex = 0; -	 -	return; -} - -bool LLTextureFetchDebugger::processGLCreation(F32 max_time) -{ -	mTimer.reset(); - -	bool done = true; -	S32 size = mFetchingHistory.size(); -	S32 size1 = mTempTexList.size(); -	for(; mHistoryListIndex < size && mTempIndex < size1; mHistoryListIndex++) -	{ -		if(mFetchingHistory[mHistoryListIndex].mRawImage.notNull()) -		{ -			if(mFetchingHistory[mHistoryListIndex].mID == mTempTexList[mTempIndex]->getID()) -			{ -				mTempTexList[mTempIndex]->createGLTexture(mFetchingHistory[mHistoryListIndex].mDecodedLevel,  -					mFetchingHistory[mHistoryListIndex].mRawImage, 0, TRUE, mTempTexList[mTempIndex]->getBoostLevel()); -				mTempIndex++; -			} -		} - -		if(mTimer.getElapsedTimeF32() > max_time) -		{ -			done = false; -			break; -		} -	} - -	if(mGLCreationTime < 0.f) -	{ -		mGLCreationTime = mTimer.getElapsedTimeF32() ; -	} -	else -	{ -		mGLCreationTime += mTimer.getElapsedTimeF32() ; -	} - -	return done; -} - -//clear fetching results of all textures. -void LLTextureFetchDebugger::clearTextures() -{ -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size ; i++) -	{ -        std::vector<LLViewerFetchedTexture*> textures; -        gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures); -        std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); -        while (iter != textures.end()) -        { -            LLViewerFetchedTexture* tex = *iter++; -            if (tex) -            { -                tex->clearFetchedResults(); -            } -        } -	} -} - -void LLTextureFetchDebugger::makeRefetchList() -{ -	mRefetchList.clear(); -	S32 size = mFetchingHistory.size(); -	for(S32 i = 0 ; i < size; i++) -	{		 -		LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(mFetchingHistory[i].mID); -		if(tex && tex->isJustBound()) //visible -		{ -			continue; //the texture fetch pipeline will take care of visible textures. -		} - -		// todo: Will attempt to refetch icons and ui elements as normal images (boost_none) -		// thus will create unnecessary LLViewerFetchedTexture, consider supporting separate UI textures -		mRefetchList[tex].push_back(i); 		 -	} -} - -void LLTextureFetchDebugger::scanRefetchList() -{ -	if(mStopDebug) -	{ -		return; -	} -	if(!mRefetchNonVis) -	{ -		return; -	} - -	for(std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> >::iterator iter = mRefetchList.begin(); -		iter != mRefetchList.end(); ) -	{ -		if(iter->second.empty()) -		{ -			gTextureList.setDebugFetching(iter->first, -1); -			mRefetchList.erase(iter++);		// This is the correct method to "erase and move on" in an std::map -		} -		else -		{ -			gTextureList.setDebugFetching(iter->first, mFetchingHistory[iter->second[0]].mDecodedLevel); -			++iter; -		} -	} -} - -void LLTextureFetchDebugger::debugRefetchVisibleFromCache() -{ -	llassert_always(mDebuggerState == IDLE); -	setDebuggerState(REFETCH_VIS_CACHE); - -	clearTextures(); -	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL); -	 -	mTimer.reset(); -	mFetcher->lockFetcher(false); -	mRefetchVisCacheTime = -1.f; -	mRefetchedVisData = 0; -	mRefetchedVisPixels = 0; -} - -void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP() -{ -	llassert_always(mDebuggerState == IDLE); -	setDebuggerState(REFETCH_VIS_HTTP); - -	clearTextures(); -	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY); - -	mTimer.reset(); -	mFetcher->lockFetcher(false); -	mRefetchVisHTTPTime = -1.f; -	mRefetchedVisData = 0; -	mRefetchedVisPixels = 0; -} - -void LLTextureFetchDebugger::debugRefetchAllFromCache() -{ -	llassert_always(mDebuggerState == IDLE); -	setDebuggerState(REFETCH_ALL_CACHE); - -	clearTextures(); -	makeRefetchList(); -	mFetcher->setLoadSource(LLTextureFetch::FROM_ALL); - -	mTimer.reset(); -	mFetcher->lockFetcher(false); -	mRefetchAllCacheTime = -1.f; -	mRefetchedAllData = 0; -	mRefetchedAllPixels = 0; -	mRefetchNonVis = FALSE; -} - -void LLTextureFetchDebugger::debugRefetchAllFromHTTP() -{ -	llassert_always(mDebuggerState == IDLE); -	setDebuggerState(REFETCH_ALL_HTTP); - -	clearTextures(); -	makeRefetchList(); -	mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY); - -	mTimer.reset(); -	mFetcher->lockFetcher(false); -	mRefetchAllHTTPTime = -1.f; -	mRefetchedAllData = 0; -	mRefetchedAllPixels = 0; -	mRefetchNonVis = TRUE; -} - -bool LLTextureFetchDebugger::update(F32 max_time) -{ -	switch(mDebuggerState) -	{ -	case START_DEBUG: -		if(processStartDebug(max_time)) -		{ -			setDebuggerState(IDLE); -		} -		break; -	case READ_CACHE: -		if(!mTextureCache->update(1)) -		{ -			mCacheReadTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			unlockCache(); -		} -		break; -	case WRITE_CACHE: -		if(!mTextureCache->update(1)) -		{ -			mCacheWriteTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			unlockCache(); -		} -		break; -	case DECODING: -		if(!mImageDecodeThread->update(1)) -		{ -			mDecodingTime =  mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			unlockDecoder(); -		} -		break; -	case HTTP_FETCHING: -		// Do some notifications... -		mFetcher->getHttpRequest().update(10); -		if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size()) -		{ -			mHTTPTime =  mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -		} -		break; -	case GL_TEX: -		if(processGLCreation(max_time)) -		{ -			setDebuggerState(IDLE); -			mTempTexList.clear(); -		} -		break; -	case REFETCH_VIS_CACHE: -		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) -		{ -			mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			mFetcher->lockFetcher(true); -			mFetcher->resetLoadSource(); -		} -		break; -	case REFETCH_VIS_HTTP: -		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) -		{ -			mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			mFetcher->lockFetcher(true); -			mFetcher->resetLoadSource(); -		} -		break; -	case REFETCH_ALL_CACHE: -		scanRefetchList(); -		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) -		{ -			if(!mRefetchNonVis) -			{ -				mRefetchNonVis = TRUE; //start to fetch non-vis -				scanRefetchList(); -				break; -			} - -			mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE);  -			mFetcher->lockFetcher(true); -			mFetcher->resetLoadSource(); -			mRefetchList.clear(); -			mRefetchNonVis = FALSE; -		} -		break; -	case REFETCH_ALL_HTTP: -		scanRefetchList(); -		if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) -		{ -			mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ; -			setDebuggerState(IDLE); -			mFetcher->lockFetcher(true); -			mFetcher->resetLoadSource(); -			mRefetchList.clear(); -			mRefetchNonVis = FALSE; -		} -		break; -	default: -		setDebuggerState(IDLE); -		break; -	} - -	return mDebuggerState == IDLE; -} - -void LLTextureFetchDebugger::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) -{ -	handle_fetch_map_t::iterator iter(mHandleToFetchIndex.find(handle)); -	if (mHandleToFetchIndex.end() == iter) -	{ -		LL_INFOS(LOG_TXT) << "Fetch Debugger : Couldn't find handle " << handle << " in fetch list." << LL_ENDL; -		return; -	} -	 -	S32 fetch_ind(iter->second); -	mHandleToFetchIndex.erase(iter); -	if (fetch_ind >= mFetchingHistory.size() || mFetchingHistory[fetch_ind].mHttpHandle != handle) -	{ -		LL_INFOS(LOG_TXT) << "Fetch Debugger : Handle and fetch object in disagreement.  Punting." << LL_ENDL; -	} -	else -	{ -		callbackHTTP(mFetchingHistory[fetch_ind], response); -		mFetchingHistory[fetch_ind].mHttpHandle = LLCORE_HTTP_HANDLE_INVALID;	// Not valid after notification -	} -} - -void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image, -						   S32 imagesize, BOOL islocal) -{ -	if (success) -	{ -		mFetchingHistory[id].mFormattedImage = image; -	} -	mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false); -	mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); -} - -void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success) -{ -	mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle); -	mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); -} - -void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux) -{ -	if (success) -	{ -		llassert_always(raw); -		mFetchingHistory[id].mRawImage = raw; -	} -} - -void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response) -{ -	static const LLCore::HttpStatus par_status(HTTP_PARTIAL_CONTENT); -	 -	LLCore::HttpStatus status(response->getStatus()); -	mNbCurlRequests--; -	mNbCurlCompleted++; -	fetch.mCurlState = FetchEntry::CURL_DONE; -	if (status) -	{ -		const bool partial(par_status == status); -		LLCore::BufferArray * ba(response->getBody());	// *Not* holding reference to body -		 -		S32 data_size = ba ? ba->size() : 0; -		fetch.mCurlReceivedSize += data_size; -		//LL_INFOS(LOG_TXT) << "Fetch Debugger : got results for " << fetch.mID << ", data_size = " << data_size << ", received = " << fetch.mCurlReceivedSize << ", requested = " << fetch.mRequestedSize << ", partial = " << partial << LL_ENDL; -		if ((fetch.mCurlReceivedSize >= fetch.mRequestedSize) || !partial || (fetch.mRequestedSize == 600)) -		{ -			U8* d_buffer = (U8*)ll_aligned_malloc_16(data_size); -			if (ba) -			{ -				ba->read(0, d_buffer, data_size); -			} -			 -			llassert_always(fetch.mFormattedImage.isNull()); -			{ -				// For now, create formatted image based on extension -				std::string texture_url = mHTTPUrl + "/?texture_id=" + fetch.mID.asString().c_str(); -				std::string extension = gDirUtilp->getExtension(texture_url); -				fetch.mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); -				if (fetch.mFormattedImage.isNull()) -				{ -					fetch.mFormattedImage = new LLImageJ2C; // default -				} -			} -						 -			fetch.mFormattedImage->setData(d_buffer, data_size);	 -		} -	} -	else //failed -	{ -		LL_INFOS(LOG_TXT) << "Fetch Debugger : CURL GET FAILED,  ID = " << fetch.mID -						  << ", status: " << status.toTerseString() -						  << " reason:  " << status.toString() << LL_ENDL; -	} -} - - -//--------------------- -/////////////////////////////////////////////////////////////////////////////////////////// -//End LLTextureFetchDebugger -/////////////////////////////////////////////////////////////////////////////////////////// -  LLTextureFetchTester::LLTextureFetchTester() : LLMetricPerformanceTesterBasic(sTesterName)   {  	mTextureFetchTime = 0; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index bf6732963f..3ca88422a2 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -48,7 +48,6 @@ class LLTextureFetchWorker;  class LLImageDecodeThread;  class LLHost;  class LLViewerAssetStats; -class LLTextureFetchDebugger;  class LLTextureCache;  class LLTextureFetchTester; @@ -59,7 +58,9 @@ class LLTextureFetch : public LLWorkerThread  	friend class LLTextureFetchWorker;  public: -	LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode); +    static std::string getStateString(S32 state); + +	LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode);  	~LLTextureFetch();  	class TFRequest; @@ -116,10 +117,11 @@ public:      // Threads:  T*  	BOOL isFromLocalCache(const LLUUID& id); -	// @return	Magic number giving the internal state of the -	//			request.  We should make these codes public if we're -	//			going to return them as a status value. -	// +    // get the current fetch state, if any, from the given UUID +    S32 getFetchState(const LLUUID& id); + +	// @return	Fetch state of given image and associates statistics +	//          See also getStateString      // Threads:  T*  	S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,  					  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http); @@ -322,7 +324,6 @@ private:  	LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.  	LLTextureCache* mTextureCache; -	LLImageDecodeThread* mImageDecodeThread;  	// Map of all requests by UUID  	typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; @@ -409,10 +410,6 @@ public:  	static LLTextureFetchTester* sTesterp;  private: -	//debug use -	LLTextureFetchDebugger* mFetchDebugger; -	bool mFetcherLocked; -	  	e_tex_source mFetchSource;  	e_tex_source mOriginFetchSource; @@ -420,10 +417,6 @@ private:  	//LLAdaptiveRetryPolicy mFetchRetryPolicy;  public: -	//debug use -	LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} -	void lockFetcher(bool lock) { mFetcherLocked = lock;} -  	void setLoadSource(e_tex_source source) {mFetchSource = source;}  	void resetLoadSource() {mFetchSource = mOriginFetchSource;}  	bool canLoadFromCache() { return mFetchSource != FROM_HTTP_ONLY;} @@ -431,216 +424,6 @@ public:  //debug use  class LLViewerFetchedTexture; -class LLTextureFetchDebugger : public LLCore::HttpHandler -{ -	friend class LLTextureFetch; -public: -	LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ; -	~LLTextureFetchDebugger(); - -public: -	enum e_debug_state -	{ -		IDLE = 0, -		START_DEBUG, -		READ_CACHE, -		WRITE_CACHE, -		DECODING, -		HTTP_FETCHING, -		GL_TEX, -		REFETCH_VIS_CACHE, -		REFETCH_VIS_HTTP, -		REFETCH_ALL_CACHE, -		REFETCH_ALL_HTTP, -		INVALID -	}; - -private:	 -	struct FetchEntry -	{ -		enum e_curl_state -		{ -			CURL_NOT_DONE = 0, -			CURL_IN_PROGRESS, -			CURL_DONE -		}; -		LLUUID mID; -		S32 mRequestedSize; -		S32 mDecodedLevel; -		S32 mFetchedSize; -		S32 mDecodedSize; -		BOOL mNeedsAux; -		U32 mCacheHandle; -		LLPointer<LLImageFormatted> mFormattedImage; -		LLPointer<LLImageRaw> mRawImage; -		e_curl_state mCurlState; -		S32 mCurlReceivedSize; -		LLCore::HttpHandle mHttpHandle; - -		FetchEntry() : -			mDecodedLevel(-1), -			mFetchedSize(0), -			mDecodedSize(0), -			mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) -			{} -		FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) : -			mID(id), -			mRequestedSize(r_size), -			mDecodedLevel(level), -			mFetchedSize(f_size), -			mDecodedSize(d_size), -			mNeedsAux(false), -			mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) -			{} -	}; -	typedef std::vector<FetchEntry> fetch_list_t; -	fetch_list_t mFetchingHistory; - -	typedef std::map<LLCore::HttpHandle, S32> handle_fetch_map_t; -	handle_fetch_map_t mHandleToFetchIndex; - -	void setDebuggerState(e_debug_state new_state) { mDebuggerState = new_state; } -	e_debug_state mDebuggerState; -	 -	F32 mCacheReadTime; -	F32 mCacheWriteTime; -	F32 mDecodingTime; -	F32 mHTTPTime; -	F32 mGLCreationTime; - -	F32 mTotalFetchingTime; -	F32 mRefetchVisCacheTime; -	F32 mRefetchVisHTTPTime; -	F32 mRefetchAllCacheTime; -	F32 mRefetchAllHTTPTime; - -	LLTimer mTimer; -	 -	LLTextureFetch* mFetcher; -	LLTextureCache* mTextureCache; -	LLImageDecodeThread* mImageDecodeThread; -	LLCore::HttpHeaders::ptr_t mHttpHeaders; -	LLCore::HttpRequest::policy_t mHttpPolicyClass; -	 -	S32 mNumFetchedTextures; -	S32 mNumCacheHits; -	S32 mNumVisibleFetchedTextures; -	S32 mNumVisibleFetchingRequests; -	U32 mFetchedData; -	U32 mDecodedData; -	U32 mVisibleFetchedData; -	U32 mVisibleDecodedData; -	U32 mRenderedData; -	U32 mRenderedDecodedData; -	U32 mFetchedPixels; -	U32 mRenderedPixels; -	U32 mRefetchedVisData; -	U32 mRefetchedVisPixels; -	U32 mRefetchedAllData; -	U32 mRefetchedAllPixels; - -	BOOL mFreezeHistory; -	BOOL mStopDebug; -	BOOL mClearHistory; -	BOOL mRefetchNonVis; - -	std::string mHTTPUrl; -	S32 mNbCurlRequests; -	S32 mNbCurlCompleted; - -	std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList; // treats UI textures as normal textures -	std::vector< LLPointer<LLViewerFetchedTexture> > mTempTexList; -	S32 mTempIndex; -	S32 mHistoryListIndex; - -public: -	bool update(F32 max_time); //called in the main thread once per frame - -	//fetching history -	void clearHistory(); -	void addHistoryEntry(LLTextureFetchWorker* worker); -	 -	// Inherited from LLCore::HttpHandler -	// Threads:  Ttf -	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - -	void startWork(e_debug_state state); -	void setStopDebug() {mStopDebug = TRUE;} -	void tryToStopDebug(); //stop everything -	void callbackCacheRead(S32 id, bool success, LLImageFormatted* image, -						   S32 imagesize, BOOL islocal); -	void callbackCacheWrite(S32 id, bool success); -	void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux); -	void callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response); - -	e_debug_state getState()             {return mDebuggerState;} -	S32  getNumFetchedTextures()         {return mNumFetchedTextures;} -	S32  getNumFetchingRequests()        {return mFetchingHistory.size();} -	S32  getNumCacheHits()               {return mNumCacheHits;} -	S32  getNumVisibleFetchedTextures()  {return mNumVisibleFetchedTextures;} -	S32  getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;} -	U32  getFetchedData()                {return mFetchedData;} -	U32  getDecodedData()                {return mDecodedData;} -	U32  getVisibleFetchedData()         {return mVisibleFetchedData;} -	U32  getVisibleDecodedData()         {return mVisibleDecodedData;} -	U32  getRenderedData()               {return mRenderedData;} -	U32  getRenderedDecodedData()        {return mRenderedDecodedData;} -	U32  getFetchedPixels()              {return mFetchedPixels;} -	U32  getRenderedPixels()             {return mRenderedPixels;} -	U32  getRefetchedVisData()              {return mRefetchedVisData;} -	U32  getRefetchedVisPixels()            {return mRefetchedVisPixels;} -	U32  getRefetchedAllData()              {return mRefetchedAllData;} -	U32  getRefetchedAllPixels()            {return mRefetchedAllPixels;} - -	F32  getCacheReadTime()     {return mCacheReadTime;} -	F32  getCacheWriteTime()    {return mCacheWriteTime;} -	F32  getDecodeTime()        {return mDecodingTime;} -	F32  getGLCreationTime()    {return mGLCreationTime;} -	F32  getHTTPTime()          {return mHTTPTime;} -	F32  getTotalFetchingTime() {return mTotalFetchingTime;} -	F32  getRefetchVisCacheTime() {return mRefetchVisCacheTime;} -	F32  getRefetchVisHTTPTime()  {return mRefetchVisHTTPTime;} -	F32  getRefetchAllCacheTime() {return mRefetchAllCacheTime;} -	F32  getRefetchAllHTTPTime()  {return mRefetchAllHTTPTime;} - -private: -	void init(); -	void clearTextures();//clear fetching results of all textures. -	void clearCache(); -	void makeRefetchList(); -	void scanRefetchList(); - -	void lockFetcher(); -	void unlockFetcher(); - -	void lockCache(); -	void unlockCache(); - -	void lockDecoder(); -	void unlockDecoder(); -	 -	S32 fillCurlQueue(); - -	void startDebug(); -	void debugCacheRead(); -	void debugCacheWrite();	 -	void debugHTTP(); -	void debugDecoder(); -	void debugGLTextureCreation(); -	void debugRefetchVisibleFromCache(); -	void debugRefetchVisibleFromHTTP(); -	void debugRefetchAllFromCache(); -	void debugRefetchAllFromHTTP(); - -	bool processStartDebug(F32 max_time); -	bool processGLCreation(F32 max_time); - -private: -	static bool sDebuggerEnabled; -public: -	static bool isEnabled() {return sDebuggerEnabled;} -}; -  class LLTextureFetchTester : public LLMetricPerformanceTesterBasic  { diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b74577315e..f0e9cee101 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -49,6 +49,8 @@  #include "llviewerobjectlist.h"  #include "llviewertexture.h"  #include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llwindow.h"  #include "llvovolume.h"  #include "llviewerstats.h"  #include "llworld.h" @@ -117,8 +119,8 @@ public:  			LLTextureBar* bar2p = (LLTextureBar*)i2;  			LLViewerFetchedTexture *i1p = bar1p->mImagep;  			LLViewerFetchedTexture *i2p = bar2p->mImagep; -			F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority -			F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority +			F32 pri1 = i1p->getMaxVirtualSize(); +			F32 pri2 = i2p->getMaxVirtualSize();  			if (pri1 > pri2)  				return true;  			else if (pri2 > pri1) @@ -177,7 +179,7 @@ void LLTextureBar::draw()  	{  		color = LLColor4::magenta; // except none and alm  	} -	else if (mImagep->getDecodePriority() <= 0.0f) +	else if (mImagep->getMaxVirtualSize() <= 0.0f)  	{  		color = LLColor4::grey; color[VALPHA] = .7f;  	} @@ -202,26 +204,13 @@ void LLTextureBar::draw()  	std::string uuid_str;  	mImagep->mID.toString(uuid_str);  	uuid_str = uuid_str.substr(0,7); -	if (mTextureView->mOrderFetch) -	{ -		tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)", -						   uuid_str.c_str(), -						   mImagep->mMaxVirtualSize, -						   mImagep->mDesiredDiscardLevel, -						   mImagep->mRequestedDiscardLevel, -						   mImagep->mFetchPriority, -						   mImagep->getDecodePriority()); -	} -	else -	{ -		tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", -						   uuid_str.c_str(), -						   mImagep->mMaxVirtualSize, -						   mImagep->mDesiredDiscardLevel, -						   mImagep->mRequestedDiscardLevel, -						   mImagep->getDecodePriority(), -						   mImagep->mFetchPriority); -	} +	 +    tex_str = llformat("%s %7.0f %d(%d)", +        uuid_str.c_str(), +        mImagep->mMaxVirtualSize, +        mImagep->mDesiredDiscardLevel, +        mImagep->mRequestedDiscardLevel); +  	LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(),  									 color, LLFontGL::LEFT, LLFontGL::TOP); @@ -500,10 +489,6 @@ private:  void LLGLTexMemBar::draw()  { -	S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory; - 	S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory; -	S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory; -	S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem;  	F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;  	F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits<LLUnits::Megabytes>();  	F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits<LLUnits::Megabytes>(); @@ -549,15 +534,10 @@ void LLGLTexMemBar::draw()      U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);      U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f); -	text = llformat("GL Tot: %d/%d MB GL Free: %d Sys Free: %d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", -					total_mem.value(), -					max_total_mem.value(), -                    LLImageGLThread::getFreeVRAMMegabytes(), +    text = llformat("GL Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", +                    gViewerWindow->getWindow()->getAvailableVRAMMegabytes(),                      LLMemory::getAvailableMemKB()/1024, -					bound_mem.value(), -					max_bound_mem.value(),  					LLRenderTarget::sBytesAllocated/(1024*1024), -					LLImageRaw::sGlobalRawMemory >> 20,  					discard_bias,  					cache_usage,  					cache_max_usage); @@ -837,7 +817,7 @@ void LLTextureView::draw()  				LL_INFOS() << imagep->getID()  						<< "\t" << tex_mem  						<< "\t" << imagep->getBoostLevel() -						<< "\t" << imagep->getDecodePriority() +						<< "\t" << imagep->getMaxVirtualSize()  						<< "\t" << imagep->getWidth()  						<< "\t" << imagep->getHeight()  						<< "\t" << cur_discard @@ -857,7 +837,7 @@ void LLTextureView::draw()  			}  			else  			{ -				pri = imagep->getDecodePriority(); +				pri = imagep->getMaxVirtualSize();  			}  			pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp new file mode 100644 index 0000000000..935f8e7794 --- /dev/null +++ b/indra/newview/lltinygltfhelper.cpp @@ -0,0 +1,245 @@ +/** + * @file   lltinygltfhelper.cpp + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltinygltfhelper.h" + +#include "llimage.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" + +void strip_alpha_channel(LLPointer<LLImageRaw>& img) +{ +    if (img->getComponents() == 4) +    { +        LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3); +        tmp->copyUnscaled4onto3(img); +        img = tmp; +    } +} + +// copy red channel from src_img to dst_img +// PRECONDITIONS: +// dst_img must be 3 component +// src_img and dst_image must have the same dimensions +void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img) +{ +    llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight()); +    llassert(dst_img->getComponents() == 3); + +    U32 pixel_count = dst_img->getWidth() * dst_img->getHeight(); +    U8* src = src_img->getData(); +    U8* dst = dst_img->getData(); +    S8 src_components = src_img->getComponents(); + +    for (U32 i = 0; i < pixel_count; ++i) +    { +        dst[i * 3] = src[i * src_components]; +    } +} + +void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material, +    LLPointer<LLImageRaw>& albedo_img, +    LLPointer<LLImageRaw>& normal_img, +    LLPointer<LLImageRaw>& mr_img, +    LLPointer<LLImageRaw>& emissive_img, +    LLPointer<LLImageRaw>& occlusion_img, +    LLPointer<LLViewerFetchedTexture>& albedo_tex, +    LLPointer<LLViewerFetchedTexture>& normal_tex, +    LLPointer<LLViewerFetchedTexture>& mr_tex, +    LLPointer<LLViewerFetchedTexture>& emissive_tex) +{ +    if (albedo_img) +    { +        albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true); +    } + +    if (normal_img) +    { +        strip_alpha_channel(normal_img); +        normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true); +    } + +    if (mr_img) +    { +        strip_alpha_channel(mr_img); + +        if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) +        { +            // occlusion is a distinct texture from pbrMetallicRoughness +            // pack into mr red channel +            int occlusion_idx = material.occlusionTexture.index; +            int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; +            if (occlusion_idx != mr_idx) +            { +                //scale occlusion image to match resolution of mr image +                occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); + +                copy_red_channel(occlusion_img, mr_img); +            } +        } +    } +    else if (occlusion_img) +    { +        //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over +        mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3); +        mr_img->clear(255, 255, 255); +        copy_red_channel(occlusion_img, mr_img); +    } + +    if (mr_img) +    { +        mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true); +    } + +    if (emissive_img) +    { +        strip_alpha_channel(emissive_img); +        emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true); +    } +} + +void LLTinyGLTFHelper::setFromModel(LLGLTFMaterial* mat, tinygltf::Model& model) +{ +    S32 index; + +    auto& material_in = model.materials[0]; + +    // get albedo texture +    index = material_in.pbrMetallicRoughness.baseColorTexture.index; +    if (index >= 0) +    { +        mat->mAlbedoId.set(model.images[index].uri); +    } +    else +    { +        mat->mAlbedoId.setNull(); +    } + +    // get normal map +    index = material_in.normalTexture.index; +    if (index >= 0) +    { +        mat->mNormalId.set(model.images[index].uri); +    } +    else +    { +        mat->mNormalId.setNull(); +    } + +    // get metallic-roughness texture +    index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index; +    if (index >= 0) +    { +        mat->mMetallicRoughnessId.set(model.images[index].uri); +    } +    else +    { +        mat->mMetallicRoughnessId.setNull(); +    } + +    // get emissive texture +    index = material_in.emissiveTexture.index; +    if (index >= 0) +    { +        mat->mEmissiveId.set(model.images[index].uri); +    } +    else +    { +        mat->mEmissiveId.setNull(); +    } + +    mat->setAlphaMode(material_in.alphaMode); +    mat->mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f); + +    mat->mAlbedoColor = getColor(material_in.pbrMetallicRoughness.baseColorFactor); +    mat->mEmissiveColor = getColor(material_in.emissiveFactor); + +    mat->mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f); +    mat->mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f); + +    mat->mDoubleSided = material_in.doubleSided; +} + +LLColor4 LLTinyGLTFHelper::getColor(const std::vector<double>& in) +{ +    LLColor4 out; +    for (S32 i = 0; i < llmin((S32)in.size(), 4); ++i) +    { +        out.mV[i] = in[i]; +    } + +    return out; +} + +const tinygltf::Image * LLTinyGLTFHelper::getImageFromTextureIndex(const tinygltf::Model & model, S32 texture_index) +{ +    if (texture_index >= 0) +    { +        S32 source_idx = model.textures[texture_index].source; +        if (source_idx >= 0) +        { +            return &(model.images[source_idx]); +        } +    } + +    return nullptr; +} + +LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name) +{ +    const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index); +    LLImageRaw* rawImage = nullptr; + +    if (image != nullptr && +        image->bits == 8 && +        !image->image.empty() && +        image->component <= 4) +    { +        name = image->name; +        rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); +        rawImage->verticalFlip(); +    } + +    return rawImage; +} + +LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index) +{ +    const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index); +    LLImageRaw* rawImage = nullptr; + +    if (image != nullptr && +        image->bits == 8 && +        !image->image.empty() && +        image->component <= 4) +    { +        rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); +        rawImage->verticalFlip(); +    } + +    return rawImage; +} diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h new file mode 100644 index 0000000000..a25fdac41d --- /dev/null +++ b/indra/newview/lltinygltfhelper.h @@ -0,0 +1,55 @@ +/** + * @file   lltinygltfhelper.h + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#pragma once + +#include "llgltfmaterial.h" +#include "llpointer.h" +#include "tinygltf/tiny_gltf.h" + +class LLImageRaw; +class LLViewerFetchedTexture; + +namespace LLTinyGLTFHelper +{ +    void setFromModel(LLGLTFMaterial* mat, tinygltf::Model& model); +    LLColor4 getColor(const std::vector<double>& in); +    const tinygltf::Image* getImageFromTextureIndex(const tinygltf::Model& model, S32 texture_index); +    LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name); +    LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); + +    void initFetchedTextures(tinygltf::Material& material, +        LLPointer<LLImageRaw>& albedo_img, +        LLPointer<LLImageRaw>& normal_img, +        LLPointer<LLImageRaw>& mr_img, +        LLPointer<LLImageRaw>& emissive_img, +        LLPointer<LLImageRaw>& occlusion_img, +        LLPointer<LLViewerFetchedTexture>& albedo_tex, +        LLPointer<LLViewerFetchedTexture>& normal_tex, +        LLPointer<LLViewerFetchedTexture>& mr_tex, +        LLPointer<LLViewerFetchedTexture>& emissive_tex); +} + diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 8baad30e8f..692e8d91a9 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -291,7 +291,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			mLineEditor->setText(edit_text_contents);  			std::string notif_name = mNotification->getName(); -			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name)) +			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name) || ("CreateSubfolder" == notif_name))  			{  				mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);  			} diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 55e8a3b98b..ab54e2afc6 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1160,7 +1160,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,  										   S32 hit_face,  										   LLInventoryItem* item,  										   LLToolDragAndDrop::ESource source, -										   const LLUUID& src_id) +										   const LLUUID& src_id, +                                           S32 tex_channel)  {  	if (hit_face == -1) return;  	if (!item) @@ -1184,7 +1185,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,  	if (gFloaterTools->getVisible() && panel_face)  	{ -		switch (LLSelectMgr::getInstance()->getTextureChannel()) +        tex_channel = (tex_channel > -1) ? tex_channel : LLSelectMgr::getInstance()->getTextureChannel(); +        switch (tex_channel)  		{  		case 0: diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 2f6423080e..cfdbd931ce 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -246,7 +246,8 @@ public:  	static void dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face,  								   LLInventoryItem* item,  								   ESource source, -								   const LLUUID& src_id); +								   const LLUUID& src_id, +                                   S32 tex_channel = -1);  	static void dropTextureAllFaces(LLViewerObject* hit_obj,  									LLInventoryItem* item,  									ESource source, diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index a6f5a09722..9682945208 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -341,12 +341,6 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)  	return true;  } -static bool handleVideoMemoryChanged(const LLSD& newvalue) -{ -	gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger())); -	return true; -} -  static bool handleChatFontSizeChanged(const LLSD& newvalue)  {  	if(gConsole) @@ -440,6 +434,21 @@ static bool handleRenderLocalLightsChanged(const LLSD& newvalue)  	return true;  } +static bool handleRenderPBRChanged(const LLSD& newvalue) +{ +    if (gPipeline.isInit()) +    { +        LLPipeline::refreshCachedSettings(); +        gPipeline.updateRenderDeferred(); +        gPipeline.releaseGLBuffers(); +        gPipeline.createGLBuffers(); +        gPipeline.resetVertexBuffers(); +        LLViewerShaderMgr::instance()->setShaders(); +    } +    return true; +} + +#if 0 // DEPRECATED  // NOTE: may be triggered by RenderDeferred OR RenderPBR changing, don't trust "newvalue"  static bool handleRenderDeferredChanged(const LLSD& newvalue)  { @@ -477,6 +486,7 @@ static bool handleRenderBumpChanged(const LLSD& newval)  	}  	return true;  } +#endif  static bool handleRenderDebugPipelineChanged(const LLSD& newvalue)  { @@ -663,7 +673,7 @@ void settings_setup_listeners()  	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));  	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); -	gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); +	// DEPRECATED -- gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));  	gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); @@ -679,18 +689,17 @@ void settings_setup_listeners()  	gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));  	gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));  	gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); -	gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2)); +	// DEPRECATED - gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2));  	gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));      gSavedSettings.getControl("RenderVSyncEnable")->getSignal()->connect(boost::bind(&handleVSyncChanged, _2));  	gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));  	gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2));  	gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2)); -	gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2)); -    gSavedSettings.getControl("RenderPBR")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2)); +	// DEPRECATED - gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2)); +    gSavedSettings.getControl("RenderPBR")->getSignal()->connect(boost::bind(&handleRenderPBRChanged, _2));  	gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); -	gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));  	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2));  	gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2));  	gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6d98d9b10e..77b84c6789 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -797,8 +797,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  				LLViewerTexture::updateClass();  			} -            LLImageGLThread::updateClass(); -  			{  				LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP);  				gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first. diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp new file mode 100644 index 0000000000..cec08c4f15 --- /dev/null +++ b/indra/newview/llviewerdisplayname.cpp @@ -0,0 +1,226 @@ +/**  + * @file llviewerdisplayname.cpp + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewerdisplayname.h" + +// viewer includes +#include "llagent.h" +#include "llfloaterprofile.h" +#include "llfloaterreg.h" +#include "llviewerregion.h" +#include "llvoavatar.h" + +// library includes +#include "llavatarnamecache.h" +#include "llhttpnode.h" +#include "llnotificationsutil.h" +#include "llui.h"					// getLanguage() + +namespace LLViewerDisplayName +{ +	// Fired when viewer receives server response to display name change +	set_name_signal_t sSetDisplayNameSignal; + +	// Fired when there is a change in the agent's name +	name_changed_signal_t sNameChangedSignal; + +	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb)  +	{  +		sNameChangedSignal.connect(cb);  +	} + +	void doNothing() { } +} + +void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot) +{ +	// TODO: simple validation here + +	LLViewerRegion* region = gAgent.getRegion(); +	llassert(region); +	std::string cap_url = region->getCapability("SetDisplayName"); +	if (cap_url.empty()) +	{ +		// this server does not support display names, report error +		slot(false, "unsupported", LLSD()); +		return; +	} + +	// People API requires both the old and new value to change a variable. +	// Our display name will be in cache before the viewer's UI is available +	// to request a change, so we can use direct lookup without callback. +	LLAvatarName av_name; +	if (!LLAvatarNameCache::get( gAgent.getID(), &av_name)) +	{ +		slot(false, "name unavailable", LLSD()); +		return; +	} + +	// People API expects array of [ "old value", "new value" ] +	LLSD change_array = LLSD::emptyArray(); +	change_array.append(av_name.getDisplayName()); +	change_array.append(display_name); +	 +	LL_INFOS() << "Set name POST to " << cap_url << LL_ENDL; + +	// Record our caller for when the server sends back a reply +	sSetDisplayNameSignal.connect(slot); +	 +	// POST the requested change.  The sim will not send a response back to +	// this request directly, rather it will send a separate message after it +	// communicates with the back-end. +	LLSD body; +	body["display_name"] = change_array; +    LLCoros::instance().launch("LLViewerDisplayName::SetDisplayNameCoro", +            boost::bind(&LLViewerDisplayName::setDisplayNameCoro, cap_url, body)); +} + +void LLViewerDisplayName::setDisplayNameCoro(const std::string& cap_url, const LLSD& body) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("SetDisplayNameCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); + +    // People API can return localized error messages.  Indicate our +    // language preference via header. +    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT_LANGUAGE, LLUI::getLanguage()); + +    LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, body, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS() << "Unable to set display name. Status: " << status.toString() << LL_ENDL; +        LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); +        LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); +    } +} + +class LLSetDisplayNameReply : public LLHTTPNode +{ +	LOG_CLASS(LLSetDisplayNameReply); +public: +	/*virtual*/ void post( +		LLHTTPNode::ResponsePtr response, +		const LLSD& context, +		const LLSD& input) const +	{ +		LLSD body = input["body"]; + +		S32 status = body["status"].asInteger(); +		bool success = (status == HTTP_OK); +		std::string reason = body["reason"].asString(); +		LLSD content = body["content"]; + +		LL_INFOS() << "status " << status << " reason " << reason << LL_ENDL; + +		// If viewer's concept of display name is out-of-date, the set request +		// will fail with 409 Conflict.  If that happens, fetch up-to-date +		// name information. +		if (status == HTTP_CONFLICT) +		{ +			LLUUID agent_id = gAgent.getID(); +			// Flush stale data +			LLAvatarNameCache::getInstance()->erase( agent_id ); +			// Queue request for new data: nothing to do on callback though... +			// Note: no need to disconnect the callback as it never gets out of scope +            LLAvatarNameCache::getInstance()->get(agent_id, boost::bind(&LLViewerDisplayName::doNothing)); +			// Kill name tag, as it is wrong +			LLVOAvatar::invalidateNameTag( agent_id ); +		} + +		// inform caller of result +		LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content); +		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); +	} +}; + + +class LLDisplayNameUpdate : public LLHTTPNode +{ +	/*virtual*/ void post( +		LLHTTPNode::ResponsePtr response, +		const LLSD& context, +		const LLSD& input) const +	{ +		LLSD body = input["body"]; +		LLUUID agent_id = body["agent_id"]; +		std::string old_display_name = body["old_display_name"]; +		// By convention this record is called "agent" in the People API +		LLSD name_data = body["agent"]; + +		// Inject the new name data into cache +		LLAvatarName av_name; +		av_name.fromLLSD( name_data ); + +		LL_INFOS() << "name-update now " << LLDate::now() +			<< " next_update " << LLDate(av_name.mNextUpdate) +			<< LL_ENDL; + +		// Name expiration time may be provided in headers, or we may use a +		// default value +		// *TODO: get actual headers out of ResponsePtr +		//LLSD headers = response->mHeaders; +		LLSD headers; +		av_name.mExpires =  +            LLAvatarNameCache::getInstance()->nameExpirationFromHeaders(headers); + +        LLAvatarNameCache::getInstance()->insert(agent_id, av_name); + +		// force name tag to update +		LLVOAvatar::invalidateNameTag(agent_id); + +		LLSD args; +		args["OLD_NAME"] = old_display_name; +		args["SLID"] = av_name.getUserName(); +		args["NEW_NAME"] = av_name.getDisplayName(); +		LLNotificationsUtil::add("DisplayNameUpdate", args); +		if (agent_id == gAgent.getID()) +		{ +			LLViewerDisplayName::sNameChangedSignal(); +		} + +        LLFloaterProfile* profile_floater = dynamic_cast<LLFloaterProfile*>(LLFloaterReg::findInstance("profile", LLSD().with("id", agent_id))); +        if (profile_floater) +        { +            profile_floater->refreshName(); +        } +	} +}; + +LLHTTPRegistration<LLSetDisplayNameReply> +    gHTTPRegistrationMessageSetDisplayNameReply( +		"/message/SetDisplayNameReply"); + +LLHTTPRegistration<LLDisplayNameUpdate> +    gHTTPRegistrationMessageDisplayNameUpdate( +		"/message/DisplayNameUpdate"); diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h new file mode 100644 index 0000000000..337aaa68b6 --- /dev/null +++ b/indra/newview/llviewerdisplayname.h @@ -0,0 +1,55 @@ +/**  + * @file llviewerdisplayname.h + * @brief Wrapper for display name functionality + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERDISPLAYNAME_H +#define LLVIEWERDISPLAYNAME_H + +#include <boost/signals2.hpp> + +class LLSD; +class LLUUID; + +namespace LLViewerDisplayName +{ +	typedef boost::signals2::signal< +		void (bool success, const std::string& reason, const LLSD& content)> +			set_name_signal_t; +	typedef set_name_signal_t::slot_type set_name_slot_t; +	 +	typedef boost::signals2::signal<void (void)> name_changed_signal_t; +	typedef name_changed_signal_t::slot_type name_changed_slot_t; + +	// Sends an update to the server to change a display name +	// and call back when done.  May not succeed due to service +	// unavailable or name not available. +	void set(const std::string& display_name, const set_name_slot_t& slot); + +    void setDisplayNameCoro(const std::string& cap_url, const LLSD& body); + +	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb); +} + +#endif // LLVIEWERDISPLAYNAME_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 97cb8e2000..f5ccc238c0 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -57,11 +57,13 @@  #include "llfloatercamera.h"  #include "llfloatercamerapresets.h"  #include "llfloaterchatvoicevolume.h" +#include "llfloaterclassified.h"  #include "llfloaterconversationlog.h"  #include "llfloaterconversationpreview.h"  #include "llfloatercreatelandmark.h"  #include "llfloaterdeleteprefpreset.h"  #include "llfloaterdestinations.h" +#include "llfloaterdisplayname.h"  #include "llfloatereditextdaycycle.h"  #include "llfloaterenvironmentadjust.h"  #include "llfloaterexperienceprofile.h" @@ -111,6 +113,7 @@  #include "llfloaterpreference.h"  #include "llfloaterpreferenceviewadvanced.h"  #include "llfloaterpreviewtrash.h" +#include "llfloaterprofile.h"  #include "llfloaterproperties.h"  #include "llfloaterregiondebugconsole.h"  #include "llfloaterregioninfo.h" @@ -132,7 +135,6 @@  #include "llfloatertelehub.h"  #include "llfloatertestinspectors.h"  #include "llfloatertestlistview.h" -#include "llfloatertexturefetchdebugger.h"  #include "llfloatertools.h"  #include "llfloatertopobjects.h"  #include "llfloatertos.h" @@ -141,7 +143,6 @@  #include "llfloateruipreview.h"  #include "llfloatervoiceeffect.h"  #include "llfloaterwebcontent.h" -#include "llfloaterwebprofile.h"  #include "llfloatervoicevolume.h"  #include "llfloaterwhitelistentry.h"  #include "llfloaterwindowsize.h" @@ -156,7 +157,7 @@  #include "llmoveview.h"  #include "llfloaterimnearbychat.h"  #include "llpanelblockedlist.h" -#include "llpanelclassified.h" +#include "llpanelprofileclassifieds.h"  #include "llpreviewanim.h"  #include "llpreviewgesture.h"  #include "llpreviewnotecard.h" @@ -229,6 +230,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);  	LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);  	LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); +    LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);  	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);  	LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);  	LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>); @@ -276,6 +278,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLInspectRemoteObjectUtil::registerFloater();  	LLFloaterVoiceVolumeUtil::registerFloater();  	LLNotificationsUI::registerFloater(); +	LLFloaterDisplayNameUtil::registerFloater();  	LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);  	LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); @@ -284,10 +287,6 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); -	if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) -	{ -		LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); -	}  	LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);	  	LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>);  	LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>); @@ -321,7 +320,6 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>);  	LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>);  	LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>); -	LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);  	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);  	LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview");  	LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>); @@ -370,8 +368,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);      LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>);      LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); -	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); -	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); +    LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);  	LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);  	LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 812f804ea9..661f70972d 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -48,7 +48,7 @@  #include "llmutelist.h"  #include "llnotifications.h"  #include "llnotificationsutil.h" -#include "llpanelprofile.h" +#include "llavataractions.h"  #include "llparcel.h"  #include "llpluginclassmedia.h"  #include "llurldispatcher.h" diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 34ce35ddeb..dd82d43ab2 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2347,21 +2347,6 @@ class LLAdvancedEnableRenderDeferred: public view_listener_t  	}  }; -///////////////////////////////////// -// Enable Deferred Rendering sub-options -///////////////////////////////////// -class LLAdvancedEnableRenderDeferredOptions: public view_listener_t -{ -	bool handleEvent(const LLSD& userdata) -	{ -		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 && -			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred"); -		return new_value; -	} -}; - - -  //////////////////  // ADMIN STATUS //  ////////////////// @@ -2530,14 +2515,6 @@ class LLDevelopSetLoggingLevel : public view_listener_t  	}  }; -class LLDevelopTextureFetchDebugger : public view_listener_t -{ -	bool handleEvent(const LLSD& userdata) -	{ -		return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); -	} -}; -  //////////////////  // ADMIN MENU   //  ////////////////// @@ -2724,6 +2701,32 @@ void handle_object_touch()  	send_ObjectDeGrab_message(object, pick);  } +void handle_object_show_original() +{ +    LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +    if (!object) +    { +        return; +    } + +    LLViewerObject *parent = (LLViewerObject*)object->getParent(); +    while (parent) +    { +        if(parent->isAvatar()) +        { +            break; +        } +        object = parent; +        parent = (LLViewerObject*)parent->getParent(); +    } + +    if (!object || object->isAvatar()) +    { +        return; +    } + +    show_item_original(object->getAttachmentItemID()); +}  static void init_default_item_label(const std::string& item_name) @@ -3608,6 +3611,11 @@ bool my_profile_visible()  	return floaterp && floaterp->isInVisibleChain();  } +bool picks_tab_visible() +{ +    return my_profile_visible() && LLAvatarActions::isPickTabSelected(gAgentID); +} +  bool enable_freeze_eject(const LLSD& avatar_id)  {  	// Use avatar_id if available, otherwise default to right-click avatar @@ -6301,6 +6309,29 @@ class LLAvatarToggleMyProfile : public view_listener_t  	}  }; +class LLAvatarTogglePicks : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        LLFloater * instance = LLAvatarActions::getProfileFloater(gAgent.getID()); +        if (LLFloater::isMinimized(instance) || (instance && !instance->hasFocus() && !instance->getIsChrome())) +        { +            instance->setMinimized(FALSE); +            instance->setFocus(TRUE); +            LLAvatarActions::showPicks(gAgent.getID()); +        } +        else if (picks_tab_visible()) +        { +            instance->closeFloater(); +        } +        else +        { +            LLAvatarActions::showPicks(gAgent.getID()); +        } +        return true; +    } +}; +  class LLAvatarToggleSearch : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -6771,6 +6802,15 @@ class LLShowAgentProfile : public view_listener_t  	}  }; +class LLShowAgentProfilePicks : public view_listener_t +{ +    bool handleEvent(const LLSD& userdata) +    { +        LLAvatarActions::showPicks(gAgent.getID()); +        return true; +    } +}; +  class LLToggleAgentProfile : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -9328,9 +9368,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");  	// Develop > Render  	view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion"); -	view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO"); -	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred"); -	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions"); +	  	view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");  	view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");  	view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame"); @@ -9462,8 +9500,6 @@ void initialize_menus()  	view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");  	view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); -	//Develop (Texture Fetch Debug Console) -	view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");  	//Develop (clear cache immediately)  	commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );      //Develop (override environment map) @@ -9515,12 +9551,14 @@ void initialize_menus()  	enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));  	view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");  	view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); +	view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks");  	view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch");  	view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton");  	view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton");  	view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations");  	view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations");  	enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible)); +    enable.add("Avatar.IsPicksTabOpen", boost::bind(&picks_tab_visible));  	commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL"))); @@ -9530,6 +9568,7 @@ void initialize_menus()  	// Object pie menu  	view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");  	commit.add("Object.Touch", boost::bind(&handle_object_touch)); +	commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original));  	commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));  	commit.add("Object.Delete", boost::bind(&handle_object_delete));  	view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); @@ -9596,6 +9635,7 @@ void initialize_menus()  	view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak");  	view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");  	view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); +    view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks");  	view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");  	view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");      view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 148a76d93b..ffa2ce865e 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -249,6 +249,16 @@ LLFilePickerReplyThread::~LLFilePickerReplyThread()  	delete mFailureSignal;  } +void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type & failure_cb) +{ +    (new LLFilePickerReplyThread(cb, filter, get_multiple, failure_cb))->getFile(); +} + +void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ESaveFilter filter, const std::string & proposed_name, const file_picked_signal_t::slot_type & failure_cb) +{ +    (new LLFilePickerReplyThread(cb, filter, proposed_name, failure_cb))->getFile(); +} +  void LLFilePickerReplyThread::notify(const std::vector<std::string>& filenames)  {  	if (filenames.empty()) @@ -571,7 +581,7 @@ class LLFileUploadImage : public view_listener_t  		{  			gAgentCamera.changeCameraToDefault();  		} -		(new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false);  		return true;  	}  }; @@ -589,11 +599,7 @@ class LLFileUploadMaterial : public view_listener_t  {      bool handleEvent(const LLSD& userdata)      { -        LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor"); -        if (me) -        { -            me->importMaterial(); -        } +        LLMaterialEditor::importMaterial();          return TRUE;      }  }; @@ -606,7 +612,7 @@ class LLFileUploadSound : public view_listener_t  		{  			gAgentCamera.changeCameraToDefault();  		} -		(new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false);  		return true;  	}  }; @@ -619,7 +625,7 @@ class LLFileUploadAnim : public view_listener_t  		{  			gAgentCamera.changeCameraToDefault();  		} -		(new LLFilePickerReplyThread(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false);  		return true;  	}  }; @@ -632,7 +638,7 @@ class LLFileUploadBulk : public view_listener_t  		{  			gAgentCamera.changeCameraToDefault();  		} -		(new LLFilePickerReplyThread(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true);  		return true;  	}  }; diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index beeac418d9..5c2caf9c51 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -115,14 +115,18 @@ class LLFilePickerReplyThread : public LLFilePickerThread  public:  	typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t; -	 -	LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); -	LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); -	~LLFilePickerReplyThread(); + +    static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); +    static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());  	virtual void notify(const std::vector<std::string>& filenames);  private: +    LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); +    LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); +    ~LLFilePickerReplyThread(); + +private:  	LLFilePicker::ELoadFilter	mLoadFilter;  	LLFilePicker::ESaveFilter	mSaveFilter;  	file_picked_signal_t*		mFilePickedSignal; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 753fb014c9..bdc47e0c50 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4903,7 +4903,14 @@ void LLViewerObject::updateTEMaterialTextures(U8 te)      auto fetch_texture = [](const LLUUID& id)      { -        return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); +        LLViewerFetchedTexture* img = nullptr; +        if (id.notNull()) +        { +            img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE); +            img->addTextureStats(64.f * 64.f, TRUE); +        } + +        return img;      };      LLGLTFMaterial* mat = getTE(te)->getGLTFMaterial(); diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 12624ec3a2..36b2bd4c32 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -948,6 +948,7 @@ void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_M          break;      case STATE_MODE_DIFF: +        if (mOctreeNode)          {              LLSpatialSetOcclusionStateDiff setter(state);              setter.traverse(mOctreeNode); @@ -955,6 +956,7 @@ void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_M          break;      case STATE_MODE_BRANCH: +        if (mOctreeNode)          {              LLSpatialSetOcclusionState setter(state);              setter.traverse(mOctreeNode); @@ -1024,6 +1026,7 @@ void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE              break;          case STATE_MODE_DIFF: +            if (mOctreeNode)              {                  LLSpatialClearOcclusionStateDiff clearer(state);                  clearer.traverse(mOctreeNode); @@ -1031,6 +1034,7 @@ void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE              break;          case STATE_MODE_BRANCH: +            if (mOctreeNode)              {                  LLSpatialClearOcclusionState clearer(state);                  clearer.traverse(mOctreeNode); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 9b7f4ff30d..4abf53d1c5 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -266,14 +266,13 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              return;          } -        LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton! -        if (!world_inst) +        if (!LLWorld::instanceExists())          {              LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL;              return;          } -        regionp = world_inst->getRegionFromHandle(regionHandle); +        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);          if (!regionp) //region was removed          {              LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL; @@ -321,7 +320,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)          regionp = NULL;          impl = NULL; -        world_inst = NULL;          result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);          if (STATE_WORLD_INIT > LLStartUp::getStartupState()) @@ -332,17 +330,36 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)          if (LLApp::isExiting() || gDisconnected)          { +            LL_DEBUGS("AppInit", "Capabilities") << "Shutting down" << LL_ENDL;              return;          } -        world_inst = LLWorld::getInstance(); -        if (!world_inst) +        if (!result.isMap() || result.has("error")) +        { +            LL_WARNS("AppInit", "Capabilities") << "Malformed response" << LL_ENDL; +            // setup for retry. +            continue; +        } + +        LLSD httpResults = result["http_result"]; +        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); +        if (!status) +        { +            LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL; +            // setup for retry. +            continue; +        } + +        // remove the http_result from the llsd +        result.erase("http_result"); + +        if (!LLWorld::instanceExists())          {              LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL;              return;          } -        regionp = world_inst->getRegionFromHandle(regionHandle); +        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);          if (!regionp) //region was removed          {              LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL; @@ -351,7 +368,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)          impl = regionp->getRegionImplNC(); -        ++impl->mSeedCapAttempts; +        ++(impl->mSeedCapAttempts);          if (id != impl->mHttpResponderID) // region is no longer referring to this request          { @@ -360,25 +377,6 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)              continue;          } -        if (!result.isMap() || result.has("error")) -        { -            LL_WARNS("AppInit", "Capabilities") << "Malformed response" << LL_ENDL; -            // setup for retry. -            continue; -        } - -        LLSD httpResults = result["http_result"]; -        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); -        if (!status) -        { -            LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL; -            // setup for retry. -            continue; -        } - -        // remove the http_result from the llsd -        result.erase("http_result"); -          LLSD::map_const_iterator iter;          for (iter = result.beginMap(); iter != result.endMap(); ++iter)          { @@ -3002,6 +3000,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("AcceptFriendship");  	capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!!  	capabilityNames.append("AgentPreferences"); +    capabilityNames.append("AgentProfile");  	capabilityNames.append("AgentState");  	capabilityNames.append("AttachmentResources");  	capabilityNames.append("AvatarPickerSearch"); @@ -3096,6 +3095,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("UpdateScriptTask");      capabilityNames.append("UpdateSettingsAgentInventory");      capabilityNames.append("UpdateSettingsTaskInventory"); +    capabilityNames.append("UploadAgentProfileImage");      capabilityNames.append("UpdateMaterialAgentInventory");      capabilityNames.append("UpdateMaterialTaskInventory");  	capabilityNames.append("UploadBakedTexture"); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e76f0b36ee..0d9670d9ca 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -493,12 +493,12 @@ void LLViewerShaderMgr::setShaders()      llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10)); -    bool canRenderDeferred       = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); -    bool hasWindLightShaders     = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); +    //bool canRenderDeferred = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); +    //bool hasWindLightShaders = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");      S32 shadow_detail            = gSavedSettings.getS32("RenderShadowDetail");      bool pbr = gSavedSettings.getBOOL("RenderPBR"); -    bool doingWindLight          = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders"); -    bool useRenderDeferred       = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred"); +    bool doingWindLight = true; //DEPRECATED -- hasWindLightShaders&& gSavedSettings.getBOOL("WindLightUseAtmosShaders"); +    bool useRenderDeferred = true; //DEPRECATED -- doingWindLight&& canRenderDeferred&& gSavedSettings.getBOOL("RenderDeferred");      S32 light_class = 3;      S32 interface_class = 2; @@ -569,15 +569,14 @@ void LLViewerShaderMgr::setShaders()      mShaderLevel[SHADER_DEFERRED] = deferred_class;      mShaderLevel[SHADER_TRANSFORM] = transform_class; -    BOOL loaded = loadBasicShaders(); -    if (loaded) +    std::string shader_name = loadBasicShaders(); +    if (shader_name.empty())      {          LL_INFOS() << "Loaded basic shaders." << LL_ENDL;      }      else      { -        LL_ERRS() << "Unable to load basic shaders, verify graphics driver installed and current." << LL_ENDL; -        llassert(loaded); +        LL_ERRS() << "Unable to load basic shader " << shader_name << ", verify graphics driver installed and current." << LL_ENDL;          reentrance = false; // For hygiene only, re-try probably helps nothing           return;      } @@ -585,7 +584,7 @@ void LLViewerShaderMgr::setShaders()      gPipeline.mShadersLoaded = true;      // Load all shaders to set max levels -    loaded = loadShadersEnvironment(); +    BOOL loaded = loadShadersEnvironment();      if (loaded)      { @@ -675,67 +674,24 @@ void LLViewerShaderMgr::setShaders()          if (loadShadersObject())          { //hardware skinning is enabled and rigged attachment shaders loaded correctly -            BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); -              // cloth is a class3 shader -            S32 avatar_class = avatar_cloth ? 3 : 1; +            S32 avatar_class = 1;              // Set the actual level              mShaderLevel[SHADER_AVATAR] = avatar_class;              loaded = loadShadersAvatar();              llassert(loaded); - -            if (mShaderLevel[SHADER_AVATAR] != avatar_class) -            { -                if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3) -                { -                    avatar_cloth = true; -                } -                else -                { -                    avatar_cloth = false; -                } -                gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); -            }          }          else          { //hardware skinning not possible, neither is deferred rendering -            mShaderLevel[SHADER_AVATAR] = 0; -            mShaderLevel[SHADER_DEFERRED] = 0; - -                gSavedSettings.setBOOL("RenderDeferred", FALSE); -                gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); - -            loadShadersAvatar(); // unloads - -            loaded = loadShadersObject(); -            llassert(loaded); +            llassert(false); // SHOULD NOT BE POSSIBLE          }      } -    if (!loaded) -    { //some shader absolutely could not load, try to fall back to a simpler setting -        if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) -        { //disable windlight and try again -            gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); -            LL_WARNS() << "Falling back to no windlight shaders." << LL_ENDL; -            reentrance = false; -            setShaders(); -            return; -        } -    }        -      llassert(loaded); - -    if (loaded && !loadShadersDeferred()) -    { //everything else succeeded but deferred failed, disable deferred and try again -        gSavedSettings.setBOOL("RenderDeferred", FALSE); -        LL_WARNS() << "Falling back to no deferred shaders." << LL_ENDL; -        reentrance = false; -        setShaders(); -        return; -    } +    loaded = loaded && loadShadersDeferred(); +    llassert(loaded);      if (gViewerWindow)      { @@ -874,7 +830,7 @@ void LLViewerShaderMgr::unloadShaders()  	gPipeline.mShadersLoaded = false;  } -BOOL LLViewerShaderMgr::loadBasicShaders() +std::string LLViewerShaderMgr::loadBasicShaders()  {  	// Load basic dependency shaders first  	// All of these have to load for any shaders to function @@ -960,8 +916,8 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  		// Note usage of GL_VERTEX_SHADER_ARB  		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0)  		{ -			LL_SHADER_LOADING_WARNS() << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; -			return FALSE; +			LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; +			return shaders[i].first;  		}  	} @@ -1021,12 +977,12 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  		// Note usage of GL_FRAGMENT_SHADER_ARB  		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0)  		{ -			LL_SHADER_LOADING_WARNS() << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; -			return FALSE; +			LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; +			return shaders[i].first;  		}  	} -	return TRUE; +	return std::string();  }  BOOL LLViewerShaderMgr::loadShadersEnvironment() diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 87d90b49a9..ef49074959 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -49,7 +49,11 @@ public:  	void setShaders();  	void unloadShaders();      S32  getShaderLevel(S32 type); -	BOOL loadBasicShaders(); + +    // loadBasicShaders in case of a failure returns +    // name of a file error happened at, otherwise +    // returns an empty string +    std::string loadBasicShaders();  	BOOL loadShadersEffects();  	BOOL loadShadersDeferred();  	BOOL loadShadersObject(); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 3385d317e6..796ff04a41 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -155,10 +155,7 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> >  static LLTrace::SampleStatHandle<bool>   							CHAT_BUBBLES("chatbubbles", "Chat Bubbles Enabled"); -LLTrace::SampleStatHandle<F64Megabytes >	GL_TEX_MEM("gltexmemstat"), -															GL_BOUND_MEM("glboundmemstat"), -															RAW_MEM("rawmemstat"), -															FORMATTED_MEM("formattedmemstat"); +LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM("formattedmemstat");  LLTrace::SampleStatHandle<F64Kilobytes >	DELTA_BANDWIDTH("deltabandwidth", "Increase/Decrease in bandwidth based on packet loss"),  															MAX_BANDWIDTH("maxbandwidth", "Max bandwidth setting"); @@ -319,8 +316,6 @@ U32Bytes			gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGOR  extern U32  gVisCompared;  extern U32  gVisTested; -LLFrameTimer gTextureTimer; -  void update_statistics()  {  	gTotalWorldData += gVLManager.getTotalBytes(); @@ -416,19 +411,6 @@ void update_statistics()  	}  } -void update_texture_time() -{ -	if (gTextureList.isPrioRequestsFetched()) -	{ -		gTextureTimer.pause(); -	} -	else -	{		 -		gTextureTimer.unpause(); -	} - -	record(LLStatViewer::TEXTURE_FETCH_TIME, gTextureTimer.getElapsedTimeF32()); -}  /*   * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.   * diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 017c79b2e3..c21c06256e 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -191,10 +191,8 @@ extern LLTrace::SampleStatHandle<>		FPS_SAMPLE,  extern LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > PACKETS_LOST_PERCENT; -extern LLTrace::SampleStatHandle<F64Megabytes >	GL_TEX_MEM, -																	GL_BOUND_MEM, -																	RAW_MEM, -																	FORMATTED_MEM; +extern LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM; +  extern LLTrace::SampleStatHandle<F64Kilobytes >	DELTA_BANDWIDTH,  																	MAX_BANDWIDTH;  extern SimMeasurement<F64Milliseconds >	SIM_FRAME_TIME, @@ -296,7 +294,6 @@ void update_statistics();  void send_viewer_stats(bool include_preferences);  void update_texture_time(); -extern LLFrameTimer gTextureTimer;  extern U32Bytes	gTotalTextureData;  extern U32Bytes  gTotalObjectData;  extern U32Bytes  gTotalTextureBytesPerBoostLevel[] ; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c389d2122e..52294ec487 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -58,6 +58,8 @@  #include "llvovolume.h"  #include "llviewermedia.h"  #include "lltexturecache.h" +#include "llviewerwindow.h" +#include "llwindow.h"  ///////////////////////////////////////////////////////////////////////////////  // extern @@ -74,8 +76,11 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sFlatNormalImagep = NULL; +LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultIrradiancePBRp;  LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap;  LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL; +F32 LLViewerFetchedTexture::sMaxVirtualSize = 8192.f*8192.f; +  const std::string sTesterName("TextureTester");  S32 LLViewerTexture::sImageCount = 0; @@ -84,11 +89,6 @@ S32 LLViewerTexture::sAuxCount = 0;  LLFrameTimer LLViewerTexture::sEvaluationTimer;  F32 LLViewerTexture::sDesiredDiscardBias = 0.f;  F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S32Bytes LLViewerTexture::sBoundTextureMemory; -S32Bytes LLViewerTexture::sTotalTextureMemory; -S32Megabytes LLViewerTexture::sMaxBoundTextureMemory; -S32Megabytes LLViewerTexture::sMaxTotalTextureMem; -S32Bytes LLViewerTexture::sMaxDesiredTextureMem;  S8  LLViewerTexture::sCameraMovingDiscardBias = 0;  F32 LLViewerTexture::sCameraMovingBias = 0.0f;  S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size @@ -100,7 +100,6 @@ U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.  U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;  bool LLViewerTexture::sFreezeImageUpdates = false;  F32 LLViewerTexture::sCurrentTime = 0.0f; -F32  LLViewerTexture::sTexelPixelRatio = 1.0f;  LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; @@ -459,6 +458,7 @@ void LLViewerTextureManager::cleanup()  	LLViewerFetchedTexture::sWhiteImagep = NULL;  	LLViewerFetchedTexture::sFlatNormalImagep = NULL; +	LLViewerFetchedTexture::sDefaultIrradiancePBRp = NULL;  	LLViewerMediaTexture::cleanUpClass();	  } @@ -471,11 +471,6 @@ void LLViewerTextureManager::cleanup()  void LLViewerTexture::initClass()  {  	LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); -	 -	if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) -	{ -		sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio"); -	}  }  // tuning params @@ -500,7 +495,7 @@ bool LLViewerTexture::isMemoryForTextureLow()      S32Megabytes physical;      getGPUMemoryForTextures(gpu, physical); -    return (gpu < MIN_FREE_TEXTURE_MEMORY) || (physical < MIN_FREE_MAIN_MEMORY); +    return (gpu < MIN_FREE_TEXTURE_MEMORY); // || (physical < MIN_FREE_MAIN_MEMORY);  }  //static @@ -514,7 +509,7 @@ bool LLViewerTexture::isMemoryForTextureSuficientlyFree()      S32Megabytes physical;      getGPUMemoryForTextures(gpu, physical); -    return (gpu > DESIRED_FREE_TEXTURE_MEMORY) && (physical > DESIRED_FREE_MAIN_MEMORY); +    return (gpu > DESIRED_FREE_TEXTURE_MEMORY); // && (physical > DESIRED_FREE_MAIN_MEMORY);  }  //static @@ -535,9 +530,9 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p      timer.reset();      { -        gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); +        gpu_res = (S32Megabytes)gViewerWindow->getWindow()->getAvailableVRAMMegabytes(); -        //check main memory, only works for windows. +        //check main memory, only works for windows and macos.          LLMemory::updateMemoryInfo();          physical_res = LLMemory::getAvailableMemKB(); @@ -560,27 +555,7 @@ void LLViewerTexture::updateClass()  	LLViewerMediaTexture::updateClass(); -	sBoundTextureMemory = LLImageGL::sBoundTextureMemory; -	sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; -	sMaxBoundTextureMemory = gTextureList.getMaxResidentTexMem(); -	sMaxTotalTextureMem = gTextureList.getMaxTotalTextureMem(); -	sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small. - -	if (sBoundTextureMemory >= sMaxBoundTextureMemory || -		sTotalTextureMemory >= sMaxTotalTextureMem) -	{ -		//when texture memory overflows, lower down the threshold to release the textures more aggressively. -		sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam)); -	 -		// If we are using more texture memory than we should, -		// scale up the desired discard level -		if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time) -		{ -			sDesiredDiscardBias += discard_bias_delta; -			sEvaluationTimer.reset(); -		} -	} -	else if(isMemoryForTextureLow()) +	if(isMemoryForTextureLow())  	{  		// Note: isMemoryForTextureLow() uses 1s delay, make sure we waited enough for it to recheck  		if (sEvaluationTimer.getElapsedTimeF32() > GPU_MEMORY_CHECK_WAIT_TIME) @@ -590,8 +565,6 @@ void LLViewerTexture::updateClass()  		}  	}  	else if (sDesiredDiscardBias > 0.0f -			 && sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale -			 && sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale  			 && isMemoryForTextureSuficientlyFree())  	{  		// If we are using less texture memory than we should, @@ -661,7 +634,6 @@ void LLViewerTexture::init(bool firstinit)  	mMaxVirtualSize = 0.f;  	mMaxVirtualSizeResetInterval = 1;  	mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; -	mAdditionalDecodePriority = 0.f;	  	mParcelMedia = NULL;  	memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); @@ -689,6 +661,11 @@ void LLViewerTexture::cleanup()  {  	notifyAboutMissingAsset(); +    if (LLAppViewer::getTextureFetch()) +    { +        LLAppViewer::getTextureFetch()->updateRequestPriority(mID, 0.f); +    } +  	mFaceList[LLRender::DIFFUSE_MAP].clear();  	mFaceList[LLRender::NORMAL_MAP].clear();  	mFaceList[LLRender::SPECULAR_MAP].clear(); @@ -745,6 +722,12 @@ void LLViewerTexture::setBoostLevel(S32 level)  		}  	} +    // strongly encourage anything boosted to load at full res +    if (mBoostLevel >= LLViewerTexture::BOOST_HIGH) +    { +        mMaxVirtualSize = 2048.f * 2048.f; +    } +  	if (mBoostLevel == LLViewerTexture::BOOST_SELECTED)  	{  		mSelectedTime = gFrameTimeSeconds; @@ -827,16 +810,9 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co  		mNeedsGLTexture = TRUE;  	} -	virtual_size *= sTexelPixelRatio; -	if(!mMaxVirtualSizeResetCounter) -	{ -		//flag to reset the values because the old values are used. -		resetMaxVirtualSizeResetCounter(); -		mMaxVirtualSize = virtual_size; -		mAdditionalDecodePriority = 0.f; -		mNeedsGLTexture = needs_gltexture; -	} -	else if (virtual_size > mMaxVirtualSize) +    virtual_size = llmin(virtual_size, LLViewerFetchedTexture::sMaxVirtualSize); + +	if (virtual_size > mMaxVirtualSize)  	{  		mMaxVirtualSize = virtual_size;  	} @@ -845,7 +821,6 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co  void LLViewerTexture::resetTextureStats()  {  	mMaxVirtualSize = 0.0f; -	mAdditionalDecodePriority = 0.f;	  	mMaxVirtualSizeResetCounter = 0;  } @@ -1114,7 +1089,6 @@ void LLViewerFetchedTexture::init(bool firstinit)  	if (firstinit)  	{ -		mDecodePriority = 0.f;  		mInImageList = 0;  	} @@ -1163,6 +1137,7 @@ void LLViewerFetchedTexture::init(bool firstinit)  LLViewerFetchedTexture::~LLViewerFetchedTexture()  { +    assert_main_thread();  	//*NOTE getTextureFetch can return NULL when Viewer is shutting down.  	// This is due to LLWearableList is singleton and is destroyed after   	// LLAppViewer::cleanup() was called. (see ticket EXT-177) @@ -1359,10 +1334,7 @@ void LLViewerFetchedTexture::dump()  void LLViewerFetchedTexture::destroyTexture()   {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. -	{ -		return ; -	} +  	if (mNeedsCreateTexture)//return if in the process of generating a new texture.  	{  		return; @@ -1598,6 +1570,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)  void LLViewerFetchedTexture::postCreateTexture()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;      if (!mNeedsCreateTexture)      {          return; @@ -1621,6 +1594,8 @@ void LLViewerFetchedTexture::postCreateTexture()  void LLViewerFetchedTexture::scheduleCreateTexture()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +      if (!mNeedsCreateTexture)      {          mNeedsCreateTexture = TRUE; @@ -1697,6 +1672,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture()  //virtual  void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if(mKnownDrawWidth < width || mKnownDrawHeight < height)  	{  		mKnownDrawWidth = llmax(mKnownDrawWidth, width); @@ -1708,9 +1684,31 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)  	addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight));  } +void LLViewerFetchedTexture::setDebugText(const std::string& text) +{ +    for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) +    { +        llassert(mNumFaces[ch] <= mFaceList[ch].size()); + +        for (U32 i = 0; i < mNumFaces[ch]; i++) +        { +            LLFace* facep = mFaceList[ch][i]; +            if (facep) +            { +                LLDrawable* drawable = facep->getDrawable(); +                if (drawable) +                { +                    drawable->getVObj()->setDebugText(text); +                } +            } +        } +    } +} +  //virtual  void LLViewerFetchedTexture::processTextureStats()  { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if(mFullyLoaded)  	{		  		if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more @@ -1718,6 +1716,7 @@ void LLViewerFetchedTexture::processTextureStats()  			mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel);  			mFullyLoaded = FALSE;  		} +        //setDebugText("fully loaded");  	}  	else  	{ @@ -1730,7 +1729,7 @@ void LLViewerFetchedTexture::processTextureStats()  			mDesiredDiscardLevel = 0;  		}  		else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) -		{ +		{ // ??? don't load spec and normal maps when alm is disabled ???  			mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;  		}          else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) @@ -1788,198 +1787,8 @@ void LLViewerFetchedTexture::processTextureStats()  	}  } -const F32 MAX_PRIORITY_PIXEL                         = 999.f;     //pixel area -const F32 PRIORITY_BOOST_LEVEL_FACTOR                = 1000.f;    //boost level -const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR        = 100000.f;  //delta discard -const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY       = 4; -const F32 PRIORITY_ADDITIONAL_FACTOR                 = 1000000.f; //additional  -const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY          = 8; -const F32 PRIORITY_BOOST_HIGH_FACTOR                 = 10000000.f;//boost high -F32 LLViewerFetchedTexture::calcDecodePriority() -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD -	if (mID == LLAppViewer::getTextureFetch()->mDebugID) -	{ -		LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints -	} -#endif -	 -	if (mNeedsCreateTexture) -	{ -		return mDecodePriority; // no change while waiting to create -	} -	if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture -	{ -		return -1.0f; //alreay fetched -	} - -	S32 cur_discard = getCurrentDiscardLevelForFetching(); -	bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); -	F32 pixel_priority = (F32) sqrt(mMaxVirtualSize); - -	F32 priority = 0.f; - -	if (mIsMissingAsset) -	{ -		priority = 0.0f; -	} -	else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) -	{ -		priority = -2.0f; -	} -	else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) -	{ -		priority = -3.0f; -	} -	else if (mDesiredDiscardLevel > getMaxDiscardLevel()) -	{ -		// Don't decode anything we don't need -		priority = -4.0f; -	} -	else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data) -	{ -		priority = 1.f; -	} -	else if (pixel_priority < 0.001f && !have_all_data) -	{ -		// Not on screen but we might want some data -		if (mBoostLevel > BOOST_SELECTED) -		{ -			// Always want high boosted images -			priority = 1.f; -		} -		else -		{ -			priority = -5.f; //stop fetching -		} -	} -	else if (cur_discard < 0) -	{ -		//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. -		// priority range = 100,000 - 500,000 -		static const F64 log_2 = log(2.0); -		F32 desired = (F32)(log(32.0/pixel_priority) / log_2); -		S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; -		ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); -		priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; -		setAdditionalDecodePriority(0.1f);//boost the textures without any data so far. -	} -	else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) -	{ -		// larger mips are corrupted -		priority = -6.0f; -	} -	else -	{ -		// priority range = 100,000 - 500,000 -		S32 desired_discard = mDesiredDiscardLevel; -		if (!isJustBound() && mCachedRawImageReady) -		{ -			if(mBoostLevel < BOOST_HIGH) -			{ -				// We haven't rendered this in a while, de-prioritize it -				desired_discard += 2; -			} -			else -			{ -				// We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is -				desired_discard = cur_discard; -			} -		} - -		S32 ddiscard = cur_discard - desired_discard; -		ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); -		priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;		 -	} - -	// Priority Formula: -	// BOOST_HIGH  +  ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS -	// [10,000,000] + [1,000,000-9,000,000]  + [100,000-500,000]   + [1-20,000]  + [0-999] -	if (priority > 0.0f) -	{ -		bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize); -		if(large_enough) -		{ -			//Note:  -			//to give small, low-priority textures some chance to be fetched,  -			//cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready. -			priority *= 0.5f;  -		} - -		pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL);  - -		priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel; - -		if ( mBoostLevel > BOOST_HIGH) -		{ -			if(mBoostLevel > BOOST_SUPER_HIGH) -			{ -				//for very important textures, always grant the highest priority. -				priority += PRIORITY_BOOST_HIGH_FACTOR; -			} -			else if(mCachedRawImageReady) -			{ -				//Note:  -				//to give small, low-priority textures some chance to be fetched,  -				//if high priority texture has a 64*64 ready, lower its fetching priority. -				setAdditionalDecodePriority(0.5f); -			} -			else -			{ -				priority += PRIORITY_BOOST_HIGH_FACTOR; -			} -		}		 - -		if(mAdditionalDecodePriority > 0.0f) -		{ -			// priority range += 1,000,000.f-9,000,000.f -			F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY); -			if(large_enough) -			{ -				//Note:  -				//to give small, low-priority textures some chance to be fetched,  -				//cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready. -				additional *= 0.25f; -			} -			priority += additional; -		} -	} -	return priority; -} - -//static -F32 LLViewerFetchedTexture::maxDecodePriority() -{ -	static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR +                           //boost_high -		PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) +             //additional (view dependent factors) -		PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard -		PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) +                              //boost level -		MAX_PRIORITY_PIXEL + 1.0f;                                                        //pixel area. -	 -	return max_priority; -} -  //============================================================================ -void LLViewerFetchedTexture::setDecodePriority(F32 priority) -{ -	mDecodePriority = priority; - -	if(mDecodePriority < F_ALMOST_ZERO) -	{ -		mStopFetchingTimer.reset(); -	} -} - -void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) -{ -	priority = llclamp(priority, 0.f, 1.f); -	if(mAdditionalDecodePriority < priority) -	{ -		mAdditionalDecodePriority = priority; -	} -} -  void LLViewerFetchedTexture::updateVirtualSize()   {	      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1988,6 +1797,18 @@ void LLViewerFetchedTexture::updateVirtualSize()  		addTextureStats(0.f, FALSE);//reset  	} +    if (getBoostLevel() >= LLViewerTexture::BOOST_HIGH) +    { //always load boosted textures at highest priority full res +        addTextureStats(sMaxVirtualSize); +        return; +    } + +    if (sDesiredDiscardBias > 0.f) +    { +        // running out of video memory, don't hold onto high res textures in the background +        mMaxVirtualSize = 0.f; +    } +  	for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)  	{				  		llassert(mNumFaces[ch] <= mFaceList[ch].size()); @@ -2009,8 +1830,12 @@ void LLViewerFetchedTexture::updateVirtualSize()  						setBoostLevel(LLViewerTexture::BOOST_SELECTED);  					}  					addTextureStats(facep->getVirtualSize()); -					setAdditionalDecodePriority(facep->getImportanceToCamera()); +                    //drawable->getVObj()->setDebugText(llformat("%d:%d", (S32)sqrtf(facep->getVirtualSize()), (S32)sqrtf(getMaxVirtualSize())));  				} +                else +                { +                    //drawable->getVObj()->setDebugText(""); +                }  			}  		}  	} @@ -2072,6 +1897,16 @@ bool LLViewerFetchedTexture::isActiveFetching()  	return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE.  } +void LLViewerFetchedTexture::setBoostLevel(S32 level) +{ +    LLViewerTexture::setBoostLevel(level); + +    if (level >= LLViewerTexture::BOOST_HIGH) +    { +        mDesiredDiscardLevel = 0; +    } +} +  bool LLViewerFetchedTexture::updateFetch()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -2098,31 +1933,40 @@ bool LLViewerFetchedTexture::updateFetch()  	if (mNeedsCreateTexture)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - needs create");  		// We may be fetching still (e.g. waiting on write)  		// but don't check until we've processed the raw data we have  		return false;  	}  	if (mIsMissingAsset)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - missing asset");  		llassert_always(!mHasFetcher);  		return false; // skip  	}  	if (!mLoadedCallbackList.empty() && mRawImage.notNull())  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - callback pending");  		return false; // process any raw image data in callbacks before replacing  	}  	if(mInFastCacheList)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - in fast cache");  		return false;  	} +    if (mGLTexturep.isNull()) +    { // fix for crash inside getCurrentDiscardLevelForFetching (shouldn't happen but appears to be happening) +        llassert(false); +        return false; +    }  	S32 current_discard = getCurrentDiscardLevelForFetching();  	S32 desired_discard = getDesiredDiscardLevel(); -	F32 decode_priority = getDecodePriority(); -	decode_priority = llclamp(decode_priority, 0.0f, maxDecodePriority()); +	F32 decode_priority = mMaxVirtualSize;  	if (mIsFetching)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - is fetching");  		// Sets mRawDiscardLevel, mRawImage, mAuxRawImage  		S32 fetch_discard = current_discard; @@ -2140,17 +1984,25 @@ bool LLViewerFetchedTexture::updateFetch()  		if (finished)  		{  			mIsFetching = FALSE; +            mLastFetchState = -1; +            setDebugText("");  			mLastPacketTimer.reset();  		}  		else  		{  			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,  																		mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); +            /*if (mFetchState != mLastFetchState) +            { +                setDebugText(LLTextureFetch::getStateString(mFetchState)); +                mLastFetchState = mFetchState; +            }*/  		}  		// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)  		if (mRawImage.notNull())  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image");  			LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);  			if (tester)  			{ @@ -2161,6 +2013,7 @@ bool LLViewerFetchedTexture::updateFetch()  			if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&  				(current_discard < 0 || mRawDiscardLevel < current_discard))  			{ +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good");  				mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;  				mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;  				setTexelsPerImage(); @@ -2197,6 +2050,7 @@ bool LLViewerFetchedTexture::updateFetch()  			}  			else  			{ +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed");  				// Data is ready but we don't need it  				// (received it already while fetcher was writing to disk)  				destroyRawImage(); @@ -2206,7 +2060,7 @@ bool LLViewerFetchedTexture::updateFetch()  		if (!mIsFetching)  		{ -			if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) +			if ((decode_priority > 0) && (mRawDiscardLevel < 0))  			{  				// We finished but received no data  				if (getDiscardLevel() < 0) @@ -2229,13 +2083,13 @@ bool LLViewerFetchedTexture::updateFetch()  					if(current_discard >= 0)  					{  						mMinDiscardLevel = current_discard; -						desired_discard = current_discard; +						//desired_discard = current_discard;  					}  					else  					{  						S32 dis_level = getDiscardLevel();  						mMinDiscardLevel = dis_level; -						desired_discard = dis_level; +						//desired_discard = dis_level;  					}  				}  				destroyRawImage(); @@ -2249,12 +2103,6 @@ bool LLViewerFetchedTexture::updateFetch()  		}  		else  		{ -// 			// Useful debugging code for undesired deprioritization of textures. -// 			if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard) -// 			{ -// 				LL_INFOS() << "Calling updateRequestPriority() with decode_priority = 0.0f" << LL_ENDL; -// 				calcDecodePriority(); -// 			}  			static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f.  			if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME)  			{ @@ -2264,21 +2112,27 @@ bool LLViewerFetchedTexture::updateFetch()  		}  	} +    desired_discard = llmin(desired_discard, getMaxDiscardLevel()); +  	bool make_request = true;	 -	if (decode_priority <= 0) +	/*if (decode_priority <= 0)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - priority <= 0");  		make_request = false;  	}  	else if(mDesiredDiscardLevel > getMaxDiscardLevel())  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - desired > max");  		make_request = false;  	} -	else if (mNeedsCreateTexture || mIsMissingAsset) +	else */ if (mNeedsCreateTexture || mIsMissingAsset)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - create or missing");  		make_request = false;  	}  	else if (current_discard >= 0 && current_discard <= mMinDiscardLevel)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min");  		make_request = false;  	}  	else if(mCachedRawImage.notNull() // can be empty @@ -2295,6 +2149,7 @@ bool LLViewerFetchedTexture::updateFetch()  	if (make_request)  	{ +#if 0  		// Load the texture progressively: we try not to rush to the desired discard too fast.  		// If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps  		// This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around @@ -2311,18 +2166,23 @@ bool LLViewerFetchedTexture::updateFetch()          {  			desired_discard = llmax(desired_discard, current_discard - delta_level);          } +#endif  		if (mIsFetching)  		{ +            // already requested a higher resolution mip  			if (mRequestedDiscardLevel <= desired_discard)  			{ +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - requested < desired");  				make_request = false;  			}  		}  		else  		{ +            // already at a higher resolution mip, don't discard  			if (current_discard >= 0 && current_discard <= desired_discard)  			{ +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired");  				make_request = false;  			}  		} @@ -2330,6 +2190,7 @@ bool LLViewerFetchedTexture::updateFetch()  	if (make_request)  	{ +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - make request");  		S32 w=0, h=0, c=0;  		if (getDiscardLevel() >= 0)  		{ @@ -2351,6 +2212,7 @@ bool LLViewerFetchedTexture::updateFetch()  		if (fetch_request_created)  		{ +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created");  			mHasFetcher = TRUE;  			mIsFetching = TRUE;  			mRequestedDiscardLevel = desired_discard; @@ -2358,15 +2220,18 @@ bool LLViewerFetchedTexture::updateFetch()  													   mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);  		} -		// if createRequest() failed, we're finishing up a request for this UUID, -		// wait for it to complete +        // If createRequest() failed, that means one of two things: +        // 1. We're finishing up a request for this UUID, so we +        //    should wait for it to complete +        // 2. We've failed a request for this UUID, so there is +        //    no need to create another request  	}  	else if (mHasFetcher && !mIsFetching)  	{  		// Only delete requests that haven't received any network data  		// for a while.  Note - this is the normal mechanism for  		// deleting requests, not just a place to handle timeouts. -		const F32 FETCH_IDLE_TIME = 5.f; +		const F32 FETCH_IDLE_TIME = 0.1f;  		if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME)  		{   			LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL; @@ -2676,7 +2541,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()  			LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL;  			LL_INFOS() << mUrl << LL_ENDL;  			LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << -				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL; +				" Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << mMaxVirtualSize << LL_ENDL;  		}  		clearCallbackEntryList() ; //remove all callbacks. @@ -2907,7 +2772,7 @@ void LLViewerFetchedTexture::forceImmediateUpdate()  		return;  	}  	//if already called forceImmediateUpdate() -	if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority()) +	if(mInImageList && mMaxVirtualSize == LLViewerFetchedTexture::sMaxVirtualSize)  	{  		return;  	} @@ -2976,6 +2841,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()  void LLViewerFetchedTexture::destroyRawImage()  {	 +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if (mAuxRawImage.notNull() && !needsToSaveRawImage())  	{  		sAuxCount--; @@ -3059,6 +2925,7 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im  void LLViewerFetchedTexture::setCachedRawImage()  {	 +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if(mRawImage == mCachedRawImage)  	{  		return; @@ -3134,6 +3001,7 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage()  void LLViewerFetchedTexture::saveRawImage()   { +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel))  	{  		return; @@ -3349,25 +3217,10 @@ void LLViewerLODTexture::processTextureStats()  		}  		else  		{ -			if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f) -			{ -				//if is a big image and not being used recently, nor close to the view point, do not load hi-res data. -				mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize); -			} - -			if ((mCalculatedDiscardLevel >= 0.f) && -				(llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) -			{ -				// < 20% change in virtual size = no change in desired discard -				discard_level = mCalculatedDiscardLevel;  -			} -			else -			{ -				// Calculate the required scale factor of the image using pixels per texel -				discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); -				mDiscardVirtualSize = mMaxVirtualSize; -				mCalculatedDiscardLevel = discard_level; -			} +			// Calculate the required scale factor of the image using pixels per texel +			discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); +			mDiscardVirtualSize = mMaxVirtualSize; +			mCalculatedDiscardLevel = discard_level;  		}  		if (mBoostLevel < LLGLTexture::BOOST_SCULPTED)  		{ @@ -3407,18 +3260,6 @@ void LLViewerLODTexture::processTextureStats()  				//needs to release texture memory urgently  				scaleDown();  			} -			// Limit the amount of GL memory bound each frame -			else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale && -				(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) -			{ -				scaleDown(); -			} -			// Only allow GL to have 2x the video card memory -			else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale && -				(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) -			{ -				scaleDown(); -			}  		}  		if (isUpdateFrozen() // we are out of memory and nearing max allowed bias @@ -4199,7 +4040,6 @@ void LLTexturePipelineTester::compareTestSessions(llofstream* os)  	*os << llformat("%s\n", getTesterName().c_str());  	*os << llformat("AggregateResults\n"); -	compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime);  	compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime);  	compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime);  	compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties);		 @@ -4259,7 +4099,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo  		return NULL;  	} -	F32 total_fetching_time = 0.f;  	F32 total_gray_time = 0.f;  	F32 total_stablizing_time = 0.f;  	F32 total_loading_sculpties_time = 0.f; @@ -4294,7 +4133,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo  		F32 cur_time   = (*log)[label]["Time"].asReal();  		if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while  		{ -			sessionp->mTotalFetchingTime += total_fetching_time;  			sessionp->mTotalGrayTime += total_gray_time;  			sessionp->mTotalStablizingTime += total_stablizing_time; @@ -4302,14 +4140,12 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo  			sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time;  			start_fetching_time = start_time; -			total_fetching_time = 0.0f;  			total_gray_time = 0.f;  			total_stablizing_time = 0.f;  			total_loading_sculpties_time = 0.f;  		}  		else  		{ -			total_fetching_time = cur_time - start_time;  			total_gray_time = (*log)[label]["TotalGrayTime"].asReal();  			total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal(); @@ -4355,7 +4191,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo  		in_log = (*log).has(currentLabel);  	} -	sessionp->mTotalFetchingTime += total_fetching_time;  	sessionp->mTotalGrayTime += total_gray_time;  	sessionp->mTotalStablizingTime += total_stablizing_time; @@ -4377,8 +4212,6 @@ LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession()  }  void LLTexturePipelineTester::LLTextureTestSession::reset()   { -	mTotalFetchingTime = 0.0f; -  	mTotalGrayTime = 0.0f;  	mTotalStablizingTime = 0.0f; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 53cf911102..312e2ca365 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -134,7 +134,7 @@ public:  	/*virtual*/ bool isActiveFetching();  	/*virtual*/ const LLUUID& getID() const { return mID; } -	void setBoostLevel(S32 level); +	virtual void setBoostLevel(S32 level);  	S32  getBoostLevel() { return mBoostLevel; }  	void setTextureListType(S32 tex_type) { mTextureListType = tex_type; }  	S32 getTextureListType() { return mTextureListType; } @@ -188,19 +188,20 @@ private:  	virtual void switchToCachedImage(); -	static bool isMemoryForTextureLow() ;  	static bool isMemoryForTextureSuficientlyFree();  	static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical); +public: +    static bool isMemoryForTextureLow();  protected: +    friend class LLViewerTextureList;  	LLUUID mID;  	S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList  	F32 mSelectedTime;				// time texture was last selected -	mutable F32 mMaxVirtualSize;	// The largest virtual size of the image, in pixels - how much data to we need?	 -	mutable S32  mMaxVirtualSizeResetCounter ; +	mutable F32 mMaxVirtualSize = 0.f;	// The largest virtual size of the image, in pixels - how much data to we need?	 +	mutable S32  mMaxVirtualSizeResetCounter;  	mutable S32  mMaxVirtualSizeResetInterval; -	mutable F32 mAdditionalDecodePriority;  // priority add to mDecodePriority.  	LLFrameTimer mLastReferencedTimer;	  	ll_face_list_t    mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture @@ -217,7 +218,6 @@ protected:  	LL::WorkQueue::weak_t mMainQueue;  	LL::WorkQueue::weak_t mImageQueue; -	static F32 sTexelPixelRatio;  public:  	static const U32 sCurrentFileVersion;	  	static S32 sImageCount; @@ -226,11 +226,6 @@ public:  	static LLFrameTimer sEvaluationTimer;  	static F32 sDesiredDiscardBias;  	static F32 sDesiredDiscardScale; -	static S32Bytes sBoundTextureMemory; -	static S32Bytes sTotalTextureMemory; -	static S32Megabytes sMaxBoundTextureMemory; -	static S32Megabytes sMaxTotalTextureMem; -	static S32Bytes sMaxDesiredTextureMem ;  	static S8  sCameraMovingDiscardBias;  	static F32 sCameraMovingBias;  	static S32 sMaxSculptRez ; @@ -285,7 +280,6 @@ public:  	LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);  public: -	static F32 maxDecodePriority();  	struct Compare  	{ @@ -294,9 +288,10 @@ public:  		{  			const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs;  			const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs; +              			// greater priority is "less" -			const F32 lpriority = lhsp->getDecodePriority(); -			const F32 rpriority = rhsp->getDecodePriority(); +			const F32 lpriority = lhsp->mMaxVirtualSize; +			const F32 rpriority = rhsp->mMaxVirtualSize;  			if (lpriority > rpriority) // higher priority  				return true;  			if (lpriority < rpriority) @@ -306,10 +301,10 @@ public:  	};  public: -	/*virtual*/ S8 getType() const ; +	/*virtual*/ S8 getType() const override;  	FTType getFTType() const; -	/*virtual*/ void forceImmediateUpdate() ; -	/*virtual*/ void dump() ; +	/*virtual*/ void forceImmediateUpdate() override; +	/*virtual*/ void dump() override;  	// Set callbacks to get called when the image gets updated with higher   	// resolution versions. @@ -335,7 +330,6 @@ public:  	void destroyTexture() ;  	virtual void processTextureStats() ; -	F32  calcDecodePriority() ;  	BOOL needsAux() const { return mNeedsAux; } @@ -343,20 +337,12 @@ public:  	void setTargetHost(LLHost host)			{ mTargetHost = host; }  	LLHost getTargetHost() const			{ return mTargetHost; } -	// Set the decode priority for this image... -	// DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up -	// the priority list, and cause horrible things to happen. -	void setDecodePriority(F32 priority = -1.0f); -	F32 getDecodePriority() const { return mDecodePriority; }; -	F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; }; - -	void setAdditionalDecodePriority(F32 priority) ; -	  	void updateVirtualSize() ;  	S32  getDesiredDiscardLevel()			 { return mDesiredDiscardLevel; }  	void setMinDiscardLevel(S32 discard) 	{ mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } +    void setBoostLevel(S32 level) override;  	bool updateFetch();  	bool setDebugFetching(S32 debug_level);  	bool isInDebug() const { return mInDebug; } @@ -369,10 +355,14 @@ public:  	// Override the computation of discard levels if we know the exact output  	// size of the image.  Used for UI textures to not decode, even if we have  	// more data. -	/*virtual*/ void setKnownDrawSize(S32 width, S32 height); +	/*virtual*/ void setKnownDrawSize(S32 width, S32 height) override; + +    // Set the debug text of all Viewer Objects associated with this texture +    // to the specified text +    void setDebugText(const std::string& text);  	void setIsMissingAsset(BOOL is_missing = true); -	/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } +	/*virtual*/ BOOL isMissingAsset() const override { return mIsMissingAsset; }  	// returns dimensions of original image for local files (before power of two scaling)  	// and returns 0 for all asset system images @@ -415,7 +405,7 @@ public:  	BOOL        isRawImageValid()const { return mIsRawImageValid ; }	  	void        forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;  	void        forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); -	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; +	/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;  	void        destroySavedRawImage() ;  	LLImageRaw* getSavedRawImage() ;  	BOOL        hasSavedRawImage() const ; @@ -431,10 +421,10 @@ public:  	void        setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }  	bool        isInFastCacheList() { return mInFastCacheList; } -	/*virtual*/bool  isActiveFetching(); //is actively in fetching by the fetching pipeline. +	/*virtual*/bool  isActiveFetching() override; //is actively in fetching by the fetching pipeline.  protected: -	/*virtual*/ void switchToCachedImage(); +	/*virtual*/ void switchToCachedImage() override;  	S32 getCurrentDiscardLevelForFetching() ;  private: @@ -472,11 +462,11 @@ protected:  	S32 mRequestedDiscardLevel;  	F32 mRequestedDownloadPriority;  	S32 mFetchState; +    S32 mLastFetchState = -1; // DEBUG  	U32 mFetchPriority;  	F32 mDownloadProgress;  	F32 mFetchDeltaTime;  	F32 mRequestDeltaTime; -	F32 mDecodePriority;			// The priority for decoding this image.  	S32	mMinDiscardLevel;  	S8  mDesiredDiscardLevel;			// The discard level we'd LIKE to have - if we have it and there's space	  	S8  mMinDesiredDiscardLevel;	// The minimum discard level we'd like to have @@ -500,7 +490,7 @@ protected:  	F32             mLastCallBackActiveTime;  	LLPointer<LLImageRaw> mRawImage; -	S32 mRawDiscardLevel; +	S32 mRawDiscardLevel = -1;  	// Used ONLY for cloth meshes right now.  Make SURE you know what you're   	// doing if you use it for anything else! - djs @@ -534,11 +524,13 @@ protected:  	BOOL   mIsFetched ; //is loaded from remote or from cache, not generated locally.  public: +    static F32 sMaxVirtualSize; //maximum possible value of mMaxVirtualSize  	static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep;	// Texture to show for an image asset that is not in the database  	static LLPointer<LLViewerFetchedTexture> sWhiteImagep;	// Texture to show NOTHING (whiteness)  	static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.  	static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture  	static LLPointer<LLViewerFetchedTexture> sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface +	static LLPointer<LLViewerFetchedTexture> sDefaultIrradiancePBRp; // PBR: irradiance  };  // @@ -774,7 +766,6 @@ private:  		void reset() ; -		F32 mTotalFetchingTime ;  		F32 mTotalGrayTime ;  		F32 mTotalStablizingTime ;  		F32 mStartTimeLoadingSculpties ;  diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index bbbf9ea7a3..9cbbf1c276 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -89,8 +89,6 @@ LLTextureKey::LLTextureKey(LLUUID id, ETexListType tex_type)  LLViewerTextureList::LLViewerTextureList()   	: mForceResetTextureStats(FALSE), -	mMaxResidentTexMemInMegaBytes(0), -	mMaxTotalTextureMemInMegaBytes(0),  	mInitialized(FALSE)  {  } @@ -99,12 +97,6 @@ void LLViewerTextureList::init()  {			  	mInitialized = TRUE ;  	sNumImages = 0; -	mMaxResidentTexMemInMegaBytes = (U32Bytes)0; -	mMaxTotalTextureMemInMegaBytes = (U32Bytes)0; -	 -	// Update how much texture RAM we're allowed to use. -	updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current -	  	doPreloadImages();  } @@ -128,7 +120,10 @@ void LLViewerTextureList::doPreloadImages()  	// Set the default flat normal map  	LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); -	 + +	// PBR: irradiance +	LLViewerFetchedTexture::sDefaultIrradiancePBRp = LLViewerTextureManager::getFetchedTextureFromFile("default_irradiance.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); +  	image_list->initFromFile();  	// turn off clamping and bilinear filtering for uv picking images @@ -204,10 +199,8 @@ static std::string get_texture_list_name()  void LLViewerTextureList::doPrefetchImages()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	gTextureTimer.start(); -	gTextureTimer.pause(); -	if (LLAppViewer::instance()->getPurgeCache()) +    if (LLAppViewer::instance()->getPurgeCache())  	{  		// cache was purged, no point  		return; @@ -342,7 +335,7 @@ void LLViewerTextureList::dump()  	{  		LLViewerFetchedTexture* image = *it; -		LL_INFOS() << "priority " << image->getDecodePriority() +		LL_INFOS() << "priority " << image->getMaxVirtualSize()  		<< " boost " << image->getBoostLevel()  		<< " size " << image->getWidth() << "x" << image->getHeight()  		<< " discard " << image->getDiscardLevel() @@ -667,13 +660,14 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)  	assert_main_thread();  	llassert_always(mInitialized) ;  	llassert(image); +    image->validateRefCount();  	S32 count = 0;  	if (image->isInImageList())  	{  		count = mImageList.erase(image) ;  		if(count != 1)  -	{ +	    {  			LL_INFOS() << "Image  " << image->getID()   				<< " had mInImageList set but mImageList.erase() returned " << count  				<< LL_ENDL; @@ -699,6 +693,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)  			LL_INFOS() << "Image  " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ;  		}  		count = mImageList.erase(image) ; +        llassert(count != 0);  		if(count != 0)   		{	// it was in the list already?  			LL_WARNS() << "Image  " << image->getID()  @@ -784,17 +779,12 @@ void LLViewerTextureList::updateImages(F32 max_time)  		using namespace LLStatViewer;  		sample(NUM_IMAGES, sNumImages);  		sample(NUM_RAW_IMAGES, LLImageRaw::sRawImageCount); -		sample(GL_TEX_MEM, LLImageGL::sGlobalTextureMemory); -		sample(GL_BOUND_MEM, LLImageGL::sBoundTextureMemory); -		sample(RAW_MEM, F64Bytes(LLImageRaw::sGlobalRawMemory));  		sample(FORMATTED_MEM, F64Bytes(LLImageFormatted::sGlobalFormattedMemory));  	}  	//loading from fast cache   	max_time -= updateImagesLoadingFastCache(max_time); -	updateImagesDecodePriorities(); -	      F32 total_max_time = max_time;  	max_time -= updateImagesFetchTextures(max_time); @@ -825,7 +815,6 @@ void LLViewerTextureList::updateImages(F32 max_time)  			didone = image->doLoadedCallbacks();  		}  	} -	  	updateImagesUpdateStats();  } @@ -848,120 +837,78 @@ void LLViewerTextureList::clearFetchingRequests()  	}  } -void LLViewerTextureList::updateImagesDecodePriorities() +void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	// Update the decode priority for N images each frame -	{ -		F32 lazy_flush_timeout = 30.f; // stop decoding -		F32 max_inactive_time  = 20.f; // actually delete -		S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - -		//reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon. -		bool reset_timer = gViewerWindow->getProgressView()->getVisible(); -         -        static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities");         // default: 32 -		const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES); -		S32 update_counter = llmin(max_update_count, mUUIDMap.size()); -		uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey); -		while ((update_counter-- > 0) && !mUUIDMap.empty()) -		{ -			if (iter == mUUIDMap.end()) -			{ -				iter = mUUIDMap.begin(); +    if (imagep->isInDebug() || imagep->isUnremovable()) +    { +        //update_counter--; +        return; //is in debug, ignore. +    } + +    F32 lazy_flush_timeout = 30.f; // stop decoding +    F32 max_inactive_time = 20.f; // actually delete +    S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference + +    // +    // Flush formatted images using a lazy flush +    // +    S32 num_refs = imagep->getNumRefs(); +    if (num_refs == min_refs) +    { +        if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) +        { +            // Remove the unused image from the image list +            deleteImage(imagep); +            imagep = NULL; // should destroy the image								 +        } +        return; +    } +    else +    { +        if (imagep->hasSavedRawImage()) +        { +            if (imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) +            { +                imagep->destroySavedRawImage();              } -            mLastUpdateKey = iter->first; -			LLPointer<LLViewerFetchedTexture> imagep = iter->second; -			++iter; // safe to increment now +        } -			if(imagep->isInDebug() || imagep->isUnremovable()) -			{ -				update_counter--; -				continue; //is in debug, ignore. -			} +        if (imagep->isDeleted()) +        { +            return; +        } +        else if (imagep->isDeletionCandidate()) +        { +            imagep->destroyTexture(); +            return; +        } +        else if (imagep->isInactive()) +        { +            if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) +            { +                imagep->setDeletionCandidate(); +            } +            return; +        } +        else +        { +            imagep->getLastReferencedTimer()->reset(); -			// -			// Flush formatted images using a lazy flush -			// -			S32 num_refs = imagep->getNumRefs(); -			if (num_refs == min_refs) -			{ -				if(reset_timer) -				{ -					imagep->getLastReferencedTimer()->reset(); -				} -				else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) -				{ -					// Remove the unused image from the image list -					deleteImage(imagep); -					imagep = NULL; // should destroy the image								 -				} -				continue; -			} -			else -			{ -				if(imagep->hasSavedRawImage()) -				{ -					if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) -					{ -						imagep->destroySavedRawImage() ; -					} -				} - -				if(imagep->isDeleted()) -				{ -					continue ; -				} -				else if(imagep->isDeletionCandidate()) -				{ -					imagep->destroyTexture() ;																 -					continue ; -				} -				else if(imagep->isInactive()) -				{ -					if(reset_timer) -					{ -						imagep->getLastReferencedTimer()->reset(); -					} -					else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) -					{ -						imagep->setDeletionCandidate() ; -					} -					continue ; -				} -				else -				{ -					imagep->getLastReferencedTimer()->reset(); - -					//reset texture state. -					imagep->setInactive() ;										 -				} -			} +            //reset texture state. +            imagep->setInactive(); +        } +    } -			if (!imagep->isInImageList()) -			{ -				continue; -			} -			if(imagep->isInFastCacheList()) -			{ -				continue; //wait for loading from the fast cache. -			} +    if (!imagep->isInImageList()) +    { +        return; +    } +    if (imagep->isInFastCacheList()) +    { +        return; //wait for loading from the fast cache. +    } -			imagep->processTextureStats(); -			F32 old_priority = imagep->getDecodePriority(); -			F32 old_priority_test = llmax(old_priority, 0.0f); -			F32 decode_priority = imagep->calcDecodePriority(); -			F32 decode_priority_test = llmax(decode_priority, 0.0f); -			// Ignore < 20% difference -			if ((decode_priority_test < old_priority_test * .8f) || -				(decode_priority_test > old_priority_test * 1.25f)) -			{ -				mImageList.erase(imagep) ; -				imagep->setDecodePriority(decode_priority); -				mImageList.insert(imagep); -			} -		} -	} +    imagep->processTextureStats();  }  void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level) @@ -973,17 +920,9 @@ void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debu  	}  	const F32 DEBUG_PRIORITY = 100000.f; -	F32 old_priority_test = llmax(tex->getDecodePriority(), 0.0f); -	F32 decode_priority_test = DEBUG_PRIORITY; -	 -	// Ignore < 20% difference -	if ((decode_priority_test < old_priority_test * .8f) || -		(decode_priority_test > old_priority_test * 1.25f)) -	{ -		removeImageFromList(tex); -		tex->setDecodePriority(decode_priority_test); -		addImageToList(tex); -	} +	removeImageFromList(tex); +    tex->mMaxVirtualSize = DEBUG_PRIORITY; +	addImageToList(tex);  }  /* @@ -1033,10 +972,6 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)  		LLViewerFetchedTexture *imagep = *curiter;  		imagep->createTexture();          imagep->postCreateTexture(); -		if (create_timer.getElapsedTimeF32() > max_time) -		{ -			break; -		}  	}  	mCreateTextureList.erase(mCreateTextureList.begin(), enditer);  	return create_timer.getElapsedTimeF32(); @@ -1064,10 +999,6 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)  		enditer = iter;  		LLViewerFetchedTexture *imagep = *curiter;  		imagep->loadFromFastCache(); -		if (timer.getElapsedTimeF32() > max_time) -		{ -			break; -		}  	}  	mFastCacheList.erase(mFastCacheList.begin(), enditer);  	return timer.getElapsedTimeF32(); @@ -1086,8 +1017,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)  	}  	imagep->processTextureStats(); -	F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority() ; -	imagep->setDecodePriority(decode_priority); +    imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;  	addImageToList(imagep);  	return ; @@ -1096,76 +1026,55 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)  F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	LLTimer image_op_timer; -	 -	// Update fetch for N images each frame -	static const S32 MAX_HIGH_PRIO_COUNT = gSavedSettings.getS32("TextureFetchUpdateHighPriority");         // default: 32 -	static const S32 MAX_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMaxMediumPriority");       // default: 256 -	static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinMediumPriority");       // default: 32 -	static const F32 MIN_PRIORITY_THRESHOLD = gSavedSettings.getF32("TextureFetchUpdatePriorityThreshold"); // default: 0.0 -	static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority");          // default: false - -	size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds.value())+1, MAX_HIGH_PRIO_COUNT); -	max_priority_count = llmin(max_priority_count, mImageList.size()); -	 -	size_t total_update_count = mUUIDMap.size(); -	size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds.value())+1, MAX_UPDATE_COUNT); -	max_update_count = llmin(max_update_count, total_update_count);	 -	 -	// MAX_HIGH_PRIO_COUNT high priority entries -	typedef std::vector<LLViewerFetchedTexture*> entries_list_t; -	entries_list_t entries; -	size_t update_counter = max_priority_count; -	image_priority_list_t::iterator iter1 = mImageList.begin(); -	while(update_counter > 0) -	{ -		entries.push_back(*iter1); -		 -		++iter1; -		update_counter--; -	} -	 -	// MAX_UPDATE_COUNT cycled entries -	update_counter = max_update_count;	 -	if(update_counter > 0) -	{ -		uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchKey); -		while ((update_counter > 0) && (total_update_count > 0)) -		{ -			if (iter2 == mUUIDMap.end()) -			{ -				iter2 = mUUIDMap.begin(); -			} -			LLViewerFetchedTexture* imagep = iter2->second; -            // Skip the textures where there's really nothing to do so to give some times to others. Also skip the texture if it's already in the high prio set. -            if (!SKIP_LOW_PRIO || (SKIP_LOW_PRIO && ((imagep->getDecodePriority() > MIN_PRIORITY_THRESHOLD) || imagep->hasFetcher()))) +    LLTimer image_op_timer; + +    typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t; +    entries_list_t entries; + +    // update N textures at beginning of mImageList +    U32 update_count = 0; +    static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount");       // default: 32 +    // WIP -- dumb code here +    //update MIN_UPDATE_COUNT or 10% of other textures, whichever is greater +    update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/10); +    update_count = llmin(update_count, (U32) mUUIDMap.size()); +     +    { +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vtluift - copy"); + +        // copy entries out of UUID map for updating +        entries.reserve(update_count); +        uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey); +        while (update_count-- > 0) +        { +            if (iter == mUUIDMap.end()) +            { +                iter = mUUIDMap.begin(); +            } +             +            if (iter->second->getGLTexture())              { -                entries.push_back(imagep); -                update_counter--; +                entries.push_back(iter->second);              } +            ++iter; +        } +    } + +    for (auto& imagep : entries) +    { +        if (imagep->getNumRefs() > 1) // make sure this image hasn't been deleted before attempting to update (may happen as a side effect of some other image updating) +        { +            updateImageDecodePriority(imagep); +            imagep->updateFetch(); +        } +    } + +    if (entries.size() > 0) +    { +        LLViewerFetchedTexture* imagep = *entries.rbegin(); +        mLastUpdateKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); +    } -			iter2++; -			total_update_count--; -		} -	} -	 -	S32 fetch_count = 0; -	size_t min_update_count = llmin(MIN_UPDATE_COUNT,(S32)(entries.size()-max_priority_count)); -	S32 min_count = max_priority_count + min_update_count; -	for (entries_list_t::iterator iter3 = entries.begin(); -		 iter3 != entries.end(); ) -	{ -		LLViewerFetchedTexture* imagep = *iter3++; -		fetch_count += (imagep->updateFetch() ? 1 : 0); -		if (min_count <= min_update_count) -		{ -			mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); -		} -		if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time)) -		{ -			break; -		} -	}  	return image_op_timer.getElapsedTimeF32();  } @@ -1209,8 +1118,6 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)  	{  		LLViewerFetchedTexture* imagep = *iter;  		imagep->processTextureStats(); -		F32 decode_priority = imagep->calcDecodePriority(); -		imagep->setDecodePriority(decode_priority);  		addImageToList(imagep);  	}  	image_list.clear(); @@ -1262,7 +1169,8 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)  BOOL LLViewerTextureList::createUploadFile(const std::string& filename,  										 const std::string& out_filename, -										 const U8 codec) +										 const U8 codec, +										 const S32 max_image_dimentions)  {	      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;  	// Load the image @@ -1291,7 +1199,7 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,  		return FALSE;  	}  	// Convert to j2c (JPEG2000) and save the file locally -	LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image);	 +	LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions);  	if (compressedImage.isNull())  	{  		image->setLastError("Couldn't convert the image to jpeg2000."); @@ -1316,10 +1224,10 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,  }  // note: modifies the argument raw_image!!!! -LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image) +LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions)  { -    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); +	LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +	raw_image->biasedScaleToPowerOfTwo(max_image_dimentions);  	LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C();  	if (gSavedSettings.getBOOL("LosslessJ2CUpload") && @@ -1349,156 +1257,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage  	return compressedImage;  } -// Returns min setting for TextureMemory (in MB) -S32Megabytes LLViewerTextureList::getMinVideoRamSetting() -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	U32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); -	//min texture mem sets to 64M if total physical mem is more than 1.5GB -	return (system_ram > U32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ; -} - -//static -// Returns max setting for TextureMemory (in MB) -S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	S32Megabytes max_texmem; -	if (gGLManager.mVRAM != 0) -	{ -		// Treat any card with < 32 MB (shudder) as having 32 MB -		//  - it's going to be swapping constantly regardless -		S32Megabytes max_vram(gGLManager.mVRAM); - -		if(gGLManager.mIsAMD) -		{ -			//shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. -			max_vram = max_vram * 0.75f;  -		} - -		max_vram = llmax(max_vram, getMinVideoRamSetting()); -		max_texmem = max_vram; -		if (!get_recommended) -			max_texmem *= 2; -	} -	else -	{ -		if (!get_recommended) -		{ -			max_texmem = (S32Megabytes)512; -		} -		else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup -		{ -			max_texmem = (S32Megabytes)512; -		} -		else -		{ -			max_texmem = (S32Megabytes)128; -		} -	} - -	S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); // In MB -	//LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; -	if (get_recommended) -		max_texmem = llmin(max_texmem, system_ram/2); -	else -		max_texmem = llmin(max_texmem, system_ram); -		 -    // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise -	max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); - -	max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam);  -	 -	return max_texmem; -} - -bool LLViewerTextureList::isPrioRequestsFetched() -{ -	static LLCachedControl<F32> prio_threshold(gSavedSettings, "TextureFetchUpdatePriorityThreshold", 0.0f); -	static LLCachedControl<F32> fetching_textures_threshold(gSavedSettings, "TextureListFetchingThreshold", 0.97f); -	S32 fetching_tex_count = 0; -	S32 tex_count_threshold = gTextureList.mImageList.size() * (1 - fetching_textures_threshold); - -	for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin(); -		iter != gTextureList.mImageList.end(); ) -	{ -		LLPointer<LLViewerFetchedTexture> imagep = *iter++; -		if (imagep->getDecodePriority() > prio_threshold) -		{ -			if (imagep->hasFetcher() || imagep->isFetching()) -			{ -				fetching_tex_count++; -				if (fetching_tex_count >= tex_count_threshold) -				{ -					return false; -				} -			} -		} -	} - -	return true; -} - -const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12); -const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512); -void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; -	// Initialize the image pipeline VRAM settings -	S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory")); -	F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); -	S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default -	if (mem == (S32Bytes)0) -	{ -		mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem; -	} -	else if (mem < (S32Bytes)0) -	{ -		mem = default_mem; -	} - -	mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); -	if (mem != cur_mem) -	{ -		gSavedSettings.setS32("TextureMemory", mem.value()); -		return; //listener will re-enter this function -	} - -	if (gGLManager.mVRAM == 0) -	{ -		LL_WARNS() << "VRAM amount not detected, defaulting to " << mem << " MB" << LL_ENDL; -	} - -	// TODO: set available resident texture mem based on use by other subsystems -	// currently max(12MB, VRAM/4) assumed... -	 -	S32Megabytes vb_mem = mem; -	S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4); -	mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB -	 -	mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2; -	if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640) -	{ -		mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4); -	} - -	//system mem -	S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); - -	//minimum memory reserved for non-texture use. -	//if system_raw >= 1GB, reserve at least 512MB for non-texture use; -	//otherwise reserve half of the system_ram for non-texture use. -	S32Megabytes min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ;  - -	if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem) -	{ -		mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem ; -	} -	 -	LL_INFOS() << "Total Video Memory set to: " << vb_mem << " MB" << LL_ENDL; -	LL_INFOS() << "Available Texture Memory set to: " << (vb_mem - fb_mem) << " MB" << LL_ENDL; -} -  ///////////////////////////////////////////////////////////////////////////////  // static diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index fead2e52b2..7de3d68e42 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -1,10 +1,10 @@  /**  - * @file llviewertexturelinumimagest.h + * @file llviewertexturelist.h   * @brief Object for managing the list of images within a region   * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2022, 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 @@ -92,8 +92,11 @@ class LLViewerTextureList  	friend class LLLocalBitmap;  public: -	static BOOL createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec); -	static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image); +    static BOOL createUploadFile(const std::string& filename, +                                 const std::string& out_filename, +                                 const U8 codec, +                                 const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); +	static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);  	static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );  	static void receiveImageHeader(LLMessageSystem *msg, void **user_data);  	static void receiveImagePacket(LLMessageSystem *msg, void **user_data); @@ -124,25 +127,20 @@ public:  	void handleIRCallback(void **data, const S32 number); -	S32Megabytes	getMaxResidentTexMem() const	{ return mMaxResidentTexMemInMegaBytes; } -	S32Megabytes getMaxTotalTextureMem() const   { return mMaxTotalTextureMemInMegaBytes;}  	S32 getNumImages()					{ return mImageList.size(); } -	void updateMaxResidentTexMem(S32Megabytes mem); -	  	void doPreloadImages();  	void doPrefetchImages();  	void clearFetchingRequests();  	void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level); -	static S32Megabytes getMinVideoRamSetting(); -	static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); - -	static bool isPrioRequestsFetched(); -	  private: -	void updateImagesDecodePriorities(); +    // do some book keeping on the specified texture +    // - updates decode priority +    // - updates desired discard level +    // - cleans up textures that haven't been referenced in awhile +    void updateImageDecodePriority(LLViewerFetchedTexture* imagep);  	F32  updateImagesCreateTextures(F32 max_time);  	F32  updateImagesFetchTextures(F32 max_time);  	void updateImagesUpdateStats(); @@ -215,17 +213,14 @@ private:      typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;      uuid_map_t mUUIDMap;      LLTextureKey mLastUpdateKey; -    LLTextureKey mLastFetchKey; -	typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t;	 +    typedef std::set < LLPointer<LLViewerFetchedTexture> > image_priority_list_t;  	image_priority_list_t mImageList;  	// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon  	std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;  	BOOL mInitialized ; -	S32Megabytes	mMaxResidentTexMemInMegaBytes; -	S32Megabytes mMaxTotalTextureMemInMegaBytes;  	LLFrameTimer mForceDecodeTimer;  private: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0a44664f17..e9815a7872 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -103,7 +103,6 @@  #include "llfilepicker.h"  #include "llfirstuse.h"  #include "llfloater.h" -#include "llfloaterbuildoptions.h"  #include "llfloaterbuyland.h"  #include "llfloatercamera.h"  #include "llfloaterland.h" @@ -494,24 +493,12 @@ public:  		if (gSavedSettings.getBOOL("DebugShowTime"))  		{ -			{ -			const U32 y_inc2 = 15; -				LLFrameTimer& timer = gTextureTimer; -				F32 time = timer.getElapsedTimeF32(); -				S32 hours = (S32)(time / (60*60)); -				S32 mins = (S32)((time - hours*(60*60)) / 60); -				S32 secs = (S32)((time - hours*(60*60) - mins*60)); -				addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2; -			} -			 -			{  			F32 time = gFrameTimeSeconds;  			S32 hours = (S32)(time / (60*60));  			S32 mins = (S32)((time - hours*(60*60)) / 60);  			S32 secs = (S32)((time - hours*(60*60) - mins*60));  			addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;  		} -		}  		if (gSavedSettings.getBOOL("DebugShowMemory"))  		{ @@ -1913,7 +1900,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)  		gSavedSettings.getBOOL("RenderVSyncEnable"),  		!gHeadlessClient,  		p.ignore_pixel_depth, -		gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled +		0); //don't use window level anti-aliasing  	if (NULL == mWindow)  	{ @@ -4668,8 +4655,8 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picke  		else  			pick_type = LLFilePicker::FFSAVE_ALL; -		(new LLFilePickerReplyThread(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, -										boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)))->getFile(); +		LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, +										boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb));  	}  	else  	{ @@ -5641,7 +5628,6 @@ void LLViewerWindow::stopGL(BOOL save_state)  		// Pause texture decode threads (will get unpaused during main loop)  		LLAppViewer::getTextureCache()->pause(); -		LLAppViewer::getImageDecodeThread()->pause();  		LLAppViewer::getTextureFetch()->pause();  		gSky.destroyGL(); @@ -5688,8 +5674,6 @@ void LLViewerWindow::stopGL(BOOL save_state)  			LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin());  			shader->unload();  		} -		 -		LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory.value() << " bytes" << LL_ENDL;  	}  } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4ec5c999ac..30e3d77d29 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4621,7 +4621,12 @@ bool LLVOAvatar::updateCharacter(LLAgent &agent)  	}  	else if (!getParent() && isSitting() && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED))  	{ -		getOffObject(); +        // If we are starting up, motion might be loading +        LLMotion *motionp = mMotionController.findMotion(ANIM_AGENT_SIT_GROUND_CONSTRAINED); +        if (!motionp || !mMotionController.isMotionLoading(motionp)) +        { +            getOffObject(); +        }  	}  	//-------------------------------------------------------------------- @@ -5702,7 +5707,6 @@ void LLVOAvatar::checkTextureLoading()  }  const F32  SELF_ADDITIONAL_PRI = 0.75f ; -const F32  ADDITIONAL_PRI = 0.5f;  void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)  {  	//Note: @@ -5717,15 +5721,6 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel  	mMinPixelArea = llmin(pixel_area, mMinPixelArea);	  	imagep->addTextureStats(pixel_area / texel_area_ratio);  	imagep->setBoostLevel(boost_level); -	 -	if(boost_level != LLGLTexture::BOOST_AVATAR_BAKED_SELF) -	{ -		imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ; -	} -	else -	{ -		imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; -	}  }  //virtual	 diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 60a69a4ac4..4080a61fb0 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1825,7 +1825,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const  			}  			else  			{ -				const LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); +				LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() );  				LL_INFOS() << "LocTex " << name << ": "  						<< "Discard " << image->getDiscardLevel() << ", " @@ -1835,7 +1835,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const  					// makes textures easier to steal  						<< image->getID() << " "  #endif -						<< "Priority: " << image->getDecodePriority() +						<< "Priority: " << image->getMaxVirtualSize()  						<< LL_ENDL;  			}  		} @@ -2074,8 +2074,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV  									   << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index)  									   << " discard: " << image->getDiscardLevel()  									   << " desired: " << image->getDesiredDiscardLevel() -									   << " decode: " << image->getDecodePriority() -									   << " addl: " << image->getAdditionalDecodePriority() +									   << " vsize: " << image->getMaxVirtualSize()  									   << " ts: " << image->getTextureState()  									   << " bl: " << image->getBoostLevel()  									   << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. @@ -2453,7 +2452,6 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe  				desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());  				imagep->setBoostLevel(getAvatarBoostLevel()); -				imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;  				imagep->resetTextureStats();  				imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);  				imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -2823,7 +2821,6 @@ void LLVOAvatarSelf::deleteScratchTextures()  		LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << LL_ENDL;  		delete_and_clear(sScratchTexNames); -		LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;  		sScratchTexBytes = S32Bytes(0);  	}  } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4fa9f05c09..ad11fb3908 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -232,6 +232,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re  	mMediaImplList.resize(getNumTEs());  	mLastFetchedMediaVersion = -1; +    mServerDrawableUpdateCount = 0;  	memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS);  	mMDCImplCount = 0;  	mLastRiggingInfoLOD = -1; @@ -327,6 +328,9 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  	LLColor4U color;  	const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); +    const bool previously_volume_changed = mVolumeChanged; +    const bool previously_face_mapping_changed = mFaceMappingChanged; +    const bool previously_color_changed = mColorChanged;  	// Do base class updates...  	U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); @@ -550,9 +554,31 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  	// ...and clean up any media impls  	cleanUpMediaImpls(); +    if (( +            (mVolumeChanged && !previously_volume_changed) || +            (mFaceMappingChanged && !previously_face_mapping_changed) || +            (mColorChanged && !previously_color_changed) +        ) +        && !mLODChanged) { +        onDrawableUpdateFromServer(); +    } +  	return retval;  } +// Called when a volume, material, etc is updated by the server, possibly by a +// script. If this occurs too often for this object, mark it as active so that +// it doesn't disrupt the octree/render batches, thereby potentially causing a +// big performance penalty. +void LLVOVolume::onDrawableUpdateFromServer() +{ +    constexpr U32 UPDATES_UNTIL_ACTIVE = 8; +    ++mServerDrawableUpdateCount; +    if (mDrawable && !mDrawable->isActive() && mServerDrawableUpdateCount > UPDATES_UNTIL_ACTIVE) +    { +        mDrawable->makeActive(); +    } +}  void LLVOVolume::animateTextures()  { @@ -670,12 +696,13 @@ void LLVOVolume::animateTextures()  void LLVOVolume::updateTextures()  { -	const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds -	if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) +    LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +	//const F32 TEXTURE_AREA_REFRESH_TIME = 1.f; // seconds +	//if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)  	{  		updateTextureVirtualSize(); -		if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) +		/*if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive())  		{ //delete vertex buffer to free up some VRAM  			LLSpatialGroup* group  = mDrawable->getSpatialGroup();  			if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) @@ -686,9 +713,7 @@ void LLVOVolume::updateTextures()  				//it becomes visible  				group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);  			} -		} - - +		}*/      }  } @@ -762,6 +787,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  	const S32 num_faces = mDrawable->getNumFaces();  	F32 min_vsize=999999999.f, max_vsize=0.f;  	LLViewerCamera* camera = LLViewerCamera::getInstance(); +    std::stringstream debug_text;  	for (S32 i = 0; i < num_faces; i++)  	{  		LLFace* face = mDrawable->getFace(i); @@ -788,10 +814,14 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  		else  		{  			vsize = face->getTextureVirtualSize(); +            imagep->addTextureStats(vsize);  		} -		mPixelArea = llmax(mPixelArea, face->getPixelArea());		 +		mPixelArea = llmax(mPixelArea, face->getPixelArea()); +        // if the face has gotten small enough to turn off texture animation and texture +        // animation is running, rebuild the render batch for this face to turn off +        // texture animation  		if (face->mTextureMatrix != NULL)  		{  			if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || @@ -811,10 +841,11 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  			LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;  			if(img)  			{ -				F32 pri = img->getDecodePriority(); +                debug_text << img->getDiscardLevel() << ":" << img->getDesiredDiscardLevel() << ":" << img->getWidth() << ":" << (S32) sqrtf(vsize) << ":" << (S32) sqrtf(img->getMaxVirtualSize()) << "\n"; +				/*F32 pri = img->getDecodePriority();  				pri = llmax(pri, 0.0f);  				if (pri < min_vsize) min_vsize = pri; -				if (pri > max_vsize) max_vsize = pri; +				if (pri > max_vsize) max_vsize = pri;*/  			}  		}  		else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) @@ -846,14 +877,6 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  				F32 lodf = ((F32)(lod + 1.0f)/4.f);  				F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;  				mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); -			 -				//if the sculpty very close to the view point, load first -				{				 -					LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); -					F32 dist = lookAt.normVec() ; -					F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ;				 -					mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; -				}  			}  			S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture @@ -897,7 +920,8 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  	}   	else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))   	{ - 		setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + 		//setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); +        setDebugText(debug_text.str());   	}  	else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))  	{ @@ -1677,7 +1701,7 @@ void LLVOVolume::regenFaces()  	}  } -BOOL LLVOVolume::genBBoxes(BOOL force_global) +BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds)  {      LL_PROFILE_ZONE_SCOPED;      BOOL res = TRUE; @@ -1753,20 +1777,9 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)          }      } -    bool rigged = false; - -    if (!isAnimatedObject()) -    { -        rigged = isRiggedMesh() && isAttachment(); -    } -    else -    { -        rigged = isRiggedMesh() && getControlAvatar() && getControlAvatar()->mPlaying; -    } -      if (any_valid_boxes)      { -        if (rebuild) +        if (rebuild && should_update_octree_bounds)          {              //get the Avatar associated with this object if it's rigged              LLVOAvatar* avatar = nullptr; @@ -1928,7 +1941,7 @@ void LLVOVolume::updateRelativeXform(bool force_identity)  	}  } -bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &should_update_octree_bounds)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;  	bool regen_faces = false; @@ -1960,6 +1973,9 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled)          }  		compiled = TRUE; +        // new_lod > old_lod breaks a feedback loop between LOD updates and +        // bounding box updates. +        should_update_octree_bounds = should_update_octree_bounds || mSculptChanged || new_lod > old_lod;  		sNumLODChanges += new_num_faces;  		if ((S32)getNumTEs() != getVolume()->getNumFaces()) @@ -2019,8 +2035,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  		group->dirtyMesh();  	} -	BOOL compiled = FALSE; -			  	updateRelativeXform();  	if (mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -2028,49 +2042,55 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  		return TRUE; // No update to complete  	} +	BOOL compiled = FALSE; +    // This should be true in most cases, unless we're sure no octree update is +    // needed. +    BOOL should_update_octree_bounds = bool(getRiggedVolume()) || mDrawable->isState(LLDrawable::REBUILD_POSITION) || !mDrawable->getSpatialExtents()->isFinite3(); +  	if (mVolumeChanged || mFaceMappingChanged)  	{  		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));  		bool was_regen_faces = false; +        should_update_octree_bounds = true;  		if (mVolumeChanged)  		{ -			was_regen_faces = lodOrSculptChanged(drawable, compiled); +            was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds);  			drawable->setState(LLDrawable::REBUILD_VOLUME);  		}  		else if (mSculptChanged || mLODChanged || mColorChanged)  		{  			compiled = TRUE; -			was_regen_faces = lodOrSculptChanged(drawable, compiled); +            was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds);  		}  		if (!was_regen_faces) {  			regenFaces();  		} - -		genBBoxes(FALSE);  	}  	else if (mLODChanged || mSculptChanged || mColorChanged)  	{  		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));  		compiled = TRUE; -		lodOrSculptChanged(drawable, compiled); +        lodOrSculptChanged(drawable, compiled, should_update_octree_bounds);  		if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED))   		{  			updateRiggedVolume(false);  		} -		genBBoxes(FALSE);  	}  	// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local  	else  	{  		compiled = TRUE;  		// All it did was move or we changed the texture coordinate offset -		genBBoxes(FALSE);  	} +    // Generate bounding boxes if needed, and update the object's size in the +    // octree +    genBBoxes(FALSE, should_update_octree_bounds); +  	// Update face flags  	updateFaceFlags(); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index db586fd741..391351c13e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -236,7 +236,7 @@ public:  				void	updateFaceFlags();  				void	regenFaces(); -				BOOL	genBBoxes(BOOL force_global); +                BOOL    genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = TRUE);  				void	preRebuild();  	virtual		void	updateSpatialExtents(LLVector4a& min, LLVector4a& max) override;  	virtual		F32		getBinRadius() override; @@ -403,13 +403,14 @@ protected:  	static S32 mRenderComplexity_last;  	static S32 mRenderComplexity_current; +    void onDrawableUpdateFromServer();  	void requestMediaDataUpdate(bool isNew);  	void cleanUpMediaImpls();  	void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;  	void removeMediaImpl(S32 texture_index) ;  private: -	bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); +    bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &shouldUpdateOctreeBounds);  public: @@ -441,6 +442,7 @@ private:  	LLPointer<LLViewerFetchedTexture> mLightTexture;  	media_list_t mMediaImplList;  	S32			mLastFetchedMediaVersion; // as fetched from the server, starts as -1 +    U32         mServerDrawableUpdateCount;  	S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];  	S32 mMDCImplCount; diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index ff899fe895..3cc82621c4 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -36,7 +36,7 @@  #include "llstring.h"  // newview -#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions +#include "llavataractions.h" // for getProfileURL()  #include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals  #include "llcorehttputil.h" diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 32c8ce66a0..2b400c5586 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -395,7 +395,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const  	mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this )); -	mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,  +	mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID,  		mURI, body.get(), httpOpts, httpHeaders, mHandler);  } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b23c1fe741..67f0ea68c1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -442,6 +442,7 @@ void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name)  void LLPipeline::init()  { +    LL_WARNS() << "Begin pipeline initialization" << LL_ENDL; // TODO: Remove after testing  	refreshCachedSettings();      mRT = &mMainRT; @@ -449,7 +450,7 @@ void LLPipeline::init()  	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");  	gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");  	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); -	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); +    sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump");  	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");  	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");  	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO"); @@ -460,6 +461,7 @@ void LLPipeline::init()  	mInitialized = true;  	stop_glerror(); +    LL_WARNS() << "No GL errors yet. Pipeline initialization will continue." << LL_ENDL; // TODO: Remove after testing  	//create render pass pools  	getPool(LLDrawPool::POOL_ALPHA); @@ -521,7 +523,9 @@ void LLPipeline::init()  	// Enable features +    LL_WARNS() << "Shader initialization start" << LL_ENDL; // TODO: Remove after testing  	LLViewerShaderMgr::instance()->setShaders(); +    LL_WARNS() << "Shader initialization end" << LL_ENDL; // TODO: Remove after testing  	stop_glerror(); @@ -548,8 +552,8 @@ void LLPipeline::init()  	connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors");  	connectRefreshCachedSettingsSafe("RenderDelayVBUpdate");  	connectRefreshCachedSettingsSafe("UseOcclusion"); -	connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); -	connectRefreshCachedSettingsSafe("RenderDeferred"); +	// DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); +	// DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred");      connectRefreshCachedSettingsSafe("RenderPBR");  	connectRefreshCachedSettingsSafe("RenderDeferredSunWash");  	connectRefreshCachedSettingsSafe("RenderFSAASamples"); @@ -1033,7 +1037,7 @@ void LLPipeline::updateRenderTransparentWater()  //static  void LLPipeline::updateRenderBump()  { -	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); +    sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump");  }  // static @@ -1043,8 +1047,7 @@ void LLPipeline::updateRenderDeferred()                        RenderDeferred &&                        LLRenderTarget::sUseFBO &&                        LLPipeline::sRenderBump && -                      WindLightUseAtmosShaders && -                      (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); +                      WindLightUseAtmosShaders;      sRenderPBR = sRenderDeferred && gSavedSettings.getBOOL("RenderPBR");  } @@ -1065,8 +1068,8 @@ void LLPipeline::refreshCachedSettings()  			&& gSavedSettings.getBOOL("UseOcclusion")   			&& gGLManager.mHasOcclusionQuery) ? 2 : 0; -	WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); -	RenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); +    WindLightUseAtmosShaders = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders"); +    RenderDeferred = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred");  	RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");  	RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");  	RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); @@ -3746,7 +3749,7 @@ void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize)      if (tex)      {          LLImageGL* gl_tex = tex->getGLTexture(); -        if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory)) +        if (gl_tex && gl_tex->updateBindStats())          {              tex->setActive();              tex->addTextureStats(vsize); @@ -3766,6 +3769,7 @@ void LLPipeline::touchTextures(LLDrawInfo* info)      touchTexture(info->mTexture, info->mVSize);      touchTexture(info->mSpecularMap, info->mVSize);      touchTexture(info->mNormalMap, info->mVSize); +    touchTexture(info->mEmissiveMap, info->mVSize);  }  void LLPipeline::postSort(LLCamera& camera) @@ -3815,25 +3819,47 @@ void LLPipeline::postSort(LLCamera& camera)  			group->rebuildGeom();  		} -		for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) -		{ -			LLSpatialGroup::drawmap_elem_t& src_vec = j->second;	 -			if (!hasRenderType(j->first)) -			{ -				continue; -			} -			 -			for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) -			{ +        for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) +        { +            LLSpatialGroup::drawmap_elem_t& src_vec = j->second; +            if (!hasRenderType(j->first)) +            { +                continue; +            } + +            // DEBUG -- force a texture virtual size update every frame +            /*if (group->getSpatialPartition()->mDrawableType == LLPipeline::RENDER_TYPE_VOLUME) +            { +                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("plps - update vsize"); +                auto& entries = group->getData(); +                for (auto& entry : entries) +                { +                    if (entry) +                    { +                        auto* data = entry->getDrawable(); +                        if (data) +                        { +                            LLVOVolume* volume = ((LLDrawable*)data)->getVOVolume(); +                            if (volume) +                            { +                                volume->updateTextureVirtualSize(true); +                            } +                        } +                    } +                } +            }*/ + +            for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) +            {                  LLDrawInfo* info = *k; -				 -				sCull->pushDrawInfo(j->first, info); + +                sCull->pushDrawInfo(j->first, info);                  if (!sShadowRender && !sReflectionRender && !gCubeSnapshot)                  {                      touchTextures(info);                      addTrianglesDrawn(info->mCount, info->mDrawMode);                  } -			} +            }  		}  		if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA)) @@ -3976,7 +4002,7 @@ void LLPipeline::postSort(LLCamera& camera)  	}  	LL_PUSH_CALLSTACKS();  	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint. -	if (LLFloaterTelehub::renderBeacons()) +	if (LLFloaterTelehub::renderBeacons() && !sShadowRender)  	{  		LLFloaterTelehub::addBeacons();  	} @@ -8617,6 +8643,11 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)              soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);              soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV); +            if (!LLPipeline::sUnderWaterRender && LLPipeline::sRenderPBR) +            { +                soften_shader.bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, LLViewerFetchedTexture::sDefaultIrradiancePBRp); // PBR: irradiance +            } +              if(LLPipeline::sRenderPBR)              {                  LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis(); @@ -10264,7 +10295,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)                      LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED,                      LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED,                      LLPipeline::RENDER_TYPE_PASS_PBR_OPAQUE, -                    //LLRenderPass::PASS_PBR_OPAQUE_RIGGED, +                    LLPipeline::RENDER_TYPE_PASS_PBR_OPAQUE_RIGGED,  					END_RENDER_TYPES);  	gGL.setColorMask(false, false); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 7beb013fba..1085972d9e 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -886,6 +886,22 @@        name="PanelNotificationListItem"        value="0.3 0.3 0.3 .3" /> +	<!-- profiles --> +    <color +        name="StatusUserOnline" +        reference="White" /> +    <color +        name="StatusUserOffline" +        reference="LtGray_35" /> +    <!-- Groups visible in own profiles --> +    <color +        name="GroupVisibleInProfile" +        reference="TextBgFocusColor" /> +    <color +        name="GroupHiddenInProfile" +        reference="Gray" /> +     +    <!-- Generic color names (legacy) -->    <color      name="white" diff --git a/indra/newview/skins/default/textures/default_irradiance.png b/indra/newview/skins/default/textures/default_irradiance.png Binary files differnew file mode 100644 index 0000000000..899e0ddf2a --- /dev/null +++ b/indra/newview/skins/default/textures/default_irradiance.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png Binary files differnew file mode 100644 index 0000000000..9a81c5f94b --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png Binary files differnew file mode 100644 index 0000000000..88012cf8d1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Off.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png Binary files differnew file mode 100644 index 0000000000..ab02e7d42d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardMenu_Press.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png Binary files differnew file mode 100644 index 0000000000..63b4bd2127 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png Binary files differnew file mode 100644 index 0000000000..4200182b0c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Off.png diff --git a/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png Binary files differnew file mode 100644 index 0000000000..e12887f489 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ClipboardSmallMenu_Press.png diff --git a/indra/newview/skins/default/textures/icons/CopyBright.png b/indra/newview/skins/default/textures/icons/CopyBright.png Binary files differnew file mode 100644 index 0000000000..8d21c47295 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/CopyBright.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png b/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png Binary files differnew file mode 100644 index 0000000000..aeba6b70f7 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Friend_Offline.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png b/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png Binary files differnew file mode 100644 index 0000000000..d668fd8dfa --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Friend_Online.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png Binary files differnew file mode 100644 index 0000000000..8f8caa10d8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png Binary files differnew file mode 100644 index 0000000000..42a209dda5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Find_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png Binary files differnew file mode 100644 index 0000000000..644edf0ef6 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png Binary files differnew file mode 100644 index 0000000000..629c05ecb8 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Objects_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png Binary files differnew file mode 100644 index 0000000000..ecf66c0ee1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png Binary files differnew file mode 100644 index 0000000000..26123938fa --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Profile_Perm_Online_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png Binary files differnew file mode 100644 index 0000000000..3a2ed399b2 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png Binary files differnew file mode 100644 index 0000000000..789f59a491 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_off_pressed.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png Binary files differnew file mode 100644 index 0000000000..4fb56c389c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on.png diff --git a/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png Binary files differnew file mode 100644 index 0000000000..ae04a256a4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_group_visibility_eye_on_pressed.png diff --git a/indra/newview/skins/default/textures/map_ui_collapse_icon.png b/indra/newview/skins/default/textures/map_ui_collapse_icon.png Binary files differnew file mode 100644 index 0000000000..e4de49d4af --- /dev/null +++ b/indra/newview/skins/default/textures/map_ui_collapse_icon.png diff --git a/indra/newview/skins/default/textures/map_ui_expand_icon.png b/indra/newview/skins/default/textures/map_ui_expand_icon.png Binary files differnew file mode 100644 index 0000000000..08734b4cc0 --- /dev/null +++ b/indra/newview/skins/default/textures/map_ui_expand_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 84ca634600..65faea48a0 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -191,6 +191,7 @@ with the same filename but different name    <texture name="Conv_log_inbox" file_name="icons/Conv_log_inbox.png" preload="false" />    <texture name="Copy" file_name="icons/Copy.png" preload="false" /> +  <texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" />    <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> @@ -448,6 +449,13 @@ with the same filename but different name    <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />    <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" /> +  <texture name="ClipboardSmallMenu_Disabled" file_name="icons/ClipboardSmallMenu_Disabled.png" preload="false" /> +  <texture name="ClipboardSmallMenu_Off" file_name="icons/ClipboardSmallMenu_Off.png" preload="false" /> +  <texture name="ClipboardSmallMenu_Press" file_name="icons/ClipboardSmallMenu_Press.png" preload="false" /> +  <texture name="ClipboardMenu_Disabled" file_name="icons/ClipboardMenu_Disabled.png" preload="false" /> +  <texture name="ClipboardMenu_Off" file_name="icons/ClipboardMenu_Off.png" preload="false" /> +  <texture name="ClipboardMenu_Press" file_name="icons/ClipboardMenu_Press.png" preload="false" /> +    <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" />    <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" />    <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" /> @@ -506,6 +514,19 @@ with the same filename but different name    <texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" />    <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" /> +  <texture name="Profile_Group_Visibility_Off" file_name="icons/profile_group_visibility_eye_off.png" preload="true"/> +  <texture name="Profile_Group_Visibility_Off_Pressed" file_name="icons/profile_group_visibility_eye_off_pressed.png" preload="true"/> +  <texture name="Profile_Group_Visibility_On" file_name="icons/profile_group_visibility_eye_on.png" preload="true"/> +  <texture name="Profile_Group_Visibility_On_Pressed" file_name="icons/profile_group_visibility_eye_on_pressed.png" preload="true"/> +  <texture name="Profile_Friend_Offline" file_name="icons/Profile_Friend_Offline.png" preload="true"/> +  <texture name="Profile_Friend_Online" file_name="icons/Profile_Friend_Online.png" preload="true"/> +  <texture name="Profile_Perm_Find_Disabled" file_name="icons/Profile_Perm_Find_Disabled.png" preload="true"/> +  <texture name="Profile_Perm_Find_Enabled" file_name="icons/Profile_Perm_Find_Enabled.png" preload="true"/> +  <texture name="Profile_Perm_Objects_Disabled" file_name="icons/Profile_Perm_Objects_Disabled.png" preload="true"/> +  <texture name="Profile_Perm_Objects_Enabled" file_name="icons/Profile_Perm_Objects_Enabled.png" preload="true"/> +  <texture name="Profile_Perm_Online_Disabled" file_name="icons/Profile_Perm_Online_Disabled.png" preload="true"/> +  <texture name="Profile_Perm_Online_Enabled" file_name="icons/Profile_Perm_Online_Enabled.png" preload="true"/> +      <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />    <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />    <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" /> @@ -804,6 +825,8 @@ with the same filename but different name    <texture name="map_infohub.tga" />    <texture name="map_telehub.tga" />    <texture name="map_track_16.tga" /> +  <texture name="map_ui_collapse_icon.png" /> +  <texture name="map_ui_expand_icon.png" />    <texture name="notify_caution_icon.tga" /> diff --git a/indra/newview/skins/default/xui/da/panel_me.xml b/indra/newview/skins/default/xui/da/panel_me.xml deleted file mode 100644 index f98ced5f91..0000000000 --- a/indra/newview/skins/default/xui/da/panel_me.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Min profil" name="panel_me"> -	<tab_container name="tabs"> -		<panel label="MIN PROFIL" name="panel_profile"/> -		<panel label="MINE FAVORITTER" name="panel_picks"/> -	</tab_container> -</panel> diff --git a/indra/newview/skins/default/xui/da/panel_side_tray.xml b/indra/newview/skins/default/xui/da/panel_side_tray.xml deleted file mode 100644 index 66c3e69904..0000000000 --- a/indra/newview/skins/default/xui/da/panel_side_tray.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<!-- Side tray cannot show background because it is always -	partially on screen to hold tab buttons. --> -<side_tray name="sidebar"> -	<sidetray_tab description="Åbn/luk sidebar" name="sidebar_openclose" tab_title="Åbn/luk sidebar"/> -	<sidetray_tab description="Hjem." name="sidebar_home" tab_title="Hjem"> -		<panel label="hjem" name="panel_home"/> -	</sidetray_tab> -	<sidetray_tab description="Redigér din profile og favoritter." name="sidebar_me" tab_title="Min profil"> -		<panel_container name="panel_container"> -			<panel label="Mig" name="panel_me"/> -		</panel_container> -	</sidetray_tab> -	<sidetray_tab description="Find venner, kontakter og personer tæt på." name="sidebar_people" tab_title="Personer"> -		<panel_container name="panel_container"> -			<panel label="Gruppe profil" name="panel_group_info_sidetray"/> -			<panel label="Blokerede beboere og objekter" name="panel_block_list_sidetray"/> -		</panel_container> -	</sidetray_tab> -	<sidetray_tab description="Find steder du vil hen og steder du har været før." label="Steder" name="sidebar_places" tab_title="Steder"> -		<panel label="Steder" name="panel_places"/> -	</sidetray_tab> -	<sidetray_tab description="Browse din beholdning." name="sidebar_inventory" tab_title="Min beholdning"> -		<panel label="Redigér beholdning" name="sidepanel_inventory"/> -	</sidetray_tab> -	<sidetray_tab description="Ændre dit nuværende udseende" name="sidebar_appearance" tab_title="Mit udseende"> -		<panel label="Redigér udseende" name="sidepanel_appearance"/> -	</sidetray_tab> -</side_tray> diff --git a/indra/newview/skins/default/xui/de/floater_preview_texture.xml b/indra/newview/skins/default/xui/de/floater_preview_texture.xml index eacd11c3e6..b386d0288c 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		In Inventar kopieren  	</floater.string> -	<text name="desc txt"> -		Beschreibung: -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		Vorschau Seitenverhältnis -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Mit einem vordefinierten Seitenverhältnis anzeigen"> -		<combo_item name="Unconstrained"> -			keines -		</combo_item> -		<combo_item name="1:1" tool_tip="Gruppeninsignien oder Beschreibung"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="[SECOND_LIFE]-Profil"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Anzeigen und Suchergebnisse, Landmarken"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="Über Land"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Profilauswahl"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Verwerfen" name="Discard"/> -	<button label="Speichern unter" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Beschreibung: +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				Vorschau Seitenverhältnis +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Mit einem vordefinierten Seitenverhältnis anzeigen"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Verwerfen" name="Discard"/> +			<button label="Speichern unter" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/de/floater_profile.xml b/indra/newview/skins/default/xui/de/floater_profile.xml new file mode 100644 index 0000000000..eb03463930 --- /dev/null +++ b/indra/newview/skins/default/xui/de/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="Interessen" name="panel_profile_interests"/> +			<panel label="Auswahlen" name="panel_profile_picks"/> +			<panel label="Anzeige" name="panel_profile_classifieds"/> +			<panel label="Echtes Leben" name="panel_profile_firstlife"/> +			<panel label="Hinweise" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Profiländerungen speichern und schließen"/> +		<button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml index f0152ad8cd..636f320a95 100644 --- a/indra/newview/skins/default/xui/de/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		E-Mail senden  	</string> +	<string name="facebook_progress_str"> +		Auf Facebook posten +	</string>  	<string name="profile_progress_str">  		Posten  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Speichern auf Computer  	</string> +	<string name="facebook_succeeded_str"> +		Bild hochgeladen +	</string>  	<string name="profile_succeeded_str">  		Bild hochgeladen  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Auf Computer gespeichert!  	</string> +	<string name="facebook_failed_str"> +		Fehler beim Hochladen des Bilds in Ihre Facebook-Chronik. +	</string>  	<string name="profile_failed_str">  		Fehler beim Hochladen des Bilds in Ihr Profil.  	</string> diff --git a/indra/newview/skins/default/xui/de/menu_name_field.xml b/indra/newview/skins/default/xui/de/menu_name_field.xml new file mode 100644 index 0000000000..1d293c9361 --- /dev/null +++ b/indra/newview/skins/default/xui/de/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Anzeigenamen kopieren" name="copy_display"/> +	<menu_item_call label="Agent-Namen kopieren" name="copy_name"/> +	<menu_item_call label="Agent-ID kopieren" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 359a835630..a72784f70b 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2698,6 +2698,9 @@ Wählen Sie eine kleinere Landfläche.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/de/panel_edit_classified.xml b/indra/newview/skins/default/xui/de/panel_edit_classified.xml index bd270697ea..8adacb4a5f 100644 --- a/indra/newview/skins/default/xui/de/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/de/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="Abbrechen" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_friends.xml b/indra/newview/skins/default/xui/de/panel_facebook_friends.xml index f6a8fda23e..1a0bbc7d30 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_friends.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_friends"> -	<string name="facebook_friends_empty" value="Sie haben gegenwärtig keine Facebook-Freunde, die gleichzeitig Einwohner von Second Life sind. Laden Sie Ihre Facebook-Freunde ein, Second Life beizutreten!"/> -	<string name="facebook_friends_no_connected" value="Sie sind gegenwärtig nicht mit Facebook verbunden. Um eine Verbindung herzustellen und diese Funktion zu aktivieren, gehen Sie zur Registerkarte „Status“."/> +	<string name="facebook_friends_empty" value="Sie haben gegenwärtig keine Facebook-Freunde, die ebenfalls Second Life-Einwohner sind. Laden Sie Ihre Facebook-Freunde ein, Second Life beizutreten!"/> +	<string name="facebook_friends_no_connected" value="Sie sind gegenwärtig nicht mit Facebook verbunden. Um eine Verbindung herzustellen und diese Funktion zu aktivieren, wechseln Sie zur Registerkarte "Status"."/>  	<accordion name="friends_accordion">  		<accordion_tab name="tab_second_life_friends" title="SL-Freunde"/>  		<accordion_tab name="tab_suggested_friends" title="Diese Personen als SL-Freunde hinzufügen"/> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_photo.xml b/indra/newview/skins/default/xui/de/panel_facebook_photo.xml index bc48931129..fac9fe9984 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_photo.xml @@ -2,10 +2,10 @@  <panel name="panel_facebook_photo">  	<combo_box name="resolution_combobox" tool_tip="Bildauflösung">  		<combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/> -		<combo_box.item label="640x480" name="640x480"/> -		<combo_box.item label="800x600" name="800x600"/> -		<combo_box.item label="1024x768" name="1024x768"/> -		<combo_box.item label="1200x630" name="1200x630"/> +		<combo_box.item label="640 x 480" name="640x480"/> +		<combo_box.item label="800 x 600" name="800x600"/> +		<combo_box.item label="1024 x 768" name="1024x768"/> +		<combo_box.item label="1200 x 630" name="1200x630"/>  	</combo_box>  	<combo_box name="filters_combobox" tool_tip="Bildfilter">  		<combo_box.item label="Kein Filter" name="NoFilter"/> diff --git a/indra/newview/skins/default/xui/de/panel_facebook_status.xml b/indra/newview/skins/default/xui/de/panel_facebook_status.xml index 23c9d3b75f..1fefef548e 100644 --- a/indra/newview/skins/default/xui/de/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/de/panel_facebook_status.xml @@ -13,7 +13,7 @@  		</text>  	</panel>  	<text name="status_caption_label"> -		Was machst du gerade? +		Was machen Sie gerade?  	</text>  	<button label="Posten" name="post_status_btn"/>  	<button label="Abbrechen" name="cancel_status_btn"/> diff --git a/indra/newview/skins/default/xui/de/panel_group_general.xml b/indra/newview/skins/default/xui/de/panel_group_general.xml index 9fec5a242d..e50124c37e 100644 --- a/indra/newview/skins/default/xui/de/panel_group_general.xml +++ b/indra/newview/skins/default/xui/de/panel_group_general.xml @@ -46,7 +46,7 @@ Bewegen Sie die Maus über die Optionen, um weitere Informationen anzuzeigen.  		<check_box label="Jeder kann beitreten" name="open_enrollement" tool_tip="Festlegen, ob der Gruppenbeitritt ohne Einladung zulässig ist."/>  		<check_box label="Kosten für Beitritt" name="check_enrollment_fee" tool_tip="Festlegen, ob Neumitglieder eine Beitrittsgebühr zahlen müssen"/>  		<spinner label="L$" name="spin_enrollment_fee" tool_tip="Wenn Beitrittsgebühr aktiviert ist, müssen neue Mitglieder diesen Betrag zahlen."/> -		<combo_box name="group_mature_check" tool_tip="Inhaltseinstufungen kennzeichnen die in einer Gruppe zulässigen Inhalte und Verhaltensweisen"> +		<combo_box name="group_mature_check" tool_tip="Legt fest, ob Ihre Gruppe als moderat eingestufte Informationen enthält">  			<combo_item name="select_mature">  				- Inhaltseinstufung auswählen -  			</combo_item> diff --git a/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml new file mode 100644 index 0000000000..fc911a64df --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Unbekannt"/> +	<button name="info_btn" tool_tip="Mehr Infos"/> +	<button name="profile_btn" tool_tip="Profil anzeigen"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_me.xml b/indra/newview/skins/default/xui/de/panel_me.xml deleted file mode 100644 index f49446fbbf..0000000000 --- a/indra/newview/skins/default/xui/de/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mein Profil" name="panel_me"> -	<panel label="MEINE AUSWAHLEN" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/de/panel_people.xml b/indra/newview/skins/default/xui/de/panel_people.xml index 81de679429..e4a4c1033e 100644 --- a/indra/newview/skins/default/xui/de/panel_people.xml +++ b/indra/newview/skins/default/xui/de/panel_people.xml @@ -40,6 +40,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte].  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Online"/>  				<accordion_tab name="tab_all" title="Alle"/> +				<accordion_tab name="tab_suggested_friends" title="Potenzielle Freunde"/>  			</accordion>  		</panel>  		<panel label="GRUPPEN" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/de/panel_profile_classified.xml b/indra/newview/skins/default/xui/de/panel_profile_classified.xml new file mode 100644 index 0000000000..5c11a01977 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Moderat +	</panel.string> +	<panel.string name="type_pg"> +		Generelle Inhalte +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] Teleportieren, [MAP] Karten, [PROFILE] Profil +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Aktiviert +	</panel.string> +	<panel.string name="auto_renew_off"> +		Deaktiviert +	</panel.string> +	<panel.string name="location_notice"> +		(wird nach dem Speichern aktualisiert) +	</panel.string> +	<string name="publish_label"> +		Veröffentlichen +	</string> +	<string name="save_label"> +		Speichern +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Standort:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Inhaltsart:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Kategorie:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Erstellungsdatum:"/> +					<text_editor name="creation_date" tool_tip="Erstellungsdatum" value="[date]"/> +					<text name="price_for_listing_label" value="Preis für Auflistung:"/> +					<text_editor name="price_for_listing" tool_tip="Preis für Auflistung."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Klicks:"/> +					<text_editor name="click_through_text" tool_tip="Click-Through-Daten" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Autom. erneuern:"/> +					<text name="auto_renew" value="Aktiviert"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Beschreibung:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Titel: +				</text> +				<text name="description_label"> +					Beschreibung: +				</text> +				<text name="location_label"> +					Standort: +				</text> +				<text name="classified_location_edit"> +					Laden... +				</text> +				<button label="Aktuellen Standort verwenden" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Kategorie:"/> +				<text name="content_type_label" value="Inhaltsart:"/> +				<icons_combo_box label="Generelle Inhalte" name="content_type_edit"> +					<icons_combo_box.item label="Moderate Inhalte" name="mature_ci" value="Adult"/> +					<icons_combo_box.item label="Generelle Inhalte" name="pg_ci" value="PG"/> +				</icons_combo_box> +				<check_box label="Jede Woche automatisch erneuern" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Preis für Auflistung:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Preis für Auflistung." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Teleportieren" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Karte" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Bearbeiten" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Abbrechen" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml new file mode 100644 index 0000000000..83549cb138 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anzeige" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="Keine Anzeigen"/> +	<button label="Neu..." name="new_btn"/> +	<button label="Löschen..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Laden... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/de/floater_picks.xml b/indra/newview/skins/default/xui/de/panel_profile_firstlife.xml index 2521920e83..0f65090209 100644 --- a/indra/newview/skins/default/xui/de/floater_picks.xml +++ b/indra/newview/skins/default/xui/de/panel_profile_firstlife.xml @@ -1,2 +1,2 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Auswahlen"/> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/de/panel_profile_interests.xml b/indra/newview/skins/default/xui/de/panel_profile_interests.xml new file mode 100644 index 0000000000..0f36f76aa0 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interessen" name="panel_profile_interests"> +	<text name="I Want To:"> +		Ich möchte: +	</text> +	<check_box label="Erstellen" name="chk0"/> +	<check_box label="Erkunden" name="chk1"/> +	<check_box label="Treffen" name="chk2"/> +	<check_box label="Angestellt werden" name="chk6"/> +	<check_box label="Gruppe" name="chk3"/> +	<check_box label="Kaufen" name="chk4"/> +	<check_box label="Verkaufen" name="chk5"/> +	<check_box label="Anstellen" name="chk7"/> +	<line_editor name="want_to_edit"> +		(wird geladen...) +	</line_editor> +	<text name="Skills:"> +		Fähigkeiten: +	</text> +	<check_box label="Texturen" name="schk0"/> +	<check_box label="Architektur" name="schk1"/> +	<check_box label="Modellierung" name="schk3"/> +	<check_box label="Eventplanung" name="schk2"/> +	<check_box label="Scripting" name="schk4"/> +	<check_box label="Benutzerdefinierte Charaktere" name="schk5"/> +	<line_editor name="skills_edit"> +		(wird geladen...) +	</line_editor> +	<text name="Languages:"> +		Sprachen: +	</text> +	<line_editor name="languages_edit"> +		(wird geladen...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_notes.xml b/indra/newview/skins/default/xui/de/panel_profile_notes.xml new file mode 100644 index 0000000000..05c46ff858 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anmerkungen & Privatsphäre" name="panel_notes"> +	<text name="status_message" value="Private Anmerkungen zu diesem Avatar:"/> +	<text name="status_message2" value="Dieser Avatar darf:"/> +	<check_box label="Sehen, wenn ich online bin" name="status_check"/> +	<check_box label="Mich auf der Weltkarte sehen" name="map_check"/> +	<check_box label="Meine Objekte bearbeiten, löschen oder nehmen" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_pick.xml b/indra/newview/skins/default/xui/de/panel_profile_pick.xml new file mode 100644 index 0000000000..1f44ba8b1b --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(wird nach dem Speichern aktualisiert) +	</panel.string> +	<line_editor name="pick_location"> +		Laden... +	</line_editor> +	<button label="Teleportieren" name="teleport_btn"/> +	<button label="Auf Karte anzeigen" name="show_on_map_btn"/> +	<button label="Standort festlegen" name="set_to_curr_location_btn" tool_tip="Aktuellen Standort verwenden"/> +	<button label="Auswahl speichern" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_picks.xml b/indra/newview/skins/default/xui/de/panel_profile_picks.xml new file mode 100644 index 0000000000..96403715e4 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Auswahlen" name="panel_picks"> +	<string name="no_picks" value="Keine Auswahl"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Erzählen Sie von Ihren Lieblingsorten in Second Life. +	</text> +	<button label="Neu..." name="new_btn"/> +	<button label="Löschen..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Laden... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml new file mode 100644 index 0000000000..baaa58e1d7 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> +	<string name="status_online"> +		Zurzeit online +	</string> +	<string name="status_offline"> +		Zurzeit offline +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=de +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=de +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Keine"/> +	<string name="no_group_text" value="Keine"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Entwickler"/> +	<string name="FSSupp" value="Support"/> +	<string name="FSQualityAssurance" value="Fehlersuche"/> +	<string name="FSGW" value="Gateway"/> +	<text name="name_label" value="Name:"/> +	<button label="Name:" name="set_name" tool_tip="Anzeigenamen festlegen"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(wird geladen...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Status unbekannt"/> +			<text name="label" value="Second Life-Geburtsdatum:"/> +			<text name="label2" value="Konto:"/> +			<text name="partner_label" value="Partner:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Gruppen:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="In Gruppe einladen"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="Info:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Objekt geben:"/> +			<text name="Give inventory" tool_tip="Legen Sie hier Inventarobjekte ab, um Sie dieser Person zu geben."> +				Inventarobjekt hier ablegen. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Auf Karte anzeigen" label_selected="Auf Karte anzeigen" name="show_on_map_btn" tool_tip="Einwohner auf Karte lokalisieren"/> +			<button label="Bezahlen" label_selected="Bezahlen" name="pay" tool_tip="Geld an den Einwohner zahlen"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Teleportation anbieten" label_selected="Teleportation anbieten" name="teleport" tool_tip="Dem Einwohner eine Teleportation anbieten"/> +			<button label="Instant Message" label_selected="Instant Message" name="im" tool_tip="Instant Message-Sitzung öffnen"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Freund hinzufügen" label_selected="Freund hinzufügen" name="add_friend" tool_tip="Dem Einwohner die Freundschaft anbieten"/> +			<button label="Blockieren" name="block" tool_tip="Diesen Einwohner blockieren"/> +			<button label="Blockierung aufheben" name="unblock" tool_tip="Diesen Einwohner nicht mehr blockieren"/> +		</layout_panel> +	</layout_stack> +	<check_box label="In Suche anzeigen" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/panel_profile_web.xml b/indra/newview/skins/default/xui/de/panel_profile_web.xml new file mode 100644 index 0000000000..a03918f4b5 --- /dev/null +++ b/indra/newview/skins/default/xui/de/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Ladezeit: [TIME] Sekunden"/> +	<line_editor name="url_edit"> +		(wird geladen..) +	</line_editor> +	<flyout_button label="Laden" name="load" tool_tip="Lädt diese Profilseite im integrierten Webbrowser."> +		<flyout_button.item label="Im Viewer-Browser öffnen" name="open_item"/> +		<flyout_button.item label="In externem Browser öffnen" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Webprofil ausklappen"/> +</panel> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 97ace4fc18..4625c48714 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -356,6 +356,24 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.  	<string name="TestingDisconnect">  		Verbindungsabbruch wird getestet  	</string> +	<string name="SocialFacebookConnecting"> +		Mit Facebook verbinden... +	</string> +	<string name="SocialFacebookPosting"> +		Posten... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Facebook-Verbindung trennen... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Problem beim Verbinden mit Facebook +	</string> +	<string name="SocialFacebookErrorPosting"> +		Problem beim Posten auf Facebook +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Problem beim Trennen der Facebook-Verbindung +	</string>  	<string name="SocialFlickrConnecting">  		Verbinden mit Flickr...  	</string> @@ -2578,9 +2596,21 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich unter http://suppo  	<string name="NoPicksClassifiedsText">  		Sie haben keine Auswahl oder Anzeigen erstelllt. Klicken Sie auf die „Plus"-Schaltfläche, um eine Auswahl oder Anzeige zu erstellen.  	</string> +	<string name="NoPicksText"> +		Sie haben keine Auswahl erstellt. Klicken Sie auf die Schaltfläche "Neu", um eine Auswahl zu erstellen. +	</string> +	<string name="NoClassifiedsText"> +		Sie haben keine Anzeigen erstellt. Klicken Sie auf die Schaltfläche "Neu", um eine Anzeige zu erstellen. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		Der Einwohner hat keine Auswahl oder Anzeigen  	</string> +	<string name="NoAvatarPicksText"> +		Der Einwohner hat keine Auswahl +	</string> +	<string name="NoAvatarClassifiedsText"> +		Der Einwohner hat keine Anzeigen +	</string>  	<string name="PicksClassifiedsLoadingText">  		Wird geladen...  	</string> @@ -4558,6 +4588,9 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_  	<string name="share_alert">  		Objekte aus dem Inventar hier her ziehen  	</string> +	<string name="facebook_post_success"> +		Sie haben auf Facebook gepostet. +	</string>  	<string name="flickr_post_success">  		Sie haben auf Flickr gepostet.  	</string> diff --git a/indra/newview/skins/default/xui/en/floater_picks.xml b/indra/newview/skins/default/xui/en/floater_classified.xml index 984894b016..5b14c827d0 100644 --- a/indra/newview/skins/default/xui/en/floater_picks.xml +++ b/indra/newview/skins/default/xui/en/floater_classified.xml @@ -2,20 +2,19 @@  <floater   positioning="cascading"   can_close="true" - can_resize="true" + can_resize="false"   height="572"   help_topic="sidebar_me"   min_width="333"   min_height="440" - name="floater_picks" + name="floater_classified"   save_rect="true" - save_visibility="true" - reuse_instance="true" - title="Picks" + save_visibility="false" + title="Classified"   width="333" >     <panel -    class="panel_me" +    class="panel_classified_info"      name="main_panel" -    filename="panel_me.xml" +    filename="panel_classified_info.xml"      follows="all"/>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_display_name.xml b/indra/newview/skins/default/xui/en/floater_display_name.xml index 9a9fd32a77..3c8f415860 100644 --- a/indra/newview/skins/default/xui/en/floater_display_name.xml +++ b/indra/newview/skins/default/xui/en/floater_display_name.xml @@ -23,7 +23,7 @@       use_ellipses="true"       width="380"       wrap="true"> -      The name you give your avatar is called your Display Name. You can change it once a week. +      Your display name is what other people see above your head. It is different from your login name. You can change it once a week.      </text>  	<text       type="string" @@ -85,19 +85,10 @@       width="120" />      <button       height="23" -     label="Reset" -     layout="topleft" -     font="SansSerif" -     left_pad="5" -     name="reset_btn" -     tool_tip="Make Display Name the same as Username" -     width="120" /> -    <button -     height="23"       label="Cancel"       font="SansSerif"       layout="topleft" -     left_pad="5" +     left_pad="125"       name="cancel_btn"       width="120" />  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml index 74adc86126..0a05a4f868 100644 --- a/indra/newview/skins/default/xui/en/floater_material_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml @@ -111,6 +111,7 @@                 layout="topleft"                 left_delta="0"                 top_pad="5" +               min_val="0"                 max_val="1"                 name="transparency"                width="64" @@ -169,6 +170,7 @@                 layout="topleft"                 left_delta="0"                 top_pad="5" +               min_val="0"                 max_val="1"                 name="alpha cutoff"                width="64" @@ -245,6 +247,7 @@               layout="topleft"               left_delta="0"               top_pad="5" +             min_val="0"               max_val="1"               name="metalness factor"              width="64" @@ -270,7 +273,7 @@                 layout="topleft"                 left_delta="0"                 top_pad="5" -                +               min_val="0"                 max_val="1"                 name="roughness factor"                width="64" diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml index 6aff387dcb..db81c8bba2 100644 --- a/indra/newview/skins/default/xui/en/floater_my_environments.xml +++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml @@ -119,7 +119,7 @@                         follows="all"                         layout="topleft"                         name="pnl_settings" -                       filter_asset_type="settings"/> +                       filter_asset_types="settings"/>              </panel>          </layout_panel>          <layout_panel diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index b7708b057d..97a87d56f4 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -272,22 +272,6 @@       Hardware    </text> -  <slider -    control_name="TextureMemory" -    decimal_digits="0" -    follows="left|top" -    height="16" -    increment="16" -    initial_value="32" -    label="Texture Memory (MB):" -    label_width="185" -    layout="topleft" -    left="30" -    max_val="4096" -    name="GraphicsCardTextureMemory" -    tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry." -    top_delta="16" -    width="335" />    <check_box      control_name="RenderAnisotropic" diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml index e1e7e1c8c8..048cf7df62 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -17,94 +17,122 @@       name="Copy">          Copy To Inventory      </floater.string> -    <text -     type="string" -     length="1" -     follows="left|top" -     font="SansSerif" -     height="19" -     layout="topleft" -     left="10" -     name="desc txt" -     top="21" -     width="90"> -        Description: -    </text> -    <line_editor -     border_style="line" -     border_thickness="1" -     follows="left|top|right" -     font="SansSerif" -     height="19" -     layout="topleft" -     left_pad="0" -     max_length_bytes="127" -     name="desc" -     width="190" /> -    <text -     type="string" -     halign="right" -     length="1" -     follows="right|bottom" -     height="16" -     layout="topleft" -     left="110" -     name="dimensions" -     top="255" -     width="200"> -        [WIDTH]px x [HEIGHT]px -    </text> -    <text -     type="string" -     halign="right" -     length="1" -     follows="right|bottom" -     height="16" -     layout="topleft" -     left_delta="-110" -     name="aspect_ratio" -     top_pad="5" -     width="200"> -        Preview aspect ratio -    </text> -    <combo_box -     allow_text_entry="true"  -     top_delta="-3"  -     follows="right|bottom"  -     height="23" -     left_pad="10" -     max_chars="20" -     mouse_opaque="true" -     enabled="true" -     width="108" -     name="combo_aspect_ratio" -     tool_tip="Preview at a fixed aspect ratio"> -	</combo_box> -    <button -     follows="right|bottom" -     height="22" -     label="OK" -     layout="topleft" -     left="6" -     name="Keep" -     top_pad="5" -     width="110" /> -    <button -     follows="right|bottom" -     height="22" -     label="Discard" -     layout="topleft" -     left_pad="5" -     name="Discard" -     top_delta="0" -     width="110" /> -    <button -     follows="right|bottom" -     height="22" -     label="Save As" -     layout="topleft" -     left_pad="5" -     name="save_tex_btn" -     top_delta="0" -     width="110" /> +    <layout_stack +     animate="false" +     name="preview_stack" +     top_pad="15" +     left="0" +     follows="all" +     orientation="vertical" +     height="350" +     width="370" +     layout="topleft"> +      <layout_panel +        name="texture_panel" +        height="305" +        top_pad="0" +        left="0" +        follows="left|top" +        layout="topleft"> +          <text +           type="string" +           length="1" +           follows="left|top" +           font="SansSerif" +           height="19" +           layout="topleft" +           left="10" +           name="desc txt" +           top="6" +           width="90"> +              Description: +          </text> +          <line_editor +           border_style="line" +           border_thickness="1" +           follows="left|top|right" +           font="SansSerif" +           height="19" +           layout="topleft" +           left_pad="0" +           max_length_bytes="127" +           name="desc" +           width="190" /> +          <text +           type="string" +           halign="right" +           length="1" +           follows="right|bottom" +           height="16" +           layout="topleft" +           left="110" +           name="dimensions" +           bottom="-40" +           width="200"> +              [WIDTH]px x [HEIGHT]px +          </text> +          <text +           type="string" +           halign="right" +           length="1" +           follows="right|bottom" +           height="16" +           layout="topleft" +           left_delta="-110" +           name="aspect_ratio" +           top_pad="5" +           width="200"> +              Preview aspect ratio +          </text> +          <combo_box +           allow_text_entry="true"  +           top_delta="-3"  +           follows="right|bottom"  +           height="23" +           left_pad="10" +           max_chars="20" +           mouse_opaque="true" +           enabled="true" +           width="108" +           name="combo_aspect_ratio" +           tool_tip="Preview at a fixed aspect ratio"> +	      </combo_box> +      </layout_panel> +      <layout_panel +        name="buttons_panel" +        height="45" +        bottom="-40" +        left="0" +        follows="right|bottom" +        auto_resize="false" +        layout="topleft"> +        <button +         follows="right|bottom" +         height="22" +         label="OK" +         layout="topleft" +         left="6" +         name="Keep" +         top_pad="0" +         width="110" /> +        <button +         follows="right|bottom" +         height="22" +         label="Discard" +         layout="topleft" +         left_pad="5" +         name="Discard" +         top_delta="0" +         width="110" /> +        <button +         follows="right|bottom" +         height="22" +         label="Save As" +         layout="topleft" +         left_pad="5" +         name="save_tex_btn" +         top_delta="0" +         width="110" /> +      </layout_panel> +    </layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile.xml b/indra/newview/skins/default/xui/en/floater_profile.xml new file mode 100644 index 0000000000..32ab811a6e --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater + name="avatarinfo" + height="510" + width="510" + layout="topleft" + can_close="true" + can_resize="true" + help_topic="panel_my_profile_tab" + min_height="510" + min_width="510" + positioning="centered" + save_rect="true" + title="Profile" +> +    <panel +     name="panel_profile_view" +     top="0" +     left="0" +     height="500" +     width="505" +     follows="all" +     class="panel_profile" +    > +        <tab_container +         name="panel_profile_tabs" +         top_pad="5" +         left="0" +         height="500" +         width="505" +         follows="all" +         layout="topleft" +         halign="center" +         tab_min_width="81" +         tab_height="30" +         tab_position="top" +        > +            <panel +             name="panel_profile_secondlife" +             label="BIO" +             layout="topleft" +             class="panel_profile_secondlife" +             filename="panel_profile_secondlife.xml" +             help_topic="profile_secondlife_tab" +            /> +            <panel +             name="panel_profile_web" +             label="FEED" +             layout="topleft" +             class="panel_profile_web" +             filename="panel_profile_web.xml" +             help_topic="profile_web_tab" +            /> +            <panel +             name="panel_profile_picks" +             label="PICKS" +             layout="topleft" +             class="panel_profile_picks" +             filename="panel_profile_picks.xml" +             help_topic="profile_picks_tab" +            /> +            <panel +             name="panel_profile_classifieds" +             label="CLASSIFIEDS" +             layout="topleft" +             class="panel_profile_classifieds" +             filename="panel_profile_classifieds.xml" +             help_topic="profile_classified_tab" +            /> +            <panel +             name="panel_profile_firstlife" +             label="REAL LIFE" +             layout="topleft" +             class="panel_profile_firstlife" +             filename="panel_profile_firstlife.xml" +             help_topic="profile_firstlife_tab" +            /> +            <panel +             name="panel_profile_notes" +             label="MY NOTES" +             layout="topleft" +             class="panel_profile_notes" +             filename="panel_profile_notes.xml" +             help_topic="profile_notes_tab" +            /> +        </tab_container> +    </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile_permissions.xml b/indra/newview/skins/default/xui/en/floater_profile_permissions.xml new file mode 100644 index 0000000000..9f3b4d9a00 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile_permissions.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="false" + show_title="false" + can_minimize="false" + can_close="false" + header_height="10" + bg_opaque_image="Window_NoTitle_Foreground" + bg_alpha_image="Window_NoTitle_Background" + height="115" + layout="topleft" + name="profile_permissions" + width="300"> +  <string +   name="description_string" +   value="Allow [AGENT_NAME] to:" /> +  <text +   name="perm_description" +   value="Allow agent to:" +   top="1" +   left="12" +   right="-6" +   height="16" +   follows="top|left" +   layout="topleft" +   font.style="BOLD" +    /> +  <check_box +   name="online_check" +   label="See when I am online" +   top_pad="5" +   left="16" +   height="16" +   width="293" +   follows="top|left" +   layout="topleft" +    /> +  <check_box +   name="map_check" +   label="Find me on the world map" +   top_pad="5" +   left="16" +   height="16" +   width="293" +   follows="top|left" +   layout="topleft" +    /> +  <check_box +   name="objects_check" +   label="Edit, delete or take my objects from my land" +   top_pad="5" +   left="16" +   height="16" +   width="293" +   follows="top|left" +   layout="topleft" +    /> +  <button +   name="perms_btn_ok" +   label="OK" +   top_pad="5" +   left="42" +   height="20" +   width="100" +   follows="top|left" +   layout="topleft"/> +  <button +   name="perms_btn_cancel" +   label="Cancel" +   top_delta="0" +   left_pad="12" +   height="20" +   width="100" +   follows="top|left" +   layout="topleft"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_profile_texture.xml b/indra/newview/skins/default/xui/en/floater_profile_texture.xml new file mode 100644 index 0000000000..3b351a3325 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_profile_texture.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="false" + show_title="false" + can_minimize="false" + can_close="false" + header_height="10" + height="223" + width="200" + layout="topleft" + min_height="128" + min_width="128" + name="profile_texture"> +    <layout_stack +     name="preview_stack" +     top="0" +     left="0" +     right="-1" +     bottom="-1" +     follows="all" +     orientation="vertical" +     layout="topleft" +     animate="false"> +      <layout_panel +        name="texture_panel" +        height="196" +        follows="left|top" +        auto_resize="true" +        layout="topleft"> +        <icon +         name="profile_pic" +         image_name="Generic_Person_Large" +         layout="topleft" +         follows="all" +         top="5" +         left="5" +         bottom="-1" +         right="-5"/> +      </layout_panel> +      <layout_panel +        name="buttons_panel" +        height="26" +        auto_resize="false" +        layout="topleft"> +        <layout_stack +         name="buttons_stack" +         top="0" +         left="0" +         right="-1" +         bottom="-1" +         follows="all" +         orientation="horizontal" +         layout="topleft" +         animate="false"> +          <layout_panel +           follows="all" +           layout="topleft" +           name="resizer_left" +           auto_resize="true" +           width="1"> +          </layout_panel> +          <layout_panel +           follows="all" +           layout="topleft" +           name="close_panel" +           auto_resize="false" +           width="112"> +            <button +             follows="top|left" +             height="22" +             label="Close" +             layout="topleft" +             left="1" +             top="0" +             width="110" +             name="close_btn"/> +          </layout_panel> +          <layout_panel +           follows="all" +           layout="topleft" +           name="resizer_right" +           auto_resize="true" +           width="1"> +          </layout_panel> +        </layout_stack> +      </layout_panel> +    </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_settings_picker.xml b/indra/newview/skins/default/xui/en/floater_settings_picker.xml index 3a26c3b547..8931269fe7 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_picker.xml @@ -89,7 +89,7 @@                      top="1"                      right="-4"                      bottom="-1" -                    filter_asset_type="settings" /> +                    filter_asset_types="settings" />              </panel>          </layout_panel>          <layout_panel name="pnl_combo" 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 3a66911389..18c226ed58 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -137,7 +137,29 @@       value="Preview Disabled"       word_wrap="true"       visible="false" -     width="87" /> +     width="87" />   +    <combo_box +      follows="left|top|right" +      height="23" +      label="Choose Textures, Materials or LIFE!" +      layout="topleft" +      left="175" +      name="textures_material_combo" +      top="20" +      width="231"> +      <combo_box.item +       label="Materials & Textures" +       name="Materials_Textures" +       value="0" /> +      <combo_box.item +       label="Textures" +       name="Textures" +       value="1" /> +      <combo_box.item +       label="Materials" +       name="Materials" +       value="2" /> +    </combo_box>      <filter_editor       follows="left|top|right"       height="23" @@ -145,21 +167,21 @@       layout="topleft"       left="175"       name="inventory search editor" -     top="20" +     top="48"       width="231" /> -    <asset_filtered_inv_panel -     allow_multi_select="false" +  <asset_filtered_inv_panel +   allow_multi_select="false"       bg_visible="true"       bg_alpha_color="DkGray2"       border="false"       follows="all" -     height="233" +     height="195"       layout="topleft"       left_delta="0"       name="inventory panel"       top_pad="4"       width="231" -     filter_asset_type="texture"/> +     filter_asset_types="texture|material"/>       <check_box       height="14"       initial_value="false" @@ -218,8 +240,8 @@       multi_select="true"       search_column="1"       visible="false"> +        <column name="icon" label="" width="20" />          <column name="unit_name" label="Name" dynamicwidth="true" /> -        <column name="unit_id_HIDDEN" label="ID" width="0" />      </scroll_list>  <!-- middle: bake mode --> diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml deleted file mode 100644 index 9278a1a598..0000000000 --- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml +++ /dev/null @@ -1,440 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - can_minimize="false" - height="600" - layout="topleft" - name="TexFetchDebugger" - help_topic="texfetchdebugger" - title="Texture Fetching Debugger" - width="540"> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left="10" -   name="total_num_fetched_label" -   top="30" -   width="400"> -    1, Total number of fetched textures: [NUM] -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_num_fetching_requests_label" -   top_delta="25" -   width="400"> -    2, Total number of fetching requests: [NUM] -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_num_cache_hits_label" -   top_delta="25" -   width="400"> -    3, Total number of cache hits: [NUM] -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_num_visible_tex_label" -   top_delta="25" -   width="400"> -    4, Total number of visible textures: [NUM] -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_num_visible_tex_fetch_req_label" -   top_delta="25" -   width="450"> -    5, Total number of visible texture fetching requests: [NUM] -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_fetched_data_label" -   top_delta="25" -   width="530"> -    6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_fetched_vis_data_label" -   top_delta="25" -   width="480"> -    7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_fetched_rendered_data_label" -   top_delta="25" -   width="530"> -    8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_cache_read_label" -   top_delta="25" -   width="400"> -    9, Total time on cache readings: [TIME] seconds -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_cache_write_label" -   top_delta="25" -   width="400"> -    10, Total time on cache writings: [TIME] seconds -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_decode_label" -   top_delta="25" -   width="400"> -    11, Total time on decodings: [TIME] seconds -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_gl_label" -   top_delta="25" -   width="400"> -    12, Total time on gl texture creation: [TIME] seconds -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_http_label" -   top_delta="25" -   width="400"> -    13, Total time on HTTP fetching: [TIME] seconds -  </text> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="25" -   layout="topleft" -   left_delta="0" -   name="total_time_fetch_label" -   top_delta="25" -   width="400"> -    14, Total time on entire fetching: [TIME] seconds -  </text> -  <text -  type="string" -  length="1" -  follows="left|top" -  height="25" -  layout="topleft" -  left_delta="0" -  name="total_time_refetch_vis_cache_label" -  top_delta="25" -  width="540"> -    15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels -  </text> -  <text -  type="string" -  length="1" -  follows="left|top" -  height="25" -  layout="topleft" -  left_delta="0" -  name="total_time_refetch_all_cache_label" -  top_delta="25" -  width="540"> -    16, Refetching all textures from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels -  </text> -  <text -  type="string" -  length="1" -  follows="left|top" -  height="25" -  layout="topleft" -  left_delta="0" -  name="total_time_refetch_vis_http_label" -  top_delta="25" -  width="540"> -    17, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels -  </text> -  <text -  type="string" -  length="1" -  follows="left|top" -  height="25" -  layout="topleft" -  left_delta="0" -  name="total_time_refetch_all_http_label" -  top_delta="25" -  width="540"> -    18, Refetching all textures from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels -  </text> -  <spinner -     decimal_digits="2" -     follows="left|top" -     height="20" -     increment="0.01" -     initial_value="1.0" -     label="19, Ratio of Texel/Pixel:" -     label_width="130" -     layout="topleft" -     left_delta="0" -     max_val="10.0" -     min_val="0.01" -     name="texel_pixel_ratio" -     top_delta="30" -     width="200"> -    <spinner.commit_callback -		function="TexFetchDebugger.ChangeTexelPixelRatio" /> -  </spinner> -  <text -  type="string" -  length="1" -  follows="left|top" -  height="25" -  layout="topleft" -  left_delta="0" -  name="texture_source_label" -  top_delta="30" -  width="110"> -    20, Texture Source: -  </text> -  <radio_group -     control_name="TextureFetchSource" -     follows="top|left" -     draw_border="false" -     height="25" -     layout="topleft" -     left_pad="0" -     name="texture_source" -     top_delta="0" -     width="264"> -    <radio_item -     height="16" -     label="Cache + HTTP" -     layout="topleft" -     left="3" -     name="0" -     top="0" -     width="100" /> -    <radio_item -     height="16" -     label="HTTP Only" -     layout="topleft" -     left_delta="100" -     name="1" -     top_delta="0" -     width="200" /> -  </radio_group> -  <button -   follows="left|top" -   height="20" -   label="Start" -   layout="topleft" -   left="10" -   name="start_btn" -   top_delta="20" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.Start" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Reset" -   layout="topleft" -   left_pad="7" -   name="clear_btn" -   top_delta="0" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.Clear" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Close" -   layout="topleft" -   left_pad="7" -   name="close_btn" -   top_delta="0" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.Close" /> -  </button> -  <button -   follows="left|top" -   height="22" -   label="Reset Fetching Time" -   layout="topleft" -   left_pad="175" -   name="reset_time_btn" -   top_delta="0" -   width="120"> -    <button.commit_callback -		function="TexFetchDebugger.ResetFetchTime" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Cache Read" -   layout="topleft" -   left="10" -   name="cacheread_btn" -   top_delta="20" -   width="80"> -    <button.commit_callback -		function="TexFetchDebugger.CacheRead" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Cache Write" -   layout="topleft" -   left_pad="7" -   name="cachewrite_btn" -   top_delta="0" -   width="80"> -    <button.commit_callback -		function="TexFetchDebugger.CacheWrite" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="HTTP" -   layout="topleft" -   left_pad="7" -   name="http_btn" -   top_delta="0" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.HTTPLoad" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Decode" -   layout="topleft" -   left_pad="7" -   name="decode_btn" -   top_delta="0" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.Decode" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="GL Texture" -   layout="topleft" -   left_pad="7" -   name="gl_btn" -   top_delta="0" -   width="70"> -    <button.commit_callback -		function="TexFetchDebugger.GLTexture" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Refetch Vis Cache" -   layout="topleft" -   left="10" -   name="refetchviscache_btn" -   top_delta="20" -   width="120"> -    <button.commit_callback -		function="TexFetchDebugger.RefetchVisCache" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Refetch All Cache" -   layout="topleft" -   left_pad="7" -   name="refetchallcache_btn" -   top_delta="0" -   width="120"> -    <button.commit_callback -		function="TexFetchDebugger.RefetchAllCache" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Refetch Vis HTTP" -   layout="topleft" -   left_pad="7" -   name="refetchvishttp_btn" -   top_delta="0" -   width="120"> -    <button.commit_callback -		function="TexFetchDebugger.RefetchVisHTTP" /> -  </button> -  <button -   follows="left|top" -   height="20" -   label="Refetch All HTTP" -   layout="topleft" -   left_pad="7" -   name="refetchallhttp_btn" -   top_delta="0" -   width="120"> -    <button.commit_callback -		function="TexFetchDebugger.RefetchAllHTTP" /> -  </button> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 449bf8fa3a..4700488197 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2,7 +2,7 @@  <floater   positioning="cascading"   legacy_header_height="18" - height="640" + height="651"   layout="topleft"   bg_opaque_image="Window_NoTitle_Foreground"   bg_alpha_image="Window_NoTitle_Background" @@ -68,7 +68,7 @@      </floater.string>      <floater.string       name="status_selectcount"> -        [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] +        [OBJ_COUNT] objects selected, land impact [LAND_IMPACT] [secondlife:///app/openfloater/object_weights More info]      </floater.string>      <floater.string       name="status_remaining_capacity"> @@ -763,11 +763,12 @@  	  font="SansSerifSmall"  	  layout="topleft"  	  left="10" -	  name="selection_count" +	  name="selection_faces"  	  top_delta="0"  	  visible="false"  	  width="280"> -	</text> +    Faces selected: [FACES_STRING] +  </text>  	<text  	 text_color="LtGray_50"  	  type="string" @@ -777,11 +778,10 @@  	  font="SansSerifSmall"  	  layout="topleft"  	  left="10" -	  name="remaining_capacity" +	  name="selection_count"  	  top_pad="0"  	  visible="false"  	  width="280"> -	  [CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info]  	</text>      <!-- <text -->      <!-- text_color="LtGray_50" --> @@ -820,7 +820,7 @@      width="282"/>      <tab_container       follows="left|top" -     height="460" +     height="476"       halign="center"       left="0"       name="Object Info Tabs" @@ -1430,16 +1430,40 @@ even though the user gets a free copy.               tool_tip="Causes object to not collide with other objects or avatars"               top_pad="0"               width="123" /> -        <text +            <view_border +             bevel_style="none" +             follows="top|left" +             height="0" +             layout="topleft" +             left_delta="0" +             name="object_horizontal" +             top_pad="10" +             width="95" /> +            <menu_button +             menu_filename="menu_copy_paste_pos.xml" +             follows="top|left" +             height="11" +             image_disabled="ClipboardSmallMenu_Disabled" +             image_selected="ClipboardSmallMenu_Press" +             image_unselected="ClipboardSmallMenu_Off" +             layout="topleft" +             left_delta="0" +             top_pad="13" +             name="clipboard_pos_btn" +             tool_tip="Paste options" +             width="19"/> +            <text               type="string"               length="1"               follows="left|top"               height="10"               layout="topleft"               name="label position" -             top_pad="10" +             tool_tip="Position (meters)" +             left_pad="8" +             top_delta="0"               width="121"> -                Position (meters) +                Position (m)              </text>              <spinner               follows="left|top" @@ -1449,12 +1473,12 @@ even though the user gets a free copy.               label="X"               label_width="10"               layout="topleft" -             left_delta="0" +             left_delta="-27"               max_val="512"               min_val="-256"               name="Pos X"               text_enabled_color="1 0 0.3 .7" -             top_pad="5" +             top_pad="8"               width="87" />              <spinner               follows="left|top" @@ -1481,21 +1505,36 @@ even though the user gets a free copy.               layout="topleft"               left_delta="0"               max_val="4096" +             min_val="-32"               name="Pos Z"               text_enabled_color="0 0.8 1 .65"               top_pad="3"               width="87" /> +            <menu_button +             menu_filename="menu_copy_paste_size.xml" +             follows="top|left" +             height="11" +             image_disabled="ClipboardSmallMenu_Disabled" +             image_selected="ClipboardSmallMenu_Press" +             image_unselected="ClipboardSmallMenu_Off" +             layout="topleft" +             left_delta="0" +             top_pad="13" +             name="clipboard_size_btn" +             tool_tip="Paste options" +             width="19"/>              <text               type="string"               length="1"               follows="left|top"               height="10"               layout="topleft" -             left_delta="0" +             left_pad="8" +             top_delta="0"               name="label size" -             top_pad="6" +             tool_tip="Size (meters)"               width="121"> -                Size (meters) +                Size (m)              </text>              <spinner               follows="left|top" @@ -1505,12 +1544,12 @@ even though the user gets a free copy.               label="X"               label_width="10"               layout="topleft" -             left_delta="0" +             left_delta="-27"               max_val="64"               min_val="0.01"               name="Scale X"               text_enabled_color="1 1 1 1" -             top_pad="5" +             top_pad="8"               width="87" />              <spinner               follows="left|top" @@ -1542,17 +1581,31 @@ even though the user gets a free copy.               text_enabled_color="1 1 1 1"               top_pad="3"               width="87" /> +            <menu_button +             menu_filename="menu_copy_paste_rot.xml" +             follows="top|left" +             height="11" +             image_disabled="ClipboardSmallMenu_Disabled" +             image_selected="ClipboardSmallMenu_Press" +             image_unselected="ClipboardSmallMenu_Off" +             layout="topleft" +             left_delta="0" +             top_pad="13" +             name="clipboard_rot_btn" +             tool_tip="Paste options" +             width="19"/>              <text               type="string"               length="1"               follows="left|top"               height="10"               layout="topleft" -             left_delta="0" +             left_pad="8" +             top_delta="0"               name="label rotation" -             top_pad="10" +             tool_tip="Rotation (degrees)"               width="121"> -                Rotation (degrees) +                Rotation (°)              </text>              <spinner               decimal_digits="2" @@ -1563,12 +1616,12 @@ even though the user gets a free copy.               label="X"               label_width="10"               layout="topleft" -             left_delta="0" +             left_delta="-27"               max_val="9999"               min_val="-9999"               name="Rot X"               text_enabled_color="1 1 1 1" -             top_pad="5" +             top_pad="8"               width="87" />              <spinner               decimal_digits="2" @@ -1614,13 +1667,23 @@ even though the user gets a free copy.               width="150">                  Prim Type              </text>--> + +            <view_border +             bevel_style="none" +             follows="top|left" +             layout="topleft" +             name="object_vertical" +             left="117" +             top="6" +             height="500" +             width="0"/>              <combo_box               height="19"               layout="topleft"               name="comboBaseType"               top="6"               left="125" -             width="150"> +             width="125">                  <combo_box.item                   label="Box"                   name="Box" @@ -1654,13 +1717,26 @@ even though the user gets a free copy.                   name="Sculpted"                   value="Sculpted" />              </combo_box> +            <menu_button +              menu_filename="menu_copy_paste_object.xml" +              follows="top|left" +              height="15" +              image_disabled="ClipboardMenu_Disabled" +              image_selected="ClipboardMenu_Press" +              image_unselected="ClipboardMenu_Off" +              layout="topleft" +              left_pad="8" +              top_delta="2" +              name="clipboard_obj_params_btn" +              tool_tip="Paste options" +              width="22"/>              <text               type="string"               length="1"               follows="left|top"               height="10"               layout="topleft" -             left_delta="0" +             left="125"               name="text cut"               top_pad="5"               width="150"> @@ -1700,7 +1776,7 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="text hollow" -             top_pad="6" +             top_pad="7"               width="68">                  Hollow              </text> @@ -1748,7 +1824,7 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="Hollow Shape" -             top_pad="4" +             top_pad="7"               width="150">                  Hollow Shape              </text> @@ -1784,7 +1860,7 @@ even though the user gets a free copy.               layout="topleft"               left_delta="0"               name="text twist" -             top_pad="5" +             top_pad="7"               width="150">                  Twist (begin/end)              </text> @@ -1826,12 +1902,12 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="scale_taper" -             top_pad="3" +             top_pad="7"               width="150">                  Taper              </text>              <text -			 visible="false" +             visible="false"               type="string"               length="1"               follows="left|top" @@ -1879,7 +1955,7 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="text topshear" -             top_pad="3" +             top_pad="5"               width="141">                  Top Shear              </text> @@ -1922,12 +1998,12 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="advanced_cut" -             top_pad="3" +             top_pad="7"               width="150">                  Profile Cut (begin/end)              </text>              <text -			 visible="false" +             visible="false"               type="string"               length="1"               follows="left|top" @@ -1986,7 +2062,7 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="text taper2" -             top_pad="3" +             top_pad="7"               width="150">                  Taper              </text> @@ -2029,7 +2105,7 @@ even though the user gets a free copy.               layout="topleft"               left="125"               name="text radius delta" -             top_pad="2" +             top_pad="7"               width="78">                  Radius              </text> @@ -2157,6 +2233,19 @@ even though the user gets a free copy.  	<panel.string name="None">None</panel.string>  	<panel.string name="Prim">Prim</panel.string>  	<panel.string name="Convex Hull">Convex Hull</panel.string> +            <menu_button +              menu_filename="menu_copy_paste_features.xml" +              follows="top|left" +              height="15" +              image_disabled="ClipboardMenu_Disabled" +              image_selected="ClipboardMenu_Press" +              image_unselected="ClipboardMenu_Off" +              layout="topleft" +              left="258" +              top="8" +              name="clipboard_features_params_btn" +              tool_tip="Paste options" +              width="22"/>              <text               type="string"               length="1" @@ -2309,6 +2398,15 @@ even though the user gets a free copy.               name="FlexForceZ"               top_pad="4"               width="128" /> +            <view_border +             bevel_style="none" +             follows="top|left" +             height="0" +             layout="topleft" +             left="8" +             name="object_horizontal" +             top_pad="10" +             width="278" />              <check_box               height="16" @@ -2317,7 +2415,7 @@ even though the user gets a free copy.               left="10"               name="Light Checkbox Ctrl"               tool_tip="Causes object to emit light" -             top_pad="10" +             top_pad="8"               width="60" />              <color_swatch               can_apply_immediately="true" @@ -2344,6 +2442,19 @@ even though the user gets a free copy.              name="light texture control"              tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)"              width="32" /> +         <menu_button +              menu_filename="menu_copy_paste_light.xml" +              follows="top|left" +              height="15" +              image_disabled="ClipboardMenu_Disabled" +              image_selected="ClipboardMenu_Press" +              image_unselected="ClipboardMenu_Off" +              layout="topleft" +              left="258" +              top_delta="0" +              name="clipboard_light_params_btn" +              tool_tip="Paste options" +              width="22"/>            <spinner               follows="left|top"               height="19" @@ -2353,7 +2464,7 @@ even though the user gets a free copy.               layout="topleft"               left="10"               name="Light Intensity" -             top_delta="32" +             top_pad="26"               width="128" />            <spinner bottom_delta="0"                     decimal_digits="3" @@ -2638,7 +2749,7 @@ even though the user gets a free copy.               border_visible="true"               bevel_style="in"               follows="left|top|right" -             height="325" +             height="387"               layout="topleft"               left="10"               name="contents_inventory" diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 83407069d2..45e11fc836 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -14,6 +14,31 @@   single_instance="true"   title="WORLD MAP"   width="650"> +  <string +   name="collapse_icon" +   value="map_ui_collapse_icon.png"/> +  <string +   name="expand_icon" +   value="map_ui_expand_icon.png"/> +  <string +   name="collapse_tooltip" +   value="Hide map controls"/> +  <string +   name="expand_tooltip" +   value="Show map controls"/> +  <layout_stack +   animate="false" +   follows="all" +   name="floater_map_stack" +   tab_group="1" +   top="16" +   left="0" +   right="-1" +   bottom="-1"> +    <layout_panel +     name="map_lp" +     width="385" +     height="575">      <panel       filename="panel_world_map.xml"       follows="all" @@ -21,17 +46,48 @@       layout="topleft"       left="10"       name="objects_mapview" -     top="25" +     top="6"       width="375" /> +      <panel +       follows="top|right" +       height="30" +       layout="topleft" +       left_pad="-29" +       name="expand_btn_panel" +       background_visible="true" +       bg_opaque_color="FloaterFocusBackgroundColor" +       bg_alpha_color="FloaterDefaultBackgroundColor" +       background_opaque="true" +       tool_tip="Hide map controls" +       top="350" +       width="30"> +        <icon +         follows="top|right" +         height="16" +         width="16" +         top="7" +         left="7" +         scale_image="false" +         image_name="map_ui_collapse_icon.png" +         layout="topleft" +         mouse_opaque="true" +         name="expand_collapse_icon" +         tool_tip="Hide map controls" /> +      </panel> +      </layout_panel> +    <layout_panel +      height="575" +      width="265" +      expanded_min_dim="265" +      name="controls_lp">       <panel -     name="layout_panel_1" -     height="22" -     width="238" -     follows="right|top" -     top="25" -     left_pad="5" -  background_visible="true" -  bg_alpha_color="DkGray2"> +      name="layout_panel_1" +      height="22" +      width="238" +      follows="right|top" +      top="6"      +      background_visible="true" +      bg_alpha_color="DkGray2">      <text       text_color="White"       font="SansSerifLarge" @@ -43,17 +99,17 @@       layout="topleft"       left="15"       name="events_label" -     top="3"       width="215">          Legend      </text>      </panel> -<panel - follows="right|top" -  height="126" -  top_pad="0" -  width="238" -  name="layout_panel_2"> +    <panel +     follows="right|top" +     height="126" +     top_pad="4" +     width="238" +     left="1" +     name="layout_panel_2">  <button       follows="right|top"       height="22" @@ -690,4 +746,6 @@       show_text="false"       width="200" />       </panel> +      </layout_panel> +    </layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index ef4f19cd4c..fceb9b2184 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -85,6 +85,8 @@       use_ellipses="true" />       <text       follows="left|top|right" +     trusted_content="false" +     always_show_icons="true"       height="35"       left="8"       name="user_details" diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index 26b1c86c53..3b91b9df7a 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -33,6 +33,13 @@           function="Object.EnableTouch"           name="EnableTouch"/>      </menu_item_call> +    <menu_item_call +     label="Show in inventory" +     layout="topleft" +     name="Show original"> +      <menu_item_call.on_click +       function="Object.ShowOriginal" /> +    </menu_item_call>      <menu_item_separator       layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml index 500b6fffc2..20f3ad080b 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -290,4 +290,11 @@      <menu_item_call.on_visible       function="EnableMuteParticle" />    </menu_item_call> +  <menu_item_separator/> +  <menu_item_call label="View Profile" +       layout="topleft" +       name="show_avatar_profile"> +    <menu_item_call.on_click +     function="Avatar.ToggleMyProfile" /> +  </menu_item_call>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml new file mode 100644 index 0000000000..4c12180daf --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_color.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Color Menu"> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="params_copy" +     visible="true"> +       <on_click function="PanelFace.menuDoToSelected" parameter="color_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="params_paste" +     visible="true"> +       <on_click function="PanelFace.menuDoToSelected" parameter="color_paste" /> +       <on_enable function="PanelFace.menuEnable" parameter="color_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml new file mode 100644 index 0000000000..4823d74a26 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_features.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Features Menu"> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="params_copy" +     visible="true"> +       <on_click function="PanelVolume.menuDoToSelected" parameter="features_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="params_paste" +     visible="true"> +       <on_click function="PanelVolume.menuDoToSelected" parameter="features_paste" /> +       <on_enable function="PanelVolume.menuEnable" parameter="features_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml new file mode 100644 index 0000000000..5de23dfee3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_light.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Light Menu"> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="params_copy" +     visible="true"> +       <on_click function="PanelVolume.menuDoToSelected" parameter="light_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="params_paste" +     visible="true"> +       <on_click function="PanelVolume.menuDoToSelected" parameter="light_paste" /> +       <on_enable function="PanelVolume.menuEnable" parameter="light_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml new file mode 100644 index 0000000000..bdc4537a9d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_object.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Object Menu"> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="params_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="params_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="params_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="params_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="params_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml new file mode 100644 index 0000000000..3ea95b281f --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_pos.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Position Menu"> +    <menu_item_call +     label="Copy all" +     layout="topleft" +     name="psr_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> +       <on_enable function="PanelObject.menuEnable" parameter="psr_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Copy position" +     layout="topleft" +     name="pos_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="pos_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste all" +     layout="topleft" +     name="psr_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> +    </menu_item_call> +    <menu_item_call +     label="Paste position" +     layout="topleft" +     name="pos_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="pos_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="pos_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml new file mode 100644 index 0000000000..06ce80f897 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_rot.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Rotation Menu"> +    <menu_item_call +     label="Copy all" +     layout="topleft" +     name="psr_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> +       <on_enable function="PanelObject.menuEnable" parameter="rot_paste" /> +    </menu_item_call> +    <menu_item_call +     label="Copy rotation" +     layout="topleft" +     name="rot_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="rot_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste all" +     layout="topleft" +     name="psr_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> +    </menu_item_call> +    <menu_item_call +     label="Paste rotation" +     layout="topleft" +     name="rot_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="rot_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="rot_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml new file mode 100644 index 0000000000..7082a0e65b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_size.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Size Menu"> +    <menu_item_call +     label="Copy all" +     layout="topleft" +     name="psr_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" /> +       <on_enable function="PanelObject.menuEnable" parameter="psr_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Copy size" +     layout="topleft" +     name="size_copy" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="size_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste all" +     layout="topleft" +     name="psr_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="psr_paste" /> +    </menu_item_call> +    <menu_item_call +     label="Paste size" +     layout="topleft" +     name="size_paste" +     visible="true"> +       <on_click function="PanelObject.menuDoToSelected" parameter="size_paste" /> +       <on_enable function="PanelObject.menuEnable" parameter="size_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml new file mode 100644 index 0000000000..f358affc23 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_copy_paste_texture.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Copy Paste Texture Menu"> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="params_copy" +     visible="true"> +       <on_click function="PanelFace.menuDoToSelected" parameter="texture_copy" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="params_paste" +     visible="true"> +       <on_click function="PanelFace.menuDoToSelected" parameter="texture_paste" /> +       <on_enable function="PanelFace.menuEnable" parameter="texture_paste" /> +    </menu_item_call> +</toggleable_menu> + diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml index 5cae643e44..359c093eff 100644 --- a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml @@ -9,7 +9,7 @@       layout="topleft"       name="activate">          <on_click -         function="Gesture.Action.ToogleActiveState" /> +         function="Gesture.Action.ToggleActiveState" />      </menu_item_call>      <menu_item_call       label="Rename" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 67bcbe020b..c7c1e1d75a 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -923,6 +923,25 @@                  function="Inventory.DoToSelected"                  parameter="apply_settings_parcel" />      </menu_item_call> +  <menu_item_separator +   layout="topleft" +   name="Subfolder Separator" /> +  <menu_item_call +   label="Create folder from selected" +   layout="topleft" +   name="New folder from selected"> +    <menu_item_call.on_click +     function="Inventory.DoToSelected" +     parameter="new_folder_from_selected" /> +  </menu_item_call> +  <menu_item_call +   label="Ungroup folder items" +   layout="topleft" +   name="Ungroup folder items"> +    <menu_item_call.on_click +     function="Inventory.DoToSelected" +     parameter="ungroup_folder_items" /> +  </menu_item_call>  	<menu_item_separator  	 layout="topleft"  	 name="Marketplace Separator" /> diff --git a/indra/newview/skins/default/xui/en/menu_profile_other.xml b/indra/newview/skins/default/xui/en/menu_profile_other.xml new file mode 100644 index 0000000000..4db4d0922b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_profile_other.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Avatar Profile Menu"> +  <menu_item_call +   label="IM" +   layout="topleft" +   name="im"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="im"/> +  </menu_item_call> +  <menu_item_call +  label="Offer Teleport" +  name="offer_teleport"> +    <menu_item_call.on_click +     function="Profile.Commit" +    parameter="offer_teleport"/> +    <menu_item_call.on_enable +    function="Profile.EnableItem" +    parameter="offer_teleport"/> +  </menu_item_call> +  <menu_item_call +  label="Request Teleport" +  name="request_teleport"> +    <menu_item_call.on_click +     function="Profile.Commit" +    parameter="request_teleport"/> +    <menu_item_call.on_enable +    function="Profile.EnableItem" +    parameter="request_teleport"/> +  </menu_item_call> +  <menu_item_call +   label="Voice call" +   layout="topleft" +   name="voice_call"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="voice_call"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="voice_call"/> +  </menu_item_call> +  <menu_item_separator /> +  <menu_item_call +   label="View chat history..." +   layout="topleft" +   name="chat_history"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="chat_history"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="chat_history"/> +  </menu_item_call> +  <menu_item_separator name="separator_chat_history"/> +  <menu_item_call +   label="Add Friend" +   layout="topleft" +   name="add_friend"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="add_friend"/> +    <menu_item_call.on_visible +     function="Profile.EnableItem" +     parameter="add_friend"/> +  </menu_item_call> +  <menu_item_call +   label="Remove Friend" +   layout="topleft" +   name="remove_friend"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="remove_friend"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="remove_friend"/> +  </menu_item_call> +  <menu_item_call +   label="Invite to group..." +   layout="topleft" +   name="invite_to_group"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="invite_to_group"/> +  </menu_item_call> +  <menu_item_separator name="separator_invite_to_group"/> +  <menu_item_call +   label="Permissions" +   layout="topleft" +   name="agent_permissions"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="agent_permissions"/> +    <menu_item_call.on_visible +     function="Profile.EnableItem" +     parameter="agent_permissions"/> +  </menu_item_call> +  <menu_item_call +   label="Map" +   layout="topleft" +   name="map"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="can_show_on_map"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="can_show_on_map"/> +  </menu_item_call> +  <menu_item_call +   label="Share" +   layout="topleft" +   name="share"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="share"/> +  </menu_item_call> +  <menu_item_call +   label="Pay" +   layout="topleft" +   name="pay"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="pay"/> +  </menu_item_call> +  <menu_item_check +   label="Block/Unblock" +   layout="topleft" +   name="block_unblock"> +    <menu_item_check.on_click +     function="Profile.Commit" +     parameter="toggle_block_agent"/> +    <menu_item_check.on_check +     function="Profile.CheckItem" +     parameter="toggle_block_agent"/> +    <menu_item_check.on_enable +     function="Profile.EnableItem" +     parameter="toggle_block_agent"/> +  </menu_item_check> +  <menu_item_separator name="separator_copy_options"/> +  <menu_item_call +   label="Copy Display Name" +   layout="topleft" +   name="copy_display_name"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_display_name"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="copy_display_name"/> +  </menu_item_call> +  <menu_item_call +   label="Copy Agent Name" +   layout="topleft" +   name="copy_name"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_username"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="copy_username"/> +  </menu_item_call> +  <menu_item_call +   label="Copy Agent Id" +   layout="topleft" +   name="copy_id"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_user_id"/> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_profile_self.xml b/indra/newview/skins/default/xui/en/menu_profile_self.xml new file mode 100644 index 0000000000..d0bd4000f8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_profile_self.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Avatar Profile Menu Self"> +  <menu_item_call +   label="Edit Display Name" +   layout="topleft" +   name="edit_display_name"> +    <on_click +     function="Profile.Commit" +     parameter="edit_display_name"/> +  </menu_item_call> +  <menu_item_call +   label="Edit Partner" +   layout="topleft" +   name="edit_partner"> +    <on_click +     function="Profile.Commit" +     parameter="edit_partner"/> +  </menu_item_call> +  <menu_item_call +   label="Upload Photo" +   layout="topleft" +   name="upload_photo"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="upload_photo"/> +    <menu_item_call.on_enable +    function="Profile.EnableItem" +     parameter="upload_photo"/> +  </menu_item_call> +  <menu_item_call +   label="Change Photo" +   layout="topleft" +   name="change_photo"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="change_photo"/> +    <menu_item_call.on_enable +    function="Profile.EnableItem" +     parameter="change_photo"/> +  </menu_item_call> +  <menu_item_call +   label="Remove Photo" +   layout="topleft" +   name="remove_photo"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="remove_photo"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="remove_photo"/> +  </menu_item_call> +  <menu_item_separator name="separator_copy_options"/> +  <menu_item_call +   label="Copy Display Name" +   layout="topleft" +   name="copy_display_name"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_display_name"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="copy_display_name"/> +  </menu_item_call> +  <menu_item_call +   label="Copy Agent Name" +   layout="topleft" +   name="copy_name"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_username"/> +    <menu_item_call.on_enable +     function="Profile.EnableItem" +     parameter="copy_username"/> +  </menu_item_call> +  <menu_item_call +   label="Copy Agent Id" +   layout="topleft" +   name="copy_id"> +    <menu_item_call.on_click +     function="Profile.Commit" +     parameter="copy_user_id"/> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index d3b13bfc2a..eb4f9f16fa 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -47,8 +47,7 @@         label="Picks..."         name="Picks">          <menu_item_call.on_click -         function="Floater.ToggleOrBringToFront" -         parameter="picks" /> +         function="ShowAgentProfilePicks" />        </menu_item_call>        <menu_item_call          label="Experiences..." @@ -2465,20 +2464,6 @@ function="World.EnvPreset"                 function="Advanced.ToggleConsole"                 parameter="scene monitor" />              </menu_item_check> -            <menu_item_call -              enabled="false" -              visible="false" -              label="Texture Fetch Debug Console" -              name="Texture Fetch Debug Console"> -              <menu_item_call.on_click -                function="Floater.Show" -                parameter="tex_fetch_debugger" /> -              <on_enable -                function="Develop.SetTexFetchDebugger" /> -              <on_visible -                function="Develop.SetTexFetchDebugger" /> -            </menu_item_call> -                        <menu_item_separator/>              <menu_item_call @@ -3120,18 +3105,6 @@ function="World.EnvPreset"            <menu_item_separator />            <menu_item_check -                       label="Advanced Lighting Model" -                       name="Advanced Lighting Model"> -            <menu_item_check.on_check -             function="CheckControl" -             parameter="RenderDeferred" /> -            <menu_item_check.on_click -             function="ToggleControl" -             parameter="RenderDeferred" /> -            <menu_item_check.on_enable -                 function="Advanced.EnableRenderDeferred" /> -          </menu_item_check> -          <menu_item_check                         label="   Shadows from Sun/Moon/Projectors"                         name="Shadows from Sun/Moon/Projectors">              <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index ae4b0538d8..d2a35241ba 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1496,7 +1496,19 @@ Insufficient funds to create classified.    <notification     icon="alertmodal.tga" -   name="DeleteAvatarPick" +   name="ProfileDeleteClassified" +   type="alertmodal"> +Delete classified <nolink>[CLASSIFIED]</nolink>? +    <tag>confirm</tag> +    <usetemplate +     name="okcancelbuttons" +     notext="Cancel" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="ProfileDeletePick"     type="alertmodal">  Delete pick <nolink>[PICK]</nolink>?      <tag>confirm</tag> @@ -1507,6 +1519,32 @@ Delete pick <nolink>[PICK]</nolink>?    </notification>    <notification +   icon="alert.tga" +   name="ProfileUnpublishedClassified" +   type="alert"> +    You have unpublished classifieds. They will be lost if you close the window. +    <tag>confirm</tag> +    <usetemplate +     name="okcancelbuttons" +     notext="Cancel" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alert.tga" +   name="ProfileUnsavedChanges" +   type="alert"> +    You have usaved changes. +    <tag>confirm</tag> +    <tag>save</tag> +    <usetemplate +     canceltext="Cancel" +     name="yesnocancelbuttons" +     notext="Discard" +     yestext="Save"/> +  </notification> + +  <notification     icon="alertmodal.tga"     name="DeleteOutfits"     type="alertmodal"> @@ -9122,6 +9160,29 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran    <notification     icon="alertmodal.tga" +   name="FacePasteFailed" +   type="alertmodal"> +Paste failed. [REASON] +   <usetemplate +    name="okbutton" +    yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="FacePasteTexturePermissions" +   type="alertmodal"> +    You applied a texture with limited permissions, object will inherit permissions from texture. +    <usetemplate +     ignoretext="Paste: You applied a texture with limited permissions" +     name="notifyignore"/> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="ConfirmLeaveCall"     type="alertmodal">  Are you sure you want to leave this call? @@ -9781,6 +9842,15 @@ Attempt cancelled.    <notification     icon="alertmodal.tga" +   name="LocalGLTFVerifyFail" +   persist="true" +   type="notify"> +Attempted to add an invalid or unreadable GLTF material [FNAME] which could not be opened or decoded. +Attempt cancelled. +  </notification> + +  <notification +   icon="alertmodal.tga"     name="PathfindingReturnMultipleItems"     type="alertmodal">      You are returning [NUM_ITEMS] items.  Are you sure you want to continue? @@ -11722,7 +11792,7 @@ This Region does not support environmental settings.    <notification     icon="alertmodal.tga" -   label="Save Outfit" +   label="Save Environmental Settings"     name="SaveSettingAs"     type="alertmodal">      <unique/> @@ -11901,6 +11971,40 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB      </form>    </notification> +  <notification +   icon="alertmodal.tga" +   label="Create subfolder" +   name="CreateSubfolder" +   type="alertmodal"> +    <unique/> +    Name the new folder: +    <tag>confirm</tag> +    <form name="form"> +      <input name="message" type="text"> +        [DESC] +      </input> +      <button +       default="true" +       index="0" +       name="OK" +       text="OK"/> +      <button +       index="1" +       name="Cancel" +       text="Cancel"/> +    </form> +  </notification> +  <notification +   icon="alertmodal.tga" +   name="SameFolderRequired" +   type="alert"> +    Selected items must be in the same folder. +    <tag>fail</tag> +    <usetemplate +      name="okbutton" +      yestext="OK"/> +  </notification> +  <notification   icon="notifytip.tga"   name="MaterialCreated" diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml index d4a2745d1d..04a0bc800d 100644 --- a/indra/newview/skins/default/xui/en/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -38,28 +38,15 @@    name="auto_renew_off">      Disabled   </panel.string> -    <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back_btn" -     left="10" -     tab_stop="false" -     top="2" -     width="30" -     use_draw_context_alpha="false" />      <text       follows="top|left|right"       font="SansSerifHugeBold"       height="26"       layout="topleft" -     left_pad="4" +     left="12"       name="title"       text_color="LtGray" -     top="0" +     top="2"       value="Classified Info"       use_ellipses="true"       width="275" /> @@ -420,7 +407,7 @@  		         height="23"  		         label="Teleport"  		         layout="topleft" -		         left="0" +		         left="2"  		         name="teleport_btn"  		         top="0"  		         width="101" />	 @@ -443,24 +430,6 @@  		         top="0"  		         width="100" />  		  </layout_panel>	   -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left_pad="3" -			  name="edit_btn_lp" -		      auto_resize="true" -			  width="101"> -			  <button -		         follows="bottom|left|right" -		         height="23" -		         label="Edit" -		         layout="topleft" -		         name="edit_btn" -		         top="0" -		         width="101" /> -		  </layout_panel>  	   </layout_stack>      </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml deleted file mode 100644 index e846edf1d4..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ /dev/null @@ -1,354 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - bevel_style="in" - follows="left|top|right|bottom" - height="569" - label="Edit Classified" - layout="topleft" - left="0" - min_height="350" - name="panel_edit_classified" - help_topic="profile_edit_classified" - top="0" - width="333"> - <panel.string -  name="location_notice"> -    (will update after save) - </panel.string> - <string name="publish_label"> -  Publish - </string> - <string name="save_label"> -  Save - </string> -  <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back_btn" -     left="10" -     tab_stop="false" -     top="2" -     width="30" -     use_draw_context_alpha="false" /> -   <text -     type="string" -     length="1" -     follows="top" -     font="SansSerifHugeBold" -     height="26" -     layout="topleft" -     left_pad="4" -     name="title" -     text_color="LtGray" -     top="0" -     width="250"> -        Edit Classified -    </text> -   <scroll_container -    color="DkGray2" -    follows="all" -    height="502" -    layout="topleft" -    left="8" -    top_pad="10" -    name="profile_scroll" -    reserve_scroll_corner="false" -    opaque="true" -    width="312"> -    <panel -     name="scroll_content_panel" -     follows="left|top" -     min_height="300" -     layout="topleft" -     top="0" -     background_visible="false" -     height="690" -     left="0" -     width="285"> -      <panel -         name="snapshot_panel" -         layout="topleft" -         follows="left|top|right" -         height="197" -         left="10" -         top="10" -         width="272"> -      <texture_picker -       fallback_image="default_land_picture.j2c" -       follows="left|top|right" -       height="197" -       width="272" -       layout="topleft" -       top="0" -       left="0" -       name="classified_snapshot" /> -       <icon -           height="197" -           image_name="spacer24.tga" -           layout="topleft" -           name="edit_icon" -           label="" -           tool_tip="Click to select an image" -           top="0" -           left="0" -           width="272" /> -       </panel> -        <text -         type="string" -         length="1" -         follows="left|top" -         height="15" -         font="SansSerifSmall" -         font.style="BOLD" -         layout="topleft" -         left="10" -         top="215" -         name="Name:" -         text_color="white" -         width="280"> -            Title: -        </text> -        <line_editor -         follows="left|top|right" -         font="SansSerif" -         height="20" -         layout="topleft" -         left="10" -         top_pad="2" -         max_length_bytes="30" -         name="classified_name" -         prevalidate_callback="ascii" -         text_color="black" -         width="273" /> -        <text -         type="string" -         length="1" -         follows="left|top" -         height="15" -         font="SansSerifSmall" -         font.style="BOLD" -         layout="topleft" -         left="10" -         top_pad="20" -         name="description_label" -         text_color="white" -         width="280"> -            Description: -        </text> -        <text_editor -         follows="left|top|right" -         height="100" -         width="273" -         layout="topleft" -         left="10" -         top_pad="2" -         max_length="256" -         name="classified_desc" -         text_color="black" -         word_wrap="true" /> -        <text -         type="string" -         length="1" -         font="SansSerifSmall" -         font.style="BOLD" -         follows="left|top" -         height="15" -         layout="topleft" -         left="10" -         name="location_label" -         text_color="white" -         top_pad="20" -         width="280"> -            Location: -        </text> -        <text -         type="string" -         length="1" -         follows="left|top" -         height="30" -         layout="topleft" -         left="10" -         name="classified_location" -         right="-10" -         top_pad="2" -         width="280" -         word_wrap="true"> -            loading... -        </text> -        <button -         follows="left|top" -         height="23" -         label="Set to Current Location" -         layout="topleft" -         left="10" -         top_pad="5" -         name="set_to_curr_location_btn" -         width="200" /> -        <text -         follows="left|top" -         font.style="BOLD" -         height="10" -         layout="topleft" -         left="10" -         name="category_label" -         text_color="white" -         top_pad="15" -         value="Category:" -         width="250" /> -        <combo_box -         follows="left|top"  -         height="23"  -         label="" -	     left="10"  -         name="category"  -         top_pad="5" -         width="156" /> -        <text -         follows="left|top" -         font.style="BOLD" -         height="10" -         layout="topleft" -         left="10" -         name="content_type_label" -         text_color="white" -         top_pad="15" -         value="Content type:" -         width="250" /> -        <icons_combo_box -         follows="left|top" -         height="23" -         label="General Content" -         layout="topleft" -         left="10" -         name="content_type" -         top_pad="5" -         width="156"> -            <icons_combo_box.drop_down_button -             image_overlay="Parcel_PG_Light" -             image_overlay_alignment="left" -             imgoverlay_label_space="3" -             pad_left="3"/> -            <icons_combo_box.item -             label="Moderate Content" -             name="mature_ci" -             value="Mature"> -                <item.columns -                 halign="center" -                 type="icon" -                 value="Parcel_M_Light" -                 width="20"/> -            </icons_combo_box.item> -            <icons_combo_box.item -             label="General Content" -             name="pg_ci" -             value="PG"> -                <item.columns -                 halign="center" -                 type="icon" -                 value="Parcel_PG_Light" -                 width="20"/> -            </icons_combo_box.item> -        </icons_combo_box> -        <check_box -         height="16" -         label="Auto renew each week" -         layout="topleft" -         left="10" -         name="auto_renew" -         top_pad="15" -         width="250" /> -        <text -         follows="left|top" -         height="10" -         layout="topleft" -         left="10" -         name="price_for_listing_label" -         text_color="white" -         top_pad="15" -         value="Price for listing:" -         width="250" /> -        <spinner -         decimal_digits="0" -         follows="left|top" -         halign="left" -         height="23" -         increment="1" -         label_width="20" -         label="L$" -         v_pad="10" -         layout="topleft" -         left="10" -         value="50" -         min_val="50" -         max_val="99999" -         name="price_for_listing" -         top_pad="5" -         tool_tip="Price for listing." -         width="105" /> -     </panel> -    </scroll_container> -    <panel -     follows="left|right|bottom" -     height="23" -     label="bottom_panel" -     layout="topleft" -     left="8" -     name="bottom_panel" -     top_pad="5" -     width="303"> -      -         <layout_stack -		  follows="bottom|left|right" -		  height="23" -		  layout="topleft" -		  name="bottom_panel_ls" -		  left="1" -		  orientation="horizontal" -		  top_pad="0" -		  width="309"> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left="0" -			  name="save_changes_btn_lp" -		      auto_resize="true" -			  width="156"> -			  <button -		         follows="bottom|left|right" -		         height="23" -		         label="[LABEL]" -		         layout="topleft" -		         name="save_changes_btn" -		         left="1" -		         top="0" -		         width="155" />	 -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left_pad="3" -			  name="show_on_map_btn_lp" -		      auto_resize="true" -			  width="157"> -			  <button -		         follows="bottom|left|right" -		         height="23" -		         label="Cancel" -		         layout="topleft" -		         name="cancel_btn" -		         left="1" -		         top="0" -		         width="156" /> -		  </layout_panel> -	   </layout_stack> -    </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml deleted file mode 100644 index 357a5559bf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ /dev/null @@ -1,239 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - bevel_style="in" - follows="left|top|right|bottom" - height="569" - label="Edit Pick" - layout="topleft" - left="0" - min_height="350" - name="panel_edit_pick" - help_topic="profile_edit_pick" - top="0" - width="333"> - <panel.string -  name="location_notice"> -    (will update after save) - </panel.string> -  <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back_btn" -     left="10" -     tab_stop="false" -     top="4" -     width="30" -     use_draw_context_alpha="false" /> -   <text -     type="string" -     length="1" -     follows="top" -     font="SansSerifHugeBold" -     height="26" -     layout="topleft" -     left_pad="4" -     name="title" -     text_color="LtGray" -     top="4" -     width="250"> -        Edit Pick -    </text> -   <scroll_container -     color="DkGray2" -     follows="all" -     height="501" -     layout="topleft" -     left="8" -     top_pad="9" -     name="profile_scroll" -     opaque="true" -     width="312"> -    <panel -     name="scroll_content_panel" -     follows="left|top|right" -     min_height="300" -     layout="topleft" -     top="0" -     background_visible="false" -     height="500" -     left="0" -     width="285"> -    <texture_picker -     fallback_image="default_land_picture.j2c" -     follows="left|top|right" -     height="197" -     width="272" -     layout="topleft" -     no_commit_on_selection="true" -     top="10" -     left="11" -     name="pick_snapshot" /> -          <icon -           height="197" -           image_name="spacer24.tga" -           layout="topleft" -           name="edit_icon" -           label="" -           tool_tip="Click to select an image" -           top="10" -           left="11" -           width="286" /> -        <text -         type="string" -         length="1" -         follows="left|top|right" -         height="15" -         font="SansSerifSmall" -         font.style="BOLD" -         layout="topleft" -         left="10" -         top="215" -         name="Name:" -         text_color="white" -         width="280"> -            Title: -        </text> -        <line_editor -         follows="left|top|right" -         font="SansSerif" -         height="20" -         layout="topleft" -         left="10" -         top_pad="2" -         max_length_bytes="63" -         name="pick_name" -         text_color="black" -         width="273" /> -        <text -         type="string" -         length="1" -         follows="left|top|right" -         height="15" -         font="SansSerifSmall" -         font.style="BOLD" -         layout="topleft" -         left="10" -         top_pad="20" -         name="description_label" -         text_color="white" -         width="280"> -            Description: -        </text> -        <text_editor -         follows="left|top|right" -         height="100" -         width="273" -         hide_scrollbar="false" -         layout="topleft" -         left="10" -         top_pad="2" -         max_length="1023" -         name="pick_desc" -         spellcheck="true" -         text_color="black" -         word_wrap="true" /> -        <text -         type="string" -         length="1" -         font="SansSerifSmall" -         font.style="BOLD" -         follows="left|top|right" -         height="15" -         layout="topleft" -         left="10" -         name="location_label" -         text_color="white" -         top_pad="20" -         width="280"> -            Location: -        </text> -        <text -         type="string" -         length="1" -         follows="left|top|right" -         height="50" -         layout="topleft" -         left="10" -         name="pick_location" -         top_pad="2" -         width="280" -         word_wrap="true"> -            loading... -        </text> -        <button -         follows="left|top" -         height="23" -         label="Set to Current Location" -         layout="topleft" -         left="8" -         top_pad="0" -         name="set_to_curr_location_btn" -         width="200" /> -    </panel> -    </scroll_container> -    <panel -     follows="left|right|bottom" -     height="23" -     label="bottom_panel" -     layout="topleft" -     left="8" -     name="bottom_panel" -     top_pad="5" -     width="315"> -      -     	 <layout_stack -		  follows="bottom|left|right" -		  height="23" -		  layout="topleft" -		  name="layout_stack1" -		  left="0" -		  orientation="horizontal" -		  top_pad="0" -		  width="313"> -		  	  -		  	 <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="topleft" -			  left="0" -			  name="layout_panel1" -		      auto_resize="true" -			  width="150"> -		        <button -		         follows="bottom|left|right" -		         height="23" -		         label="Save Pick" -		         layout="topleft" -		         name="save_changes_btn" -		         top="0" -		         left="1" -		         width="149" /> -			  </layout_panel> -			   -			 <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="topleft" -			  left_pad="4" -			  name="layout_panel2" -		      auto_resize="true" -			  width="146"> -		        <button -		         follows="bottom|left|right" -		         height="23" -		         label="Cancel" -		         layout="topleft" -		         name="cancel_btn" -		         top="0" -		         left="1" -		        width="145" /> -			  </layout_panel> -	</layout_stack> -		   -    </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml deleted file mode 100644 index 2c7c8133d1..0000000000 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ /dev/null @@ -1,472 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - class="edit_profile_panel" -  follows="all" - height="585" - label="Profile Edit" - layout="topleft" - left="0" - name="edit_profile_panel" -  top="0" - width="313"> -   <string -    name="CaptionTextAcctInfo"> -       [ACCTTYPE] -[PAYMENTINFO] [AGEVERIFICATION] -   </string> -   <string  -    name="RegisterDateFormat"> -	[REG_DATE] ([AGE]) -   </string>  -   <string -    name="AcctTypeResident" -    value="Resident" /> -   <string -    name="AcctTypeTrial" -    value="Trial" /> -   <string -    name="AcctTypeCharterMember" -    value="Charter Member" /> -   <string -    name="AcctTypeEmployee" -    value="Linden Lab Employee" /> -   <string -    name="PaymentInfoUsed" -    value="Payment Info Used" /> -   <string -    name="PaymentInfoOnFile" -    value="Payment Info On File" /> -   <string -    name="NoPaymentInfoOnFile" -    value="No Payment Info On File" /> -   <string -    name="AgeVerified" -    value="Age-verified" /> -   <string -    name="NotAgeVerified" -    value="Not Age-verified" /> -   <string -    name="partner_edit_link_url"> -       http://www.secondlife.com/account/partners.php?lang=en -   </string> -   <string -    name="my_account_link_url"> -       http://secondlife.com/my -   </string> -   <string -    name="no_partner_text" -    value="None" /> - <scroll_container -     color="DkGray2" -     follows="all" -     height="537" -     min_height="300" -     layout="topleft" -     left="8" -     width="292" -     name="profile_scroll" -     reserve_scroll_corner="true" -     opaque="true" -     top="10"> -      <panel -         name="scroll_content_panel" -         follows="left|top|right" -         layout="topleft" -         top="0" -     height="537" -     min_height="300" -         left="0" -         width="292"> -    <panel -     name="data_panel" -     follows="left|top|right" -         layout="topleft" -         top="0" -     height="537" -     min_height="300" -         left="0" -         width="292"> -      <text -     top="5" -     follows="top|left" -     height="13" -     layout="topleft" -     left="10" -     name="display_name_label" -     text_color="LtGray" -     value="Display Name:" -     width="80" /> -      <text -     top="5" -     follows="top|left" -     height="13" -     layout="topleft" -     left="10" -     name="solo_username_label" -     text_color="LtGray" -     value="Username:" -     visible="false"  -     width="80" /> -      <button -         name="set_name" -         layout="topleft" -         follows="top|left" -         image_overlay="Edit_Wrench" -         top="21" -         left="10" -         height="23" -         width="23" -         tool_tip="Set Display Name"/> -      <text -       follows="top|left" -       font="SansSerifBigBold" -       height="20" -       layout="topleft" -       left="10" -       name="solo_user_name" -       text_color="white" -       top_delta="3" -       translate="false" -       value="TestString PleaseIgnore" -       use_ellipses="true" -       visible="false" -       width="275" /> -      <text -       follows="top|left" -       font="SansSerifBigBold" -       height="20" -       layout="topleft" -       left="43" -       name="user_name" -       text_color="white" -       top_delta="0" -       translate="false" -       value="TestString PleaseIgnore" -       use_ellipses="true" -       visible="true" -       width="250" /> -      <text -       follows="top|left" -       font="SansSerifBold" -       height="20" -       layout="topleft" -       left_delta="0" -       name="user_name_small" -       text_color="white" -       top_delta="-4" -       translate="false" -       value="TestString PleaseIgnore" -       use_ellipses="true" -       visible="false" -       wrap="true" -       width="245" /> -      <text -    follows="top|left" -    height="13" -    layout="topleft" -    left="10" -    name="user_label" -    text_color="LtGray" -    top_pad="8" -    value="Username:" -    width="70" /> -      <text -       follows="top|left" -       height="20" -       layout="topleft" -       left_pad="0" -       name="user_slid" -       text_color="EmphasisColor" -        font="SansSerifBold" -       top_delta="-2" -       translate="false" -       use_ellipses="true"  -       value="teststring.pleaseignore" -       wrap="true"  -       width="205" /> -     <panel -       name="lifes_images_panel" -         follows="left|top|right" -         height="244" -         layout="topleft" -         top="65" -         left="0" -         width="292"> -	 <panel -         follows="left|top" -         height="117" -         layout="topleft" -         left="10" -         name="second_life_image_panel" -         top="0" -         width="282"> -          <text -             follows="left|top|right" -	     font.style="BOLD" -             height="15" -             layout="topleft" -             left="0" -             top="10" -            name="second_life_photo_title_text" -             text_color="white" -             value="[SECOND_LIFE]:" -             width="100" /> -            <texture_picker -             allow_no_texture="true" -             default_image_name="None" -             enabled="false" -             fallback_image="default_profile_picture.j2c"  -             follows="top|left" -             height="124" -             layout="topleft" -             left="1" -             name="2nd_life_pic" -             top_pad="0" -             width="102" /> -          </panel> -           <icon -           height="102" -           image_name="spacer24.tga" -           layout="topleft" -           name="2nd_life_edit_icon" -           label="" -           left="11" -           top_pad="-92" -           tool_tip="Click to select an image" -           width="102" /> -      </panel> -      <text_editor -       type="string" -       length="1" -       follows="left|top|right" -       font="SansSerifSmall" -       height="102" -       layout="topleft" -       left="123" -       top="90" -       max_length="512" -       name="sl_description_edit" -       width="157" -       word_wrap="true"> -      </text_editor> -      <panel -         follows="left|top" -         height="117" -         layout="topleft" -	 top_pad="5" -         left="10" -         name="first_life_image_panel" -         width="285"> -        <text -             follows="left|top|right" -	     font.style="BOLD" -             height="15" -             layout="topleft" -             left="0" -             top_pad="10" -            name="real_world_photo_title_text" -             text_color="white" -             value="Real World:" -             width="100" /> -            <texture_picker -             allow_no_texture="true" -             default_image_name="None" -             enabled="false" -             fallback_image="Generic_Person_Large" -             follows="top|left" -             height="124" -             layout="topleft" -             left="1" -             name="real_world_pic" -             top_pad="0" -             width="102" /> -          </panel> -           <icon -           height="102" -           image_name="spacer24.tga" -           layout="topleft" -           name="real_world_edit_icon" -           label="" -           left="11" -           top_pad="-92" -           tool_tip="Click to select an image" -           width="102" /> -       <text_editor -       type="string" -       length="1" -       follows="left|top|right" -       font="SansSerifSmall" -       height="102" -       layout="topleft" -       left="123" -       max_length="512" -       top="223" -       name="fl_description_edit" -       width="157" -       word_wrap="true"> -      </text_editor> -      <text -       type="string" -       length="1" -       follows="left|top" -       font="SansSerifSmall" -       font.style="BOLD" -       height="15" -       layout="topleft" -       left="10" -       name="title_homepage_text" -       text_color="white" -       top_pad="10" -       width="100"> -          Homepage: -      </text> -      <line_editor -       follows="left|top|right" -       font="SansSerifSmall" -       height="20" -       layout="topleft" -       left="10" -       top_pad="0" -       value="http://" -       name="homepage_edit" -       width="272"> -      </line_editor> -      <text -         follows="left|top" -         font="SansSerifSmall" -	 font.style="BOLD" -         height="15" -         layout="topleft" -         left="10" -         name="title_acc_status_text" -         text_color="white" -         top_pad="10" -         value="My Account:" -         width="100" /> -        <text_editor -         allow_scroll="false" -         bg_visible="false" -         follows="left|top|right" -         h_pad="0" -         height="28" -         layout="topleft" -         left="10" -         name="acc_status_text" -         read_only="true" -         top_pad="5" -         v_pad="0" -         value="Resident. No payment info on file." -         width="200" -         word_wrap="true" /> -        <text -         type="string" -         follows="left|top" -         font="SansSerifSmall" -         height="15" -         layout="topleft" -         left="10" -         name="my_account_link" -         value="[[URL] Go to My Dashboard]" -         width="200" /> -        <text -         follows="left|top" -         font="SansSerifSmall" -      	 font.style="BOLD" -         height="15" -         layout="topleft" -         left="10" -         name="title_partner_text" -         text_color="white" -         top_pad="10" -         value="My Partner:" -         width="150" /> -        <panel -         follows="left|top|right" -         height="15" -         layout="topleft" -         left="10" -         name="partner_data_panel" -         width="200"> -          <text -           follows="left|top|right" -           height="12" -           initial_value="(retrieving)" -           layout="topleft" -           left="0" -           name="partner_text" -           top="0" -           use_ellipses="true" -           width="280"/> -         </panel> -        <text -         follows="left|top" -         height="15" -         layout="topleft" -           link="true" -         left="10" -         name="partner_edit_link" -         value="[[URL] Edit]" -         width="70" /> -    </panel> -    </panel> -    </scroll_container> -    <panel -       follows="bottom|left|right" -       height="28" -       left="0" -       name="profile_me_buttons_panel" -       top_pad="0" -       width="313"> -        -         <layout_stack -		  follows="bottom|left|right" -		  height="28" -		  layout="topleft" -		  name="bottom_panel_ls" -		  left="7" -		  orientation="horizontal" -		  top_pad="0" -		  width="295"> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  name="save_changes_btn_lp" -			  top="0" -		      auto_resize="true" -			  width="153"> -        <button -		         follows="bottom|left|right" -         height="23" -         label="Save Changes" -         layout="topleft" -		         left="1" -         name="save_btn" -		         top="0" -         width="152" /> -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left_pad="3" -			  name="show_on_map_btn_lp" -			  top="0" -		      auto_resize="true" -			  width="154"> -        <button -		         follows="bottom|left|right" -         height="23" -         label="Cancel" -         layout="topleft" -		         left="1" -         name="cancel_btn" -		         top="0" -         width="153" /> -		  </layout_panel> -	   </layout_stack> -    </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml new file mode 100644 index 0000000000..b72af7221e --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="group_list_item" + top="0" + left="0" + height="16" + width="320" + follows="top|right|left" + layout="topleft" +> +    <icon +     name="hovered_icon" +     top="0" +     left="0" +     height="16" +     width="320" +     follows="top|right|left" +     layout="topleft" +     image_name="ListItem_Over" +     visible="false" +    /> +    <icon +     name="selected_icon" +     top="0" +     left="0" +     height="16" +     width="320" +     follows="top|right|left" +     layout="topleft" +     image_name="ListItem_Select" +     visible="false" +    /> +    <group_icon +     name="group_icon" +     top="2" +     left="5" +     height="14" +     width="14" +     image_name="Generic_Group" +     mouse_opaque="true" +     use_draw_context_alpha="false" +    /> +    <text +     name="group_name" +     value="Unknown" +     top="2" +     left_pad="5" +     right="-2" +     height="16" +     follows="left|right" +     layout="topleft" +     parse_urls="false" +     text_color="ScrollUnselectedColor" +     use_ellipses="true" +    /> +    <button +     name="visibility_hide_btn" +     tool_tip="Hide group on my profile" +     top_delta="-3" +     left_pad="3" +     right="-53" +     height="20" +     width="20" +     follows="right" +     image_pressed="Profile_Group_Visibility_Off_Pressed" +     image_unselected="Profile_Group_Visibility_Off" +     tab_stop="false" +     visible="false" +    /> +    <button +     name="visibility_show_btn" +     tool_tip="Show group on my profile" +     top_delta="0" +     right_delta="0" +     height="20" +     width="20" +     follows="right" +     image_pressed="Profile_Group_Visibility_On_Pressed" +     image_unselected="Profile_Group_Visibility_On" +     tab_stop="false" +     visible="false" +    /> +    <button +     name="info_btn" +     tool_tip="More info" +     top_delta="2" +     left_pad="3" +     right="-30" +     height="16" +     width="16" +     follows="right" +     image_pressed="Info_Press" +     image_unselected="Info_Over" +     tab_stop="false" +    /> +    <!--*TODO: Should only appear on rollover--> +    <button +     name="profile_btn" +     tool_tip="View profile" +     top_delta="-2" +     left_pad="5" +     right="-3" +     height="20" +     width="20" +     follows="right" +     layout="topleft" +     image_overlay="Web_Profile_Off" +     tab_stop="false" +    /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_me.xml b/indra/newview/skins/default/xui/en/panel_me.xml deleted file mode 100644 index 23e7814cad..0000000000 --- a/indra/newview/skins/default/xui/en/panel_me.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - border="false" - follows="all" - height="570" - label="My Profile" - layout="topleft" - left="0" - name="panel_me" - top="0" - width="333"> -    <panel -        class="panel_picks" -        filename="panel_picks.xml" -        label="MY PICKS" -        help_topic="panel_my_picks_tab" -        name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml deleted file mode 100644 index 99c47eb825..0000000000 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ /dev/null @@ -1,190 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - follows="all" - height="570" - layout="topleft" - left="0" - min_height="350" - name="panel_pick_info" - help_topic="profile_pick_info" - top="0" - width="333"> -    <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back_btn" -     left="10" -     tab_stop="false" -     top="2" -     width="30" -     use_draw_context_alpha="false" /> -    <text -     follows="top|left|right" -     font="SansSerifHugeBold" -     height="26" -     layout="topleft" -     left_pad="4" -     name="title" -     text_color="LtGray" -     top="2" -     value="Pick Info" -     use_ellipses="true" -     width="275" /> -    <scroll_container -     color="DkGray2" -     opaque="true" -     follows="all" -     height="503" -     layout="topleft" -     left="8" -     top_pad="10" -     name="profile_scroll" -     width="312"> -    <panel -     name="scroll_content_panel" -     follows="left|top|right" -     min_height="300" -     layout="topleft" -     top="0" -     background_visible="false" -     height="400" -     left="0" -     width="285"> -        <texture_picker -         fallback_image="default_land_picture.j2c" -         enabled="false" -         follows="left|top|right" -         height="197" -         layout="topleft" -         left="11" -         name="pick_snapshot" -         top="10" -         width="272" /> -        <text_editor -         allow_scroll="false" -         bg_visible="false" -         follows="left|top|right" -         h_pad="0" -         height="35" -         width="280" -         layout="topleft" -         font="SansSerifBig" -         font.style="BOLD" -         left="10" -         top_pad="10" -         name="pick_name" -         read_only="true" -         text_color="white" -         v_pad="0" -         value="[name]" -         use_ellipses="true" /> -        <text_editor -         allow_scroll="false" -         bg_visible="false" -         follows="left|top|right" -         h_pad="0" -         height="25" -         layout="topleft" -         left="10" -         name="pick_location" -         read_only="true" -         width="280" -         word_wrap="true" -         v_pad="0" -         value="[loading...]" /> -        <text_editor -         bg_readonly_color="DkGray2" -         follows="all" -         height="100" -         width="280" -         parse_urls="true"	 -         layout="topleft" -         left="10" -         top_pad="2" -         max_length="1023" -         name="pick_desc" -         read_only="true" -         text_readonly_color="white" -         value="[description]" -         wrap="true" /> -    </panel> -    </scroll_container> -    <panel -     follows="left|right|bottom" -     height="23" -     layout="topleft" -     top_pad="5" -     left="8" -     name="buttons"> -        -       <layout_stack -		  follows="bottom|left|right" -		  height="23" -		  layout="topleft" -		  name="layout_stack1" -		  left="0" -		  orientation="horizontal" -		  top_pad="0" -		  width="312"> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left="0" -			  name="layout_panel1" -		      auto_resize="true" -			  width="101"> -			  <button -			  	 follows="bottom|left|right" -		         height="23" -		         label="Teleport" -		         layout="topleft" -		         name="teleport_btn" -		         top="0" -		         width="101" /> -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left_pad="3" -			  name="show_on_map_btn_lp" -		      auto_resize="true" -			  width="100"> -			  <button -		         follows="bottom|left|right" -		         height="23" -		         label="Map" -		         layout="topleft" -		         name="show_on_map_btn" -		         top_pad="0" -		         width="100" /> -		  </layout_panel>	   -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="23" -			  layout="bottomleft" -			  left_pad="3" -			  name="edit_btn_lp" -		      auto_resize="true" -			  width="101"> -			  <button -		         follows="bottom|left|right" -		         height="23" -		         label="Edit" -		         layout="topleft" -		         name="edit_btn" -		         top_pad="0" -		         width="101" /> -		  </layout_panel> -	   </layout_stack> -    </panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml deleted file mode 100644 index 8def96cada..0000000000 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ /dev/null @@ -1,227 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel -bg_opaque_color="DkGray2" -       background_visible="true" -       background_opaque="true" - follows="all" - height="571" - label="Picks" - layout="topleft" - left="8" - name="panel_picks" - top_pad="0" - width="313"> - <string -  name="no_picks" -  value="No Picks" /> - <string -  name="no_classifieds" -  value="No Classifieds" /> - <text -  type="string" -  follows="all" -  height="535" -  layout="topleft" -  left="6" -  name="picks_panel_text" -  wrap="true" -  top="10" -  width="313"/> - <accordion -  fit_parent="true"  -  follows="all" -  height="514" -  layout="topleft" -  left="0" -  name="accordion" -  top="0" -  single_expansion="true" -  width="313"> -    <accordion_tab -     layout="topleft" -     height="235" -     min_height="150" -     name="tab_picks" -     title="Picks" -     visible="false"> - <flat_list_view -         color="DkGray2" -         follows="all" -         layout="topleft" -         left="0" -         name="picks_list" -         opaque="true" -         top="0" -         width="313" /> -    </accordion_tab> -    <accordion_tab -     layout="topleft" -     height="235" -     name="tab_classifieds" -     title="Classifieds" -     visible="false"> -            <flat_list_view -             color="DkGray2" -             follows="all" -             layout="topleft" -             left="0" -             name="classifieds_list" -             opaque="true" -             top="0" -             width="313" /> -    </accordion_tab> - </accordion> -   <panel -       bg_opaque_color="DkGray2" -       background_visible="true" -       background_opaque="true" -       bevel_style="none" -       enabled="false" -       follows="bottom|left|right" -       left="1" -       height="27" -       label="bottom_panel" -       layout="topleft" -       name="edit_panel" -       top_pad="0" -       width="312"> -          -         <layout_stack -		  follows="bottom|left|right" -		  height="23" -		  layout="bottomleft" -		  name="edit_panel_ls" -		  left="10" -		  orientation="horizontal" -		  top_pad="0" -		  width="293"> -		   -		  <layout_panel -			  follows="bottom|left" -			  height="18" -			  layout="bottomleft" -			  left="0" -			  name="gear_menu_btn" -		      auto_resize="true" -			  width="51"> -				<button -	             follows="bottom|left" -	             height="18" -	             image_disabled="AddItem_Disabled" -	             image_selected="AddItem_Press" -	             image_unselected="AddItem_Off" -	             layout="topleft" -	             left="0" -	             name="new_btn" -	             tool_tip="Create a new pick or classified at the current location" -	             top="0" -	             width="18" /> -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|right" -			  height="18" -			  layout="bottomleft" -			  name="trash_btn_lp" -		      auto_resize="true" -			  width="18"> -				<button -	             follows="bottom|right" -	             height="18" -	             image_disabled="TrashItem_Disabled" -	             image_selected="TrashItem_Press" -	             image_unselected="TrashItem_Off" -	             layout="topleft" -	             name="trash_btn" -	             top="0" -	             width="18" /> -		  </layout_panel> -		   -	  </layout_stack> -	  </panel> -	   -	  <panel - bg_opaque_color="DkGray" -       background_visible="true" -       background_opaque="true" -         follows="bottom|left|right" -         layout="topleft" -         left="0" -         height="30" -         name="buttons_cucks" -         top_pad="0" -         width="313"> -       -      <layout_stack -		  follows="bottom|left|right" -		  height="28" -		  layout="topleft" -		  left="2" -		  name="buttons_cucks_ls" -		  orientation="horizontal" -		  top="0" -		  width="313"> -		  	   -		  <layout_panel -			  follows="bottom|left|right" -			  height="28" -			  layout="topleft" -			  left="0" -			  name="info_btn_lp" -		      auto_resize="true" -			  top="0" -			  width="95"> -		       <button -		         enabled="false" -		         follows="top|left|right" -		         height="23" -		         label="Info" -		         layout="topleft" -		         name="info_btn" -		         tab_stop="false" -		         tool_tip="Show pick information" -		         width="95" /> -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="28" -			  layout="bottomleft"  -			  left_pad="2" -			  name="teleport_btn_lp" -		      auto_resize="true" -			  width="117"> -		        <button -		         enabled="false" -		         follows="top|left|right" -		         height="23" -		         label="Teleport" -		         layout="topleft" -		         name="teleport_btn" -		         tab_stop="false" -		         tool_tip="Teleport to the corresponding area" -		         width="117" /> -		  </layout_panel> -		   -		  <layout_panel -			  follows="bottom|left|right" -			  height="28" -			  layout="bottomleft" -			  name="show_on_map_btn_lp" -		      auto_resize="true"  -			  left_pad="2" -			  width="90"> -		        <button -		         enabled="false" -		         follows="top|left|right" -		         height="23" -		         label="Map" -		         layout="topleft" -		         name="show_on_map_btn" -		         tab_stop="false" -		         tool_tip="Show the corresponding area on the World Map" -		         width="88" /> -		  </layout_panel> -	</layout_stack> -	</panel> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_classified.xml b/indra/newview/skins/default/xui/en/panel_profile_classified.xml new file mode 100644 index 0000000000..c9e8b242d4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classified.xml @@ -0,0 +1,830 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_classified" + top="0" + left="0" + height="420" + width="315" + follows="all" + layout="topleft" + help_topic="panel_profile_classified" + min_height="250" +> +    <panel.string +     name="type_mature" +    > +        Moderate +    </panel.string> +    <panel.string +     name="type_pg" +    > +        General Content +    </panel.string> +    <panel.string +     name="l$_price" +    > +        L$[PRICE] +    </panel.string> +    <panel.string +     name="click_through_text_fmt" +    > +        [TELEPORT] teleport, [MAP] map, [PROFILE] profile +    </panel.string> +    <panel.string +     name="date_fmt" +    > +        [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +    </panel.string> +    <panel.string +     name="auto_renew_on" +    > +        Enabled +    </panel.string> +    <panel.string +     name="auto_renew_off" +    > +        Disabled +    </panel.string> +    <panel.string +     name="location_notice" +    > +        (will update after save) +    </panel.string> +    <string +     name="publish_label" +    > +        Publish +    </string> +    <string +     name="save_label" +    > +        Save +    </string> + +  <layout_stack +   name="main_classifieds_stack" +   top="0" +   bottom="-1" +   left="0" +   width="310" +   follows="all" +   layout="topleft" +   orientation="vertical" +   animate="false" +    > +    <layout_panel +     follows="all" +     width="310" +     height="300" +     layout="topleft" +     name="scroll_layout_panel" +     auto_resize="true"> +      <scroll_container +       name="profile_scroll" +       top="0" +       left="0" +       height="300" +       width="310" +       follows="all" +       layout="topleft" +       color="DkGray2" +       opaque="true" +       reserve_scroll_corner="false" +      > +        <panel +         name="info_scroll_content_panel" +         top="0" +         left="0" +         height="562" +         width="280" +         follows="left|top|right" +         layout="topleft" +         background_visible="false" +         min_height="200" +        > +            <texture_picker +             name="classified_snapshot" +             enabled="false" +             top="0" +             left="10" +             height="161" +             width="260" +             follows="left|top" +             layout="topleft" +             fallback_image="default_land_picture.j2c" +            /> +            <icon +             name="edit_icon" +             label="" +             tool_tip="Click to select an image" +             top="0" +             left="0" +             height="161" +             width="260" +             layout="topleft" +             follows="left|top" +             image_name="spacer24.tga" +             visible="false" +            /> +            <layout_stack +             name="info_panel" +             top="145" +             left="0" +             height="375" +             width="310" +             follows="all" +             layout="topleft" +             visible="true" +             animate="false" +             orientation="vertical" +             > +                <layout_panel +                 name="main_info_panel" +                 top="0" +                 left="0" +                 height="160" +                 width="280" +                 follows="all" +                 layout="topleft" +                 auto_resize="false" +                    > +                    <text_editor +                     name="classified_name" +                     top="0" +                     left="10" +                     height="35" +                     width="270" +                     follows="left|top|right" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     font="SansSerifBig" +                     font.style="BOLD" +                     h_pad="0" +                     read_only="true" +                     text_color="white" +                     use_ellipses="true" +                     v_pad="0" +                     > +                        [name] +                    </text_editor> +                    <text +                     name="classified_location_label" +                     value="Location:" +                     top_pad="-2" +                     left="10" +                     height="10" +                     width="250" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="classified_location" +                     value="[loading...]" +                     top_pad="5" +                     left="10" +                     height="30" +                     width="280" +                     follows="left|top" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     read_only="true" +                     v_pad="0" +                     word_wrap="true" +                     /> +                    <text +                     name="content_type_label" +                     value="Content Type:" +                     top_pad="10" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <icon +                     name="content_type_moderate" +                     top_pad="-11" +                     left_pad="0" +                     height="16" +                     width="18" +                     follows="top|left" +                     layout="topleft" +                     image_name="Parcel_M_Light" +                     /> +                    <icon +                     name="content_type_general" +                     top_delta="0" +                     left_delta="0" +                     height="16" +                     width="18" +                     follows="top|left" +                     layout="topleft" +                     image_name="Parcel_PG_Light" +                     /> +                    <text_editor +                     name="content_type" +                     value="[content type]" +                     top_delta="1" +                     left_pad="2" +                     height="18" +                     width="130" +                     follows="left|top|right" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     read_only="true" +                     v_pad="0" +                     /> +                    <text +                     name="category_label" +                     value="Category:" +                     top_pad="0" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="category" +                     value="[category]" +                     top_pad="-10" +                     left_pad="0" +                     height="18" +                     width="150" +                     follows="left|top|right" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     parse_urls="true" +                     read_only="true" +                     v_pad="0" +                     /> +                    <text +                     name="creation_date_label" +                     value="Creation date:" +                     top_pad="0" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="creation_date" +                     value="[date]" +                     tool_tip="Creation date" +                     top_pad="-10" +                     left_pad="0" +                     height="16" +                     width="150" +                     follows="left|top" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     halign="left" +                     read_only="true" +                     v_pad="0" +                     /> +                    <text +                     name="price_for_listing_label" +                     value="Price for listing:" +                     top_pad="5" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="price_for_listing" +                     tool_tip="Price for listing." +                     top_pad="-10" +                     left_pad="0" +                     height="16" +                     width="105" +                     follows="left|top" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     halign="left" +                     read_only="true" +                     v_pad="0" +                     > +                     [PRICE] +                    </text_editor> +                </layout_panel> +                <layout_panel +                 name="clickthrough_layout_panel" +                 top="0" +                 left="0" +                 height="16" +                 width="290" +                 follows="all" +                 layout="topleft" +                 auto_resize="false" +                 > +                    <text +                     name="click_through_label" +                     value="Clicks:" +                     top_pad="0" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="click_through_text" +                     value="[clicks]" +                     tool_tip="Click through data" +                     top_pad="-10" +                     left_pad="0" +                     height="16" +                     width="150" +                     follows="left|top" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     halign="left" +                     read_only="true" +                     v_pad="0" +                     /> +                </layout_panel> +                <layout_panel +                 name="auto_renew_layout_panel" +                 top="0" +                 left="0" +                 height="16" +                 width="290" +                 follows="all" +                 layout="topleft" +                 auto_resize="false" +                 > +                    <text +                     name="auto_renew_label" +                     value="Auto renew:" +                     top="0" +                     left="10" +                     height="10" +                     width="140" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text +                     name="auto_renew" +                     value="Enabled" +                     top_pad="-10" +                     left_pad="0" +                     height="16" +                     width="150" +                     follows="top|left" +                     layout="topleft" +                     /> +                </layout_panel> +                <layout_panel +                 name="descr_layout_panel" +                 top="0" +                 left="0" +                 height="220" +                 width="290" +                 follows="all" +                 layout="topleft" +                 auto_resize="true" +                 > +                    <text +                     name="classified_desc_label" +                     value="Description:" +                     top="0" +                     left="10" +                     height="10" +                     width="250" +                     follows="left|top" +                     layout="topleft" +                     font.style="BOLD" +                     text_color="white" +                     /> +                    <text_editor +                     name="classified_desc" +                     trusted_content="false" +                     value="[description]" +                     top_pad="7" +                     left="10" +                     height="200" +                     width="280" +                     follows="all" +                     layout="topleft" +                     allow_scroll="false" +                     bg_visible="false" +                     h_pad="0" +                     max_length="1023" +                     parse_urls="true" +                     read_only="true" +                     v_pad="0" +                     word_wrap="true" +                     /> +                </layout_panel> +            </layout_stack> +            <panel +             name="edit_panel" +             top="145" +             left="0" +             height="420" +             width="320" +             follows="left|top|right" +             layout="topleft" +             visible="false" +            > +                <text +                 name="Name:" +                 top="0" +                 left="10" +                 height="15" +                 width="280" +                 follows="left|top" +                 layout="topleft" +                 font="SansSerifSmall" +                 font.style="BOLD" +                 length="1" +                 text_color="white" +                 type="string" +                > +                    Title: +                </text> +                <line_editor +                 name="classified_name_edit" +                 top_pad="2" +                 left="10" +                 height="20" +                 width="273" +                 follows="left|top|right" +                 layout="topleft" +                 font="SansSerif" +                 max_length_bytes="30" +                 prevalidate_callback="ascii" +                 commit_on_focus_lost="false" +                 text_color="black" +                /> +                <text +                 name="description_label" +                 top_pad="10" +                 left="10" +                 height="15" +                 width="280" +                 follows="left|top" +                 layout="topleft" +                 font="SansSerifSmall" +                 font.style="BOLD" +                 length="1" +                 text_color="white" +                 type="string" +                > +                    Description: +                </text> +                <text_editor +                 name="classified_desc_edit" +                 top_pad="2" +                 left="10" +                 height="100" +                 width="273" +                 follows="left|top|right" +                 layout="topleft" +                 max_length="256" +                 text_color="black" +                 word_wrap="true" +                /> +                <text +                 name="location_label" +                 top_pad="10" +                 left="10" +                 height="15" +                 width="280" +                 follows="left|top" +                 layout="topleft" +                 font="SansSerifSmall" +                 font.style="BOLD" +                 length="1" +                 text_color="white" +                 type="string" +                > +                    Location: +                </text> +                <text +                 name="classified_location_edit" +                 top_pad="2" +                 left="10" +                 right="-10" +                 height="30" +                 width="280" +                 follows="left|top" +                 layout="topleft" +                 length="1" +                 type="string" +                 word_wrap="true" +                > +                    loading... +                </text> +                <button +                 name="set_to_curr_location_btn" +                 label="Set to Current Location" +                 top_pad="5" +                 left="10" +                 height="23" +                 width="200" +                 follows="left|top" +                 layout="topleft" +                /> +                <text +                 name="category_label" +                 value="Category:" +                 top_pad="10" +                 left="10" +                 height="10" +                 width="120" +                 follows="left|top" +                 layout="topleft" +                 font.style="BOLD" +                 text_color="white" +                /> +                <combo_box +                 name="category_edit" +                 label="" +                 top_delta="-3" +                 left_pad="0" +                 height="23" +                 width="156" +                 follows="left|top" +                /> +                <text +                 name="content_type_label" +                 value="Content type:" +                 top_pad="15" +                 left="10" +                 height="10" +                 width="120" +                 follows="left|top" +                 layout="topleft" +                 font.style="BOLD" +                 text_color="white" +                /> +                <icons_combo_box +                 name="content_type_edit" +                 label="General Content" +                 top_delta="-3" +                 left_pad="0" +                 height="23" +                 width="156" +                 follows="left|top" +                 layout="topleft" +                > +                    <icons_combo_box.drop_down_button +                     image_overlay="Parcel_PG_Light" +                     image_overlay_alignment="left" +                     imgoverlay_label_space="3" +                     pad_left="3" +                    /> +                    <icons_combo_box.item +                     name="mature_ci" +                     label="Moderate Content" +                     value="Mature" +                    > +                        <item.columns +                         value="Parcel_M_Light" +                         width="20" +                         halign="center" +                         type="icon" +                        /> +                    </icons_combo_box.item> +                    <icons_combo_box.item +                     name="pg_ci" +                     label="General Content" +                     value="PG" +                    > +                        <item.columns +                         value="Parcel_PG_Light" +                         width="20" +                         halign="center" +                         type="icon" +                        /> +                    </icons_combo_box.item> +                </icons_combo_box> +                <check_box +                 name="auto_renew_edit" +                 label="Auto renew each week" +                 top_pad="10" +                 left="10" +                 height="16" +                 width="250" +                 layout="topleft" +                /> +              </panel> +        </panel> +      </scroll_container> +    </layout_panel> + +    <layout_panel +     follows="all" +     width="310" +     height="25" +     layout="topleft" +     name="util_buttons_lp" +     auto_resize="true"> +      <layout_stack +       name="util_buttons_stack" +       bottom="-1" +       left="1" +       right="-1" +       height="25" +       follows="left|bottom|right" +       layout="topleft" +       orientation="horizontal" +       animate="false" +      > +        <layout_panel +         follows="all" +         layout="topleft" +         name="util_resizer_left" +         auto_resize="true" +         user_resize="false" +         width="1"/> +         +        <layout_panel +            follows="all" +            height="25" +            layout="topleft" +            left="0" +            name="teleport_btn_lp" +            auto_resize="false" +            top="0" +            width="85"> +            <button +             name="teleport_btn" +             label="Teleport" +             top="0" +             left="0" +             height="23" +             max_width="101" +             width="85" +             follows="bottom|left|right" +             layout="topleft" +             /> +        </layout_panel> + +        <layout_panel +            follows="all" +            height="25" +            layout="bottomleft" +            left_pad="2" +            name="map_btn_lp" +            auto_resize="false" +            max_width="101" +            width="85"> +            <button +             name="show_on_map_btn" +             label="Map" +             top="0" +             left="0" +             height="23" +             width="85" +             follows="bottom|left|right" +             layout="topleft" +             /> +        </layout_panel> + +        <layout_panel +            follows="all" +            height="25" +            layout="bottomleft" +            left_pad="2" +            name="edit_btn_lp" +            auto_resize="false" +            max_width="101" +            width="85"> +            <button +             name="edit_btn" +             label="Edit" +             top="0" +             left="0" +             height="23" +             width="85" +             follows="bottom|left|right" +             layout="topleft" +             /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="util_resizer_right" +         auto_resize="true" +         width="1"> +        </layout_panel> +      </layout_stack> +    </layout_panel> +    <layout_panel +     follows="all" +     width="310" +     height="41" +     layout="topleft" +     name="publish_layout_panel" +     auto_resize="false"> +      <view_border +          bevel_style="none" +          height="0" +          follows="left|top|right" +          layout="topleft" +          left="0" +          name="publish_emphasis_border" +          top="5" +          width="310"/> +      <layout_stack +       name="publish_stack" +       left="1" +       right="-1" +       top="11" +       height="25" +       follows="left|top|right" +       layout="topleft" +       orientation="horizontal" +       animate="false" +      > +        <layout_panel +         follows="all" +         layout="topleft" +         name="pbl_resizer_left" +         auto_resize="true" +         user_resize="false" +         width="1"/> +         +        <layout_panel +         follows="all" +         layout="topleft" +         name="save_btn_lp" +         auto_resize="false" +         width="134"> +          <button +           name="save_changes_btn" +           label="[LABEL]" +           top="0" +           left="0" +           left_pad="5" +           height="23" +           width="134" +           follows="left|top" +           layout="topleft" +             /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="cancel_btn_lp" +         auto_resize="false" +         width="134"> +          <button +           name="cancel_btn" +           label="Cancel" +           top="0" +           left="0" +           height="23" +           width="134" +           follows="left|top" +           layout="topleft" +             /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="pbl_resizer_right" +         auto_resize="true" +         width="1"> +        </layout_panel> +         +      </layout_stack> +    </layout_panel> +  </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml new file mode 100644 index 0000000000..2b2f60e0c2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_classifieds.xml @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_classifieds" + label="Classified" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +    <string +     name="no_classifieds" +     value="No Classifieds" +    /> + +  <layout_stack +   name="main_stack" +   top="0" +   left="0" +   right="-1" +   bottom="-1" +   follows="all" +   layout="topleft" +   animate="false" +   orientation="vertical"> +    <layout_panel +     name="buttons_header" +     follows="all" +     layout="topleft" +     height="50" +     auto_resize="false" +     user_resize="false"> +      <button +       name="new_btn" +       label="New..." +       tool_tip="Create a new classified at the current location" +       enabled="false" +       top="25" +       left="5" +       height="20" +       width="70" +       follows="left|top" +       layout="topleft" +       visible="true" +      /> +      <button +       name="delete_btn" +       label="Delete..." +       tool_tip="Delete currently selected classified" +       enabled="false" +       left_pad="5" +       height="20" +       width="70" +       follows="left|top" +       layout="topleft" +       visible="true" +      /> +    </layout_panel> +    <layout_panel +     name="main_body" +     follows="all" +     layout="topleft" +     height="430" +     auto_resize="true" +     user_resize="false"> +      <tab_container +       name="tab_classifieds" +       top="0" +       bottom="-1" +       left="4" +       right="-4" +       follows="all" +       layout="topleft" +       halign="left" +       tab_position="left" +       tab_width="150" +       use_ellipses="true" +      /> + +      <layout_stack +       name="indicator_stack" +       top="220" +       left="0" +       right="-1" +       height="28" +       follows="top|left|right" +       layout="topleft" +       animate="false" +       orientation="horizontal"> +        <layout_panel +         name="indicator_spacer_left" +         follows="all" +         layout="topleft" +         width="100" +         auto_resize="true" +         user_resize="false"> +        </layout_panel> +        <layout_panel +         name="buttons_header" +         follows="all" +         layout="topleft" +         width="25" +         auto_resize="false" +         user_resize="false"> +          <loading_indicator +           name="progress_indicator" +           top="1" +           left="1" +           height="23" +           width="23" +           follows="top|left" +           layout="topleft" +           visible="false" +            /> +        </layout_panel> +        <layout_panel +         name="indicator_spacer_right" +         follows="all" +         layout="topleft" +         width="100" +         auto_resize="true" +         user_resize="false"> +        </layout_panel> +      </layout_stack> +      <text +       name="classifieds_panel_text" +       top="250" +       left="110" +       right="-110" +       height="25" +       follows="left|top|right" +       layout="topleft" +       halign="center" +       mouse_opaque="false" +       wrap="true" +      > +          Loading... +      </text> +    </layout_panel> +  </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml new file mode 100644 index 0000000000..ca1e405a62 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_firstlife" + label="Profile" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +    <loading_indicator +     name="progress_indicator" +     top="5" +     right="-10" +     height="23" +     width="23" +     follows="top|right" +     layout="topleft" +     visible="false" +    /> +    <icon +     name="real_world_pic" +     image_name="Generic_Person_Large" +     follows="top|left" +     layout="topleft" +     top="10" +     left="8" +     height="160" +     width="160"/> +    <loading_indicator +     name="image_upload_indicator" +     top="79" +     left="77" +     height="23" +     width="23" +     follows="top|left" +     layout="topleft" +     visible="false"/> +    <button +     name="fl_upload_image" +     label="Upload Photo" +     top="102" +     left="175" +     height="20" +     width="120" +     follows="top|left" +     layout="topleft"/> +    <button +     name="fl_change_image" +     label="Change Photo" +     top_pad="5" +     left="175" +     height="20" +     width="120" +     follows="top|left" +     layout="topleft"/> +    <button +     name="fl_remove_image" +     label="Remove Photo" +     top_pad="5" +     left_delta="0" +     height="20" +     width="120" +     follows="top|left" +     layout="topleft"/> +    <text_editor +     name="fl_description_edit" +     trusted_content="false" +     enabled="false" +     top="180" +     left="6" +     right="-6" +     height="224" +     follows="all" +     layout="topleft" +     bg_readonly_color="Transparent" +     border_visible="true" +     max_length="65000" +     parse_urls="true" +     word_wrap="true" +    /> +    <button +     name="fl_save_changes" +     label="Save" +     top_pad="5" +     right="-108" +     height="20" +     width="80" +     enabled="false" +     follows="right|bottom" +     layout="topleft"/> +    <button +     name="fl_discard_changes" +     label="Discard" +     top_delta="0" +     right="-4" +     height="20" +     width="100" +     enabled="false" +     follows="right|bottom" +     layout="topleft"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_notes.xml b/indra/newview/skins/default/xui/en/panel_profile_notes.xml new file mode 100644 index 0000000000..16e7365042 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_notes.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_notes" + label="Notes & Privacy" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +    <loading_indicator +     name="progress_indicator" +     top="3" +     right="-10" +     height="23" +     width="23" +     follows="top|right" +     layout="topleft" +     visible="false" +    /> +    <text +     name="status_message" +     value="Make notes about this person here. No one else can see your notes." +     top="6" +     left="6" +     right="-6" +     height="16" +     follows="left|top|right" +     layout="topleft" +     font.style="BOLD" +    /> +    <text_editor +     name="notes_edit" +     enabled="false" +     top="28" +     left="6" +     right="-6" +     bottom="-26" +     follows="all" +     layout="topleft" +     max_length="65530" +     word_wrap="true" +    /> +    <button +     name="notes_save_changes" +     label="Save" +     bottom="-1" +     right="-108" +     height="20" +     width="80" +     enabled="false" +     follows="bottom|right" +     layout="topleft"/> +    <button +     name="notes_discard_changes" +     label="Discard" +     bottom="-1" +     right="-4" +     height="20" +     width="100" +     enabled="false" +     follows="bottom|right" +     layout="topleft"/> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_pick.xml b/indra/newview/skins/default/xui/en/panel_profile_pick.xml new file mode 100644 index 0000000000..3e91640093 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_pick.xml @@ -0,0 +1,314 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_pick_info" + top="0" + left="0" + height="360" + width="310" + follows="all" + layout="topleft" + help_topic="profile_pick_info" +> +    <panel.string +     name="location_notice" +    > +        (will update after save) +    </panel.string> + +  <layout_stack +   name="main_pick_stack" +   left="1" +   right="-1" +   top="0" +   bottom="-1" +   follows="all" +   layout="topleft" +   orientation="vertical" +   animate="false"> +    <layout_panel +     follows="all" +     layout="bottomleft" +     left_pad="2" +     name="main_pick_lp" +     auto_resize="true" +     height="314"> +      <texture_picker +       name="pick_snapshot" +       top="10" +       left="10" +       height="161" +       width="260" +       follows="left|top" +       layout="topleft" +       fallback_image="default_land_picture.j2c" +      /> +      <text +       name="title_label" +       top_pad="-15" +       left="10" +       height="15" +       width="280" +       follows="left|top" +       layout="topleft" +       font="SansSerifSmall" +       font.style="BOLD" +       length="1" +       text_color="white" +       type="string" +                > +        Title: +      </text> +      <line_editor +       name="pick_name" +       enabled="false" +       top_pad="2" +       left="10" +       height="20" +       width="290" +       follows="left|right|top" +       layout="topleft" +      /> +      <text +       name="description_label" +       top_pad="10" +       left="10" +       height="15" +       width="280" +       follows="left|top" +       layout="topleft" +       font="SansSerifSmall" +       font.style="BOLD" +       length="1" +       text_color="white" +       type="string" +                > +        Description: +      </text> +      <text_editor +       name="pick_desc" +       trusted_content="false" +       always_show_icons="true" +       enabled="false" +       top_pad="2" +       left="10" +       height="45" +       width="290" +       follows="all" +       layout="topleft" +       allow_html="true" +       border_visible="true" +       h_pad="4" +       max_length="1023" +       v_pad="3" +       word_wrap="true" +      /> +      <text +       name="location_label" +       bottom="-25" +       left="10" +       height="15" +       width="280" +       follows="left|right|bottom" +       layout="topleft" +       font="SansSerifSmall" +       font.style="BOLD" +       length="1" +       text_color="white" +       type="string" +                > +        Location: +      </text> +      <line_editor +       name="pick_location" +       enabled="false" +       bottom="-1" +       left="10" +       height="23" +       width="290" +       follows="left|right|bottom" +       layout="topleft" +       length="1" +       type="string" +      > +          Loading... +      </line_editor> +    </layout_panel> + + +    <layout_panel +     follows="all" +     layout="bottomleft" +     name="save_changes_lp" +     auto_resize="false" +     height="25"> +      <layout_stack +       name="save_changes_stack" +       left="1" +       right="-1" +       top="0" +       height="25" +       follows="left|top|right" +       layout="topleft" +       orientation="horizontal" +       animate="false"> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="util_resizer_left" +         auto_resize="true" +         width="1"> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="map_btn_lp" +         auto_resize="false" +         width="100"> +          <button +           name="show_on_map_btn" +           label="Show on Map" +           left="0" +           top="0" +           height="23" +           width="100" +           follows="left|top" +           layout="topleft" +      /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="tp_btn_lp" +         auto_resize="false" +         width="100"> +          <button +           name="teleport_btn" +           label="Teleport" +           left="0" +           top="0" +           height="23" +           width="100" +           follows="left|top" +           layout="topleft" +          /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="util_resizer_right" +         auto_resize="true" +         width="1"> +        </layout_panel> + +      </layout_stack> +    </layout_panel> + +    <layout_panel +     follows="all" +     layout="bottomleft" +     name="save_changes_lp" +     auto_resize="false" +     height="41"> +      <view_border +          bevel_style="none" +          height="0" +          follows="left|top|right" +          layout="topleft" +          left="0" +          name="save_emphasis_border" +          top="5" +          width="310"/> +      <layout_stack +       name="save_changes_stack" +       left="1" +       right="-1" +       top="11" +       height="25" +       follows="left|top|right" +       layout="topleft" +       orientation="horizontal" +       animate="false"> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="save_resizer_left" +         auto_resize="true" +         width="1"> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="create_btn_lp" +         auto_resize="false" +         width="130"> +          <button +           name="create_changes_btn" +           label="Create Pick" +           left="0" +           top="0" +           height="23" +           width="130" +           follows="left|top" +           layout="topleft" +          /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="save_btn_lp" +         auto_resize="false" +         width="130"> +          <button +           name="save_changes_btn" +           label="Save Pick" +           left="0" +           top="0" +           height="23" +           width="130" +           follows="left|top" +           layout="topleft" +          /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="bottomleft" +         left_pad="2" +         name="cancel_btn_lp" +         auto_resize="false" +         width="130"> +          <button +           name="cancel_changes_btn" +           label="Cancel" +           left="0" +           top="0" +           height="23" +           width="130" +           follows="left|top" +           layout="topleft" +          /> +        </layout_panel> + +        <layout_panel +         follows="all" +         layout="topleft" +         name="save_resizer_right" +         auto_resize="true" +         width="1"> +        </layout_panel> + +      </layout_stack> +    </layout_panel> +  </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_picks.xml b/indra/newview/skins/default/xui/en/panel_profile_picks.xml new file mode 100644 index 0000000000..44d5c448c0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_picks.xml @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_picks" + label="Picks" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +    <string +     name="no_picks" +     value="No Picks" +    /> + +  <layout_stack +   name="main_stack" +   top="0" +   left="0" +   right="-1" +   bottom="-1" +   follows="all" +   layout="topleft" +   animate="false" +   orientation="vertical"> +    <layout_panel +     name="buttons_header" +     follows="all" +     layout="topleft" +     height="50" +     auto_resize="false" +     user_resize="false"> +      <text +       name="header_text" +       top="5" +       left="5" +       right="-5" +       height="16" +       follows="left|top|right" +       layout="topleft" +       halign="center" +    > +        Tell everyone about your favorite places in Second Life. +      </text> +      <button +       name="new_btn" +       label="New..." +       tool_tip="Create a new pick at the current location" +       enabled="false" +       top_pad="4" +       left="5" +       height="20" +       width="70" +       follows="left|top" +       layout="topleft" +       visible="false" +    /> +      <button +       name="delete_btn" +       label="Delete..." +       tool_tip="Delete currently selected pick" +       enabled="false" +       left_pad="5" +       height="20" +       width="70" +       follows="left|top" +       layout="topleft" +       visible="false" +    /> +    </layout_panel> +    <layout_panel +     name="main_body" +     follows="all" +     layout="topleft" +     height="430" +     auto_resize="true" +     user_resize="false"> +      <tab_container +       name="tab_picks" +       top="0" +       bottom="-5" +       left="4" +       right="-4" +       tab_width="150" +       follows="all" +       layout="topleft" +       halign="left" +       tab_position="left" +       use_ellipses="true" +    /> +       +    <layout_stack +     name="indicator_stack" +     top="220" +     left="0" +     right="-1" +     height="28" +     follows="top|left|right" +     layout="topleft" +     animate="false" +     orientation="horizontal"> +      <layout_panel +       name="indicator_spacer_left" +       follows="all" +       layout="topleft" +       width="100" +       auto_resize="true" +       user_resize="false"> +      </layout_panel> +      <layout_panel +       name="buttons_header" +       follows="all" +       layout="topleft" +       width="25" +       auto_resize="false" +       user_resize="false"> +        <loading_indicator +         name="progress_indicator" +         top="1" +         left="1" +         height="23" +         width="23" +         follows="top|left" +         layout="topleft" +         visible="false" +        /> +      </layout_panel> +      <layout_panel +       name="indicator_spacer_right" +       follows="all" +       layout="topleft" +       width="100" +       auto_resize="true" +       user_resize="false"> +      </layout_panel> +    </layout_stack> +    <text +       name="picks_panel_text" +       top="250" +       left="100" +       right="-100" +       height="25" +       follows="left|top|right" +       layout="topleft" +       halign="center" +       mouse_opaque="false" +       wrap="true" +    > +        Loading... +      </text> +    </layout_panel> +  </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml new file mode 100644 index 0000000000..551b477876 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -0,0 +1,549 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile" + label="Profile" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +   <string  +    name="date_format" +    value="SL birthdate: [mth,datetime,slt] [day,datetime,slt], [year,datetime,slt]" /> +   <string +    name="age_format" +    value="[AGE]" /> +   <string +    name="partner_text" +    value="Partner: [LINK]" /> +   <string +    name="CaptionTextAcctInfo"> +Account: [ACCTTYPE] +[PAYMENTINFO] +    </string> + +  <layout_stack +   name="image_stack" +   top="8" +   left="6" +   bottom="-1" +   width="160" +   border_size="0" +   follows="left|top|bottom" +   layout="topleft" +   animate="false" +   orientation="vertical"> +    <layout_panel +     name="image_panel" +     follows="all" +     layout="topleft" +     width="160" +     height="160" +     auto_resize="false" +     user_resize="false"> + +      <icon +       name="2nd_life_pic" +       image_name="Generic_Person_Large" +       layout="topleft" +       follows="all" +       interactable="true" +       top="0" +       left="2" +       bottom="-1" +       right="-1"/> + +      <loading_indicator +       name="image_upload_indicator" +       top="69" +       left="69" +       height="23" +       width="23" +       follows="top|left" +       layout="topleft" +       visible="false"/> +    </layout_panel> + +    <layout_panel +     name="basics_panel" +     follows="all" +     layout="topleft" +     height="54" +     auto_resize="false" +     user_resize="false" +        > +      <line_editor +       name="user_name" +       border_thickness="0" +       use_bg_color="false" +       background_image_disabled="" +       background_image_focused="" +       enabled="false" +       value="(loading...)" +       top="4" +       left="3" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft"/> + +      <line_editor +       name="sl_birth_date" +       border_thickness="0" +       use_bg_color="false" +       background_image_disabled="" +       background_image_focused="" +       enabled="false" +       value="(loading...)" +       top_pad="0" +       left_delta="0" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft"/> + +      <line_editor +       name="user_age" +       border_thickness="0" +       use_bg_color="false" +       background_image_disabled="" +       background_image_focused="" +       enabled="false" +       value="(loading...)" +       top_pad="0" +       left_delta="0" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft"/> +    </layout_panel> +    <layout_panel +     name="partner_layout" +     follows="all" +     layout="topleft" +     height="30" +     auto_resize="false" +     user_resize="false" +     visible="true"> +      <text +       type="string" +       name="partner_link" +       value="Partner: (loading...)" +       top="0" +       left="5" +       right="-1" +       height="28" +       follows="left|top|right" +       layout="topleft" +       translate="false" +       use_ellipses="true" +       word_wrap="true" +       visible="true"/> +    </layout_panel> + +    <layout_panel +     name="partner_spacer_layout" +     follows="all" +     layout="topleft" +     height="14" +     auto_resize="false" +     user_resize="false" +     visible="true"> +    </layout_panel> +     +    <layout_panel +     name="frind_layout" +     follows="all" +     layout="topleft" +     height="16" +     auto_resize="false" +     user_resize="false" +     visible="false"> +      <text +       name="frind_text" +       value="You are friends" +       text_color="ConversationFriendColor" +       top="0" +       left="5" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft" +       translate="false" +       visible="true"/> +    </layout_panel> +    <layout_panel +     name="online_layout" +     follows="all" +     layout="topleft" +     height="16" +     auto_resize="false" +     user_resize="false" +     visible="false"> +      <icon +       name="online_icon" +       image_name="Profile_Friend_Online" +       layout="topleft" +       follows="left|top" +       top="0" +       left="5" +       height="10" +       width="10"/> +      <text +       name="online_text" +       value="Online" +       top="0" +       left="18" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft" +       translate="false" +       visible="true"/> +    </layout_panel> +    <layout_panel +     name="offline_layout" +     follows="all" +     layout="topleft" +     height="16" +     auto_resize="false" +     user_resize="false" +     visible="false"> +      <icon +       name="offline_icon" +       image_name="Profile_Friend_Offline" +       layout="topleft" +       follows="left|top" +       top="0" +       left="5" +       height="10" +       width="10"/> +      <text +       name="offline_text" +       value="Offline" +       top="0" +       left="18" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft" +       translate="false" +       visible="true"/> +    </layout_panel> +    <layout_panel +     name="account_layout" +     follows="all" +     layout="topleft" +     height="33" +     auto_resize="false" +     user_resize="false"> +      <text +       name="account_info" +       value="Account: (loading...)" +       top="0" +       left="5" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft" +       word_wrap="true"/> +    </layout_panel> +    <layout_panel +     name="indicator_stack" +     follows="all" +     layout="topleft" +     height="33" +     auto_resize="false" +     user_resize="false"> +      <loading_indicator +       name="progress_indicator" +       left="67" +       top="0" +       height="23" +       width="23" +       follows="left|top" +       layout="topleft" +       visible="true"/> +    </layout_panel> +    <layout_panel +     name="settings_panel" +     follows="all" +     layout="topleft" +     height="50" +     auto_resize="false" +     user_resize="false"> +      <!-- only for self --> +      <text +       name="search_label" +       value="Show my profile in search:" +       top="1" +       left="6" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft"/> +      <combo_box +       name="show_in_search" +       tool_tip="Let people see you in search results" +       left="1" +       top="18" +       height="23" +       width="140" +       follows="left|top" +       layout="topleft" +       visible="true" +       enabled="false"> +        <combo_box.item +           name="Hide" +           label="Hide" +           value="0" /> +        <combo_box.item +           name="Show" +           label="Show" +           value="1" /> +      </combo_box> +    </layout_panel> +     +    <layout_panel +     name="menu_panel" +     follows="all" +     layout="topleft" +     height="55" +     auto_resize="false" +     user_resize="false" +        > +      <menu_button +       layout="topleft" +       follows="left|top" +       left="1" +       top="25" +       height="25" +       width="140" +       label="Actions" +       halign="left" +       image_unselected="DropDown_Off" +       image_selected="DropDown_On" +       image_pressed="DropDown_Press" +       image_pressed_selected="DropDown_Press" +       image_disabled="DropDown_Disabled" +       name="agent_actions_menu" /> +    </layout_panel> +  </layout_stack> + +  <layout_stack +   name="main_stack" +   top="8" +   left="168" +   bottom="-1" +   right="-1" +   follows="all" +   layout="topleft" +   animate="false" +   orientation="vertical"> +    <layout_panel +     name="display_name_panel" +     follows="all" +     layout="topleft" +     height="24" +     auto_resize="false" +     user_resize="false"> +      <line_editor +       name="display_name" +       border_thickness="0" +       use_bg_color="false" +       background_image_disabled="" +       background_image_focused="" +       enabled="false" +       value="(loading...)" +       font="SansSerifBigLarge" +       top="0" +       left="6" +       height="19" +       right="-86" +       follows="left|top|right" +       layout="topleft"/> + +      <icon +       tool_tip="Friend can see my online status" +       mouse_opaque="true" +       name="can_see_online" +       image_name="Profile_Perm_Online_Enabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-61" +       height="24" +       width="24" +       left_pad="2" /> + +      <icon +       tool_tip="Friend can not see my online status" +       mouse_opaque="true" +       name="cant_see_online" +       image_name="Profile_Perm_Online_Disabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-61" +       height="24" +       width="24" +       left_pad="2" /> + +      <icon +       tool_tip="Friend can see me on map" +       mouse_opaque="true" +       name="can_see_on_map" +       image_name="Profile_Perm_Find_Enabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-30" +       height="24" +       width="24" +       left_pad="2" /> + +      <icon +       tool_tip="Friend can not see me on map" +       mouse_opaque="true" +       name="cant_see_on_map" +       image_name="Profile_Perm_Find_Disabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-30" +       height="24" +       width="24" +       left_pad="2" /> + +      <icon +       tool_tip="Friend can edit my objects" +       mouse_opaque="true" +       name="can_edit_objects" +       image_name="Profile_Perm_Objects_Enabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-1" +       height="24" +       width="24" +       left_pad="2" /> + +      <icon +       tool_tip="Friend can not edit my objects" +       mouse_opaque="true" +       name="cant_edit_objects" +       image_name="Profile_Perm_Objects_Disabled" +       layout="topleft" +       follows="right|top" +       interactable="true" +       top="0" +       right="-1" +       height="24" +       width="24" +       left_pad="2" /> + +    </layout_panel> + +    <layout_panel +     name="about_panel" +     follows="all" +     layout="topleft" +     height="159" +     auto_resize="true" +     user_resize="false"> +      <text_editor +       name="sl_description_edit" +       trusted_content="false" +       always_show_icons="true" +       commit_on_focus_lost="false" +       enabled="false" +       top="0" +       left="2" +       right="-1" +       bottom="-1" +       follows="all" +       layout="topleft" +       bg_readonly_color="Transparent" +       border_visible="true" +       font="SansSerifSmall" +       h_pad="2" +       max_length="65000" +       parse_urls="true" +       word_wrap="true" +        /> +    </layout_panel> +    <layout_panel +     name="about_buttons_panel" +     follows="all" +     layout="topleft" +     height="34" +     auto_resize="false" +     user_resize="false"> +        <button +         name="save_description_changes" +         label="Save" +         top="1" +         right="-105" +         height="20" +         width="80" +         enabled="false" +         follows="top|right" +         layout="topleft"/> +        <button +         name="discard_description_changes" +         label="Discard" +         top="1" +         right="-1" +         height="20" +         width="100" +         enabled="false" +         follows="top|right" +         layout="topleft"/> +        <view_border +         bevel_style="none" +         height="0" +         layout="topleft" +         left="0" +         name="cost_text_border" +         top_pad="9" +         width="492"/> +    </layout_panel> + +    <layout_panel +     name="groups_panel" +     follows="all" +     layout="topleft" +     height="159" +     auto_resize="true" +     user_resize="false"> +      <text +       name="group_label" +       value="Group memberships" +       top="1" +       left="2" +       right="-1" +       height="16" +       follows="left|top|right" +       layout="topleft"/> +      <group_list +       name="group_list" +       top="18" +       left="2" +       right="-1" +       bottom="-1" +       follows="all" +       layout="topleft" +       border_visible="true" +       color="ScrollBgWriteableColor" +       for_agent="false"/> + +    </layout_panel> +  </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile_web.xml b/indra/newview/skins/default/xui/en/panel_profile_web.xml new file mode 100644 index 0000000000..e0cb4d3d06 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile_web.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + name="panel_profile_web" + label="Web" + top="0" + left="0" + height="480" + width="420" + follows="all" + layout="topleft" +> +    <panel.string +     name="LoadTime" +     value="Load Time: [TIME] seconds" +    /> +    <web_browser +     name="profile_html" +     top="10" +     bottom="-18" +     left="10" +     right="-10" +     follows="all" +     layout="topleft" +     start_url="" +    /> +    <text +     name="status_text" +     bottom="-4" +     left="110" +     right="-110" +     follows="bottom|left|right" +     layout="topleft" +     halign="center" +     parse_urls="false" +    /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 85ee736176..2af7ccaa7a 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -11,6 +11,36 @@           name="Texture"           top="0"           width="295"> +            <panel.string +             name="paste_error_face_selection_mismatch"> +              When multiple faces are copied, the target object must have the same number of faces selected. +            </panel.string> +            <panel.string +             name="paste_error_object_face_count_mismatch"> +              When all faces of an object are copied, the target object must have the same number of faces. +            </panel.string> +            <panel.string +             name="paste_error_inventory_not_found"> +              One or more texture not found in inventory. +            </panel.string> +            <panel.string +             name="paste_options"> +              Paste options +            </panel.string> + +            <menu_button +             menu_filename="menu_copy_paste_color.xml" +             follows="top|left" +             height="15" +             image_disabled="ClipboardMenu_Disabled" +             image_selected="ClipboardMenu_Press" +             image_unselected="ClipboardMenu_Off" +             layout="topleft" +             left="258" +             top="8" +             name="clipboard_color_params_btn" +             tool_tip="Paste options" +             width="22"/>              <text               type="string"               length="1" @@ -36,7 +66,7 @@               name="colorswatch"               tool_tip="Click to open color picker"               top="20" -             width="64" /> +             width="54" />              <text               type="string"               length="1" @@ -84,7 +114,7 @@               left_delta="0"               name="glow"               top_pad="4" -             width="80" /> +             width="77" />              <check_box               height="19"               label="Full Bright" @@ -93,13 +123,22 @@               name="checkbox fullbright"               top_pad="4"               width="81" /> +            <view_border +             bevel_style="none" +             follows="top|left" +             height="0" +             layout="topleft" +             left="8" +             name="object_horizontal" +             top_pad="4" +             width="278" />              <combo_box               height="23"               layout="topleft"               left="10"               name="combobox matmedia" -             top_pad="5" -             width="100"> +             top_pad="17" +             width="90">                  <combo_box.item                   label="Materials"                   name="Materials" @@ -113,7 +152,7 @@              control_name="ComboMaterialType"              height="50"              layout="topleft" -            left_pad="20" +            left_pad="5"              top_delta="-10"              width="150"              visible = "false" @@ -139,7 +178,20 @@                  layout="topleft"                  top_pad="1"                  value="2"/> -            </radio_group>  +            </radio_group> +            <menu_button +                menu_filename="menu_copy_paste_texture.xml" +                follows="top|left" +                height="15" +                image_disabled="ClipboardMenu_Disabled" +                image_selected="ClipboardMenu_Press" +                image_unselected="ClipboardMenu_Off" +                layout="topleft" +                left="258" +                top_delta="0" +                name="clipboard_texture_params_btn" +                tool_tip="Paste options" +                width="22"/>              <check_box               control_name="SyncMaterialSettings"               follows="top|left" @@ -150,7 +202,7 @@               left="8"               name="checkbox_sync_settings"               tool_tip="Adjust all maps repeats simultaneously" -             top_pad="-16" +             top_pad="19"               width="160" />              <texture_picker               can_apply_immediately="true" @@ -771,14 +823,14 @@               top_delta="16"               width="260" />  			<button -			 left="10" -			 top="257" +       follows="left|top" +       layout="topleft" +			 left="9" +			 top="204"  			 height="20"  			 label="Align"  			 label_selected="Align current texture layers" -			 layout="topleft"  			 name="button align textures" -			 top_delta="0"  			 tool_tip="Align current texture layers"  			 width="66" />              <web_browser @@ -793,29 +845,4 @@               height="4"               start_url="about:blank"               decouple_texture_size="true" /> -      <button -       left="90" -       top="222" -       height="20" -       label="Save as Material" -       label_selected="Save current face as a Material" -       layout="topleft" -       name="button save material" -       top_delta="0" -       tool_tip="Save material to inventory" -       width="110" /> - -            <line_editor -             enabled="true" -             follows="top|left" -             height="16" -             layout="topleft" -             left="7" -             label="Material UUID" -             name="materialID" -             select_on_focus="true" -             top="380" -             width="200" -             tool_tip="UUID for a material asset" -             />  </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 8a3e18707f..1c9d750aa6 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -459,7 +459,7 @@          label="Price: L$"          label_width="73"				          width="150" -        min_val="1" +        min_val="0"          height="20"          max_val="999999999"          tool_tip="Object cost." /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4169929be8..960faabcfd 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2810,10 +2810,14 @@ If you continue to receive this message, please contact Second Life support for  	<string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>  	<string name="ClassifiedUpdateAfterPublish">(will update after publish)</string> -  <!-- panel picks --> -  <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> -  <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> -  <string name="PicksClassifiedsLoadingText">Loading...</string> +    <!-- panel picks --> +    <string name="NoPicksClassifiedsText">You haven't created any Picks or Classifieds. Click the Plus button below to create a Pick or Classified.</string> +    <string name="NoPicksText">You haven't created any Picks. Click the New button to create a Pick.</string> +    <string name="NoClassifiedsText">You haven't created any Classifieds. Click the New button to create a Classified.</string> +    <string name="NoAvatarPicksClassifiedsText">User has no picks or classifieds</string> +    <string name="NoAvatarPicksText">This person has no picks</string> +    <string name="NoAvatarClassifiedsText">This person has no classifieds</string> +    <string name="PicksClassifiedsLoadingText">Loading...</string>  	<!-- Multi Preview Floater -->  	<string name="MultiPreviewTitle">Preview</string> @@ -4264,6 +4268,9 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>    <string name="ExperiencePermissionShort16">Sit</string>    <string name="ExperiencePermissionShort17">Environment</string> +  <!-- PBR Materials --> +  <string name="Material Texture Name Header">Textures present this material: </string> +      <!-- Conversation log messages -->    <string name="logging_calls_disabled_log_empty">      Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat. diff --git a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml index 4f3c177976..87f93e8fcf 100644 --- a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@  	<check_box label="Gestos" name="check_gesture"/>  	<check_box label="Hitos" name="check_landmark"/>  	<check_box label="Notas" name="check_notecard"/> -	<check_box label="Redes" name="check_mesh"/> +	<check_box label="Meshs" name="check_mesh"/>  	<check_box label="Objetos" name="check_object"/>  	<check_box label="Scripts" name="check_script"/>  	<check_box label="Sonidos" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/es/floater_preview_texture.xml b/indra/newview/skins/default/xui/es/floater_preview_texture.xml index b0afd44750..2543508c40 100644 --- a/indra/newview/skins/default/xui/es/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/es/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Copiar al inventario  	</floater.string> -	<text name="desc txt"> -		Descripción: -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		Previsualizar la ratio de las proporciones -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Vista previa en una proporción concreta"> -		<combo_item name="Unconstrained"> -			Sin restricciones -		</combo_item> -		<combo_item name="1:1" tool_tip="Emblema del grupo o perfil del Mundo real"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="Perfil de [SECOND_LIFE]"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Clasificados (también en las listas de búsqueda), hitos"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="Acerca del terreno"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Destacados del perfil"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Descartar" name="Discard"/> -	<button label="Guardar como" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Descripción: +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				Previsualizar la ratio de las proporciones +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Vista previa en una proporción concreta"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Descartar" name="Discard"/> +			<button label="Guardar como" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/es/floater_profile.xml b/indra/newview/skins/default/xui/es/floater_profile.xml new file mode 100644 index 0000000000..c9448a0d4e --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Perfil"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="Intereses" name="panel_profile_interests"/> +			<panel label="Destacados" name="panel_profile_picks"/> +			<panel label="Clasificado" name="panel_profile_classifieds"/> +			<panel label="Vida real" name="panel_profile_firstlife"/> +			<panel label="Notas" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Salvar cambios en el perfil y cerrar"/> +		<button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml index c2c996aa8a..2dfaecf3e3 100644 --- a/indra/newview/skins/default/xui/es/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		Enviando el correo electrónico  	</string> +	<string name="facebook_progress_str"> +		Publicando en Facebook +	</string>  	<string name="profile_progress_str">  		Publicando  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Guardando en el equipo  	</string> +	<string name="facebook_succeeded_str"> +		Imagen subida +	</string>  	<string name="profile_succeeded_str">  		Imagen subida  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		¡Guardado en el equipo!  	</string> +	<string name="facebook_failed_str"> +		Error al subir la imagen a tu biografía de Facebook. +	</string>  	<string name="profile_failed_str">  		Error al subir la imagen a los comentarios de tu perfil.  	</string> diff --git a/indra/newview/skins/default/xui/es/menu_name_field.xml b/indra/newview/skins/default/xui/es/menu_name_field.xml new file mode 100644 index 0000000000..0d51fbffeb --- /dev/null +++ b/indra/newview/skins/default/xui/es/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Copiar Nombre mostrado" name="copy_display"/> +	<menu_item_call label="Copiar Nombre de agente" name="copy_name"/> +	<menu_item_call label="Copiar ID de agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 54707116d4..36f27bc3c6 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2690,6 +2690,9 @@ Inténtalo seleccionando un trozo más pequeño de terreno.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/es/panel_edit_classified.xml b/indra/newview/skins/default/xui/es/panel_edit_classified.xml index ffad843732..09f87015cc 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="Cancelar" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/es/panel_facebook_place.xml b/indra/newview/skins/default/xui/es/panel_facebook_place.xml index 5139bd1d0b..29f6147f23 100644 --- a/indra/newview/skins/default/xui/es/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/es/panel_facebook_place.xml @@ -3,7 +3,7 @@  	<text name="place_caption_label">  		Cuenta algo del lugar donde te encuentras:  	</text> -	<check_box initial_value="false" label="Incluir una vista general del lugar" name="add_place_view_cb"/> +	<check_box initial_value="false" label="Incluye una vista general del lugar" name="add_place_view_cb"/>  	<button label="Publicar" name="post_place_btn"/>  	<button label="Cancelar" name="cancel_place_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/es/panel_group_general.xml b/indra/newview/skins/default/xui/es/panel_group_general.xml index a17814d15d..ef919f396e 100644 --- a/indra/newview/skins/default/xui/es/panel_group_general.xml +++ b/indra/newview/skins/default/xui/es/panel_group_general.xml @@ -46,7 +46,7 @@ Deja el cursor sobre las opciones para ver más ayuda.  		<check_box label="Cualquiera puede entrar" name="open_enrollement" tool_tip="Configura si se permite la entrada de nuevos miembros sin ser invitados."/>  		<check_box label="Cuota de entrada" name="check_enrollment_fee" tool_tip="Configura si hay que pagar una cuota para entrar al grupo"/>  		<spinner label="L$" left_delta="130" name="spin_enrollment_fee" tool_tip="Si la opción Cuota de entrada está marcada, los nuevos miembros han de pagar esta cuota para entrar al grupo." width="60"/> -		<combo_box bottom_delta="-38" name="group_mature_check" tool_tip="La calificación de contenido designa el tipo de contenido y conducta que se permiten en un grupo" width="150"> +		<combo_box bottom_delta="-38" name="group_mature_check" tool_tip="Establece si tu grupo contiene información clasificada como Moderada" width="150">  			<combo_item name="select_mature">  				- Selecciona el nivel de calificación -  			</combo_item> diff --git a/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml new file mode 100644 index 0000000000..4d682068d7 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Desconocido"/> +	<button name="info_btn" tool_tip="Más información"/> +	<button name="profile_btn" tool_tip="Ver el perfil"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_me.xml b/indra/newview/skins/default/xui/es/panel_me.xml deleted file mode 100644 index 850cd6ec71..0000000000 --- a/indra/newview/skins/default/xui/es/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mi perfil" name="panel_me"> -	<panel label="MIS DESTACADOS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/es/panel_people.xml b/indra/newview/skins/default/xui/es/panel_people.xml index 73b9af3665..2aaf7e89be 100644 --- a/indra/newview/skins/default/xui/es/panel_people.xml +++ b/indra/newview/skins/default/xui/es/panel_people.xml @@ -40,6 +40,7 @@  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Conectado"/>  				<accordion_tab name="tab_all" title="Todos"/> +				<accordion_tab name="tab_suggested_friends" title="Personas de las que podrías querer ser amigo"/>  			</accordion>  		</panel>  		<panel label="GRUPOS" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/es/panel_profile_classified.xml b/indra/newview/skins/default/xui/es/panel_profile_classified.xml new file mode 100644 index 0000000000..679026d350 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Moderado +	</panel.string> +	<panel.string name="type_pg"> +		Contenido general +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] teleportes, [MAP] mapa, [PROFILE] perfil +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Activados +	</panel.string> +	<panel.string name="auto_renew_off"> +		Inhabilitado +	</panel.string> +	<panel.string name="location_notice"> +		(se actualizará tras guardarlo) +	</panel.string> +	<string name="publish_label"> +		Publicar +	</string> +	<string name="save_label"> +		Guardar +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Pulsa para elegir una imagen"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Ubicación:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Tipo de contenido:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Categoría:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Fecha de creación:"/> +					<text_editor name="creation_date" tool_tip="Fecha de creación" value="[date]"/> +					<text name="price_for_listing_label" value="Precio por publicarlo:"/> +					<text_editor name="price_for_listing" tool_tip="Precio por publicarlo."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Clics:"/> +					<text_editor name="click_through_text" tool_tip="Información sobre Click through" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Renovación:"/> +					<text name="auto_renew" value="Activados"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Descripción:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Título: +				</text> +				<text name="description_label"> +					Descripción: +				</text> +				<text name="location_label"> +					Ubicación: +				</text> +				<text name="classified_location_edit"> +					cargando... +				</text> +				<button label="Configurar en mi posición" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Categoría:"/> +				<text name="content_type_label" value="Tipo de contenido:"/> +				<icons_combo_box label="Contenido general" name="content_type_edit"> +					<icons_combo_box.item label="Contenido Moderado" name="mature_ci" value="Contenido para adultos"/> +					<icons_combo_box.item label="Contenido general" name="pg_ci" value="General"/> +				</icons_combo_box> +				<check_box label="Renovar automáticamente cada semana" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Precio por publicarlo:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Precio por publicarlo." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Teleporte" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Mapa" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Editar" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Cancelar" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml new file mode 100644 index 0000000000..2520348094 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Clasificado" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="No hay clasificados"/> +	<button label="Nuevo..." name="new_btn"/> +	<button label="Eliminar..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Cargando... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/fr/floater_picks.xml b/indra/newview/skins/default/xui/es/panel_profile_firstlife.xml index f058ff668b..0fb502e441 100644 --- a/indra/newview/skins/default/xui/fr/floater_picks.xml +++ b/indra/newview/skins/default/xui/es/panel_profile_firstlife.xml @@ -1,2 +1,2 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Favoris"/> +<panel label="Perfil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/es/panel_profile_interests.xml b/indra/newview/skins/default/xui/es/panel_profile_interests.xml new file mode 100644 index 0000000000..86dd63390c --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Intereses" name="panel_profile_interests"> +	<text name="I Want To:"> +		Quiero: +	</text> +	<check_box label="Construye" name="chk0"/> +	<check_box label="Explora" name="chk1"/> +	<check_box label="Conoce" name="chk2"/> +	<check_box label="Encuentra empleo" name="chk6"/> +	<check_box label="Agrupa" name="chk3"/> +	<check_box label="Compra" name="chk4"/> +	<check_box label="Vende" name="chk5"/> +	<check_box label="Contrata" name="chk7"/> +	<line_editor name="want_to_edit"> +		(cargando...) +	</line_editor> +	<text name="Skills:"> +		Habilidades: +	</text> +	<check_box label="Texturas" name="schk0"/> +	<check_box label="Arquitectura" name="schk1"/> +	<check_box label="Modelo" name="schk3"/> +	<check_box label="Planificación de eventos" name="schk2"/> +	<check_box label="Preparación de scripts" name="schk4"/> +	<check_box label="Personajes personalizados" name="schk5"/> +	<line_editor name="skills_edit"> +		(cargando...) +	</line_editor> +	<text name="Languages:"> +		Idiomas: +	</text> +	<line_editor name="languages_edit"> +		(cargando...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_notes.xml b/indra/newview/skins/default/xui/es/panel_profile_notes.xml new file mode 100644 index 0000000000..4cc14e1487 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notas y Privacidad" name="panel_notes"> +	<text name="status_message" value="Notas privadas en este avatar:"/> +	<text name="status_message2" value="Permitir que este avatar:"/> +	<check_box label="Ver cuándo estoy conectado" name="status_check"/> +	<check_box label="Encontrarme en el mapa del mundo" name="map_check"/> +	<check_box label="Edita, borrar o tomar mis objetos" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_pick.xml b/indra/newview/skins/default/xui/es/panel_profile_pick.xml new file mode 100644 index 0000000000..4e9f5bbdd5 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(se actualizará tras guardarlo) +	</panel.string> +	<line_editor name="pick_location"> +		Cargando... +	</line_editor> +	<button label="Teleporte" name="teleport_btn"/> +	<button label="Mostrar en el mapa" name="show_on_map_btn"/> +	<button label="Establecer ubicación" name="set_to_curr_location_btn" tool_tip="Configurar en mi posición"/> +	<button label="Guardar" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_picks.xml b/indra/newview/skins/default/xui/es/panel_profile_picks.xml new file mode 100644 index 0000000000..0641b72c13 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Destacados" name="panel_picks"> +	<string name="no_picks" value="No hay destacados"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Cuéntale a todos sobre tus lugares favoritos de Second Life. +	</text> +	<button label="Nuevo..." name="new_btn"/> +	<button label="Eliminar..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Cargando... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml new file mode 100644 index 0000000000..541593660d --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Perfil" name="panel_profile"> +	<string name="status_online"> +		Actualmente en línea +	</string> +	<string name="status_offline"> +		Actualmente sin conexión +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Ninguno"/> +	<string name="no_group_text" value="Ninguno"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Desarrollador"/> +	<string name="FSSupp" value="Soporte"/> +	<string name="FSQualityAssurance" value="Buscador de fallos"/> +	<string name="FSGW" value="Portal"/> +	<text name="name_label" value="Nombre:"/> +	<button label="Nombre:" name="set_name" tool_tip="Configurar nombre mostrado"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(cargando...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Status Desconocido"/> +			<text name="label" value="Fecha de nacimiento en Second Life:"/> +			<text name="label2" value="Cuenta:"/> +			<text name="partner_label" value="Compañero/a:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Grupos:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Invitar al grupo"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="Acerca de:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Dar objeto:"/> +			<text name="Give inventory" tool_tip="Soltar elementos de inventario aquí para dárselos a esta persona."> +				Soltar aquí el nuevo elemento de inventario. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Encontrar en el mapa" label_selected="Encontrar en el mapa" name="show_on_map_btn" tool_tip="Mostrar al Residente en el mapa"/> +			<button label="Pagar" label_selected="Pagar" name="pay" tool_tip="Pagar a este Residente"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Ofrecer teleporte" label_selected="Ofrecer teleporte" name="teleport" tool_tip="Ofrecer teleporte al residente"/> +			<button label="Mensaje instantáneo" label_selected="Mensaje instantáneo" name="im" tool_tip="Abrir una sesión de mensajes instantáneos"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Añadir como amigo" label_selected="Añadir como amigo" name="add_friend" tool_tip="Ofrecer amistad a este Residente"/> +			<button label="Bloquear" name="block" tool_tip="Bloquear al residente"/> +			<button label="Desbloquear" name="unblock" tool_tip="Desbloquear al residente"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Mostrar en la búsqueda" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/panel_profile_web.xml b/indra/newview/skins/default/xui/es/panel_profile_web.xml new file mode 100644 index 0000000000..f9a8f4b113 --- /dev/null +++ b/indra/newview/skins/default/xui/es/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Tiempo de carga: [TIME] segundos"/> +	<line_editor name="url_edit"> +		(cargando..) +	</line_editor> +	<flyout_button label="Cargar" name="load" tool_tip="Cargar esta página de perfil con el navegador incorporado."> +		<flyout_button.item label="Abrir navegador in-viewer" name="open_item"/> +		<flyout_button.item label="Abrir navegador externo" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Perfil web emergente"/> +</panel> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 4b7f6a0081..20f7f81962 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -348,6 +348,24 @@ Intenta iniciar sesión de nuevo en unos instantes.  	<string name="TestingDisconnect">  		Probando la desconexión del visor  	</string> +	<string name="SocialFacebookConnecting"> +		Conectando con Facebook... +	</string> +	<string name="SocialFacebookPosting"> +		Publicando... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Desconectando de Facebook... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Problema al conectar con Facebook +	</string> +	<string name="SocialFacebookErrorPosting"> +		Problema al publicar en Facebook +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Problema al desconectar de Facebook +	</string>  	<string name="SocialFlickrConnecting">  		Conectándose a Flickr...  	</string> @@ -2549,9 +2567,21 @@ Si sigues recibiendo el mismo mensaje, solicita ayuda al personal de asistencia  	<string name="NoPicksClassifiedsText">  		No has creado destacados ni clasificados. Pulsa el botón Más para crear uno.  	</string> +	<string name="NoPicksText"> +		No has creado destacados. Haz clic en el botón Más para crear uno. +	</string> +	<string name="NoClassifiedsText"> +		No has creado clasificados. Haz clic en el botón Nuevo para crear un anuncio clasificado. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		El usuario no tiene clasificados ni destacados  	</string> +	<string name="NoAvatarPicksText"> +		El usuario no tiene destacados +	</string> +	<string name="NoAvatarClassifiedsText"> +		El usuario no tiene clasificados +	</string>  	<string name="PicksClassifiedsLoadingText">  		Cargando...  	</string> @@ -4469,6 +4499,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].  	<string name="share_alert">  		Arrastra los ítems desde el invenbtario hasta aquí  	</string> +	<string name="facebook_post_success"> +		Has publicado en Facebook. +	</string>  	<string name="flickr_post_success">  		Has publicado en Flickr.  	</string> diff --git a/indra/newview/skins/default/xui/fr/floater_facebook.xml b/indra/newview/skins/default/xui/fr/floater_facebook.xml index f5097e7a88..f6e8696e53 100644 --- a/indra/newview/skins/default/xui/fr/floater_facebook.xml +++ b/indra/newview/skins/default/xui/fr/floater_facebook.xml @@ -10,6 +10,6 @@  		Erreur  	</text>  	<text name="connection_loading_text"> -		Chargement... +		En cours de chargement...  	</text>  </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml index d63d9903ec..46703fe612 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Copier dans l'inventaire  	</floater.string> -	<text name="desc txt"> -		Description : -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		Rapport d'aspect fixe -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Prévisualiser avec un rapport d'aspect fixe"> -		<combo_item name="Unconstrained"> -			Sans contraintes -		</combo_item> -		<combo_item name="1:1" tool_tip="Logo du groupe ou profil dans la vie réelle"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="Profil [SECOND_LIFE]"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Petites annonces, repères"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="À propos du terrain"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Favoris du profil"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Jeter" name="Discard"/> -	<button label="Enregistrer sous" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Description : +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				Rapport d'aspect fixe +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Prévisualiser avec un rapport d'aspect fixe"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Jeter" name="Discard"/> +			<button label="Enregistrer sous" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_profile.xml b/indra/newview/skins/default/xui/fr/floater_profile.xml new file mode 100644 index 0000000000..c4af79e946 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="Centres d'intérêt" name="panel_profile_interests"/> +			<panel label="Favoris" name="panel_profile_picks"/> +			<panel label="Petite annonce" name="panel_profile_classifieds"/> +			<panel label="Vie réelle" name="panel_profile_firstlife"/> +			<panel label="Remarques" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Enregistrer les changements apportés au profil et fermer"/> +		<button label="Annuler" label_selected="Annuler" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml index 8eb05dd945..adb98a68d2 100644 --- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		Envoi par e-mail  	</string> +	<string name="facebook_progress_str"> +		Publication sur Facebook +	</string>  	<string name="profile_progress_str">  		Publication  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Enregistrement sur l'ordinateur  	</string> +	<string name="facebook_succeeded_str"> +		Image chargée +	</string>  	<string name="profile_succeeded_str">  		Image chargée  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Enregistrement sur l'ordinateur effectué !  	</string> +	<string name="facebook_failed_str"> +		Échec de chargement de l'image dans votre journal Facebook. +	</string>  	<string name="profile_failed_str">  		Échec de chargement de l'image sur le flux de votre profil.  	</string> diff --git a/indra/newview/skins/default/xui/fr/menu_name_field.xml b/indra/newview/skins/default/xui/fr/menu_name_field.xml new file mode 100644 index 0000000000..6c3fba4110 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Copier le Nom d'affichage" name="copy_display"/> +	<menu_item_call label="Copier le  Nom de l'agent" name="copy_name"/> +	<menu_item_call label="Copier l'ID de l'agent" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index e84de375d8..09905f4e5d 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2683,6 +2683,9 @@ Veuillez sélectionner un terrain plus petit.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_classified.xml b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml index 7b58f2e825..b892d25f26 100644 --- a/indra/newview/skins/default/xui/fr/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="Annuler" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml b/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml index 319737a2af..0e36c2092c 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_friends.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_friends"> -	<string name="facebook_friends_empty" value="Vous n'avez actuellement aucun ami Facebook qui est également résident de Second Life. Invitez vos amis Facebook à rejoindre Second Life !"/> +	<string name="facebook_friends_empty" value="Vous n'avez actuellement aucun ami Facebook qui est également résident de Second Life. Invitez vos amis Facebook à rejoindre Second Life aujourd'hui !"/>  	<string name="facebook_friends_no_connected" value="Vous n'êtes pas connecté(e) à Facebook. Allez à l'onglet Statut pour vous connecter et activer cette fonctionnalité."/>  	<accordion name="friends_accordion">  		<accordion_tab name="tab_second_life_friends" title="Amis SL"/> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml b/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml index 3236f35b55..cc4045bc74 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_photo.xml @@ -4,14 +4,14 @@  		<combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>  		<combo_box.item label="640 x 480" name="640x480"/>  		<combo_box.item label="800 x 600" name="800x600"/> -		<combo_box.item label="1 024 x 768" name="1024x768"/> -		<combo_box.item label="1 200 x 630" name="1200x630"/> +		<combo_box.item label="1024 x 768" name="1024x768"/> +		<combo_box.item label="1200 x 630" name="1200x630"/>  	</combo_box> -	<combo_box name="filters_combobox" tool_tip="Filtres d'image"> +	<combo_box name="filters_combobox" tool_tip="Filtres d’image">  		<combo_box.item label="Aucun filtre" name="NoFilter"/>  	</combo_box>  	<button label="Actualiser" name="new_snapshot_btn" tool_tip="Cliquer pour actualiser"/> -	<button label="Aperçu" name="big_preview_btn" tool_tip="Cliquer pour activer/désactiver l'aperçu"/> +	<button label="Aperçu" name="big_preview_btn" tool_tip="Cliquer pour basculer l'aperçu"/>  	<text name="caption_label">  		Commentaire (facultatif) :  	</text> diff --git a/indra/newview/skins/default/xui/fr/panel_facebook_status.xml b/indra/newview/skins/default/xui/fr/panel_facebook_status.xml index 9afa42d2aa..dc8e4b9ecc 100644 --- a/indra/newview/skins/default/xui/fr/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/fr/panel_facebook_status.xml @@ -6,7 +6,7 @@  		Pas connecté(e) à Facebook.  	</text>  	<panel name="panel_buttons"> -		<button label="Connexion..." name="connect_btn"/> +		<button label="Connexion en cours..." name="connect_btn"/>  		<button label="Déconnexion" name="disconnect_btn"/>  		<text name="account_learn_more_label">  			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Apprenez comment publier sur Facebook] diff --git a/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml new file mode 100644 index 0000000000..b1b32af7c6 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Inconnu"/> +	<button name="info_btn" tool_tip="En savoir plus"/> +	<button name="profile_btn" tool_tip="Voir le profil"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_me.xml b/indra/newview/skins/default/xui/fr/panel_me.xml deleted file mode 100644 index 5676986228..0000000000 --- a/indra/newview/skins/default/xui/fr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Mon profil" name="panel_me"> -	<panel label="MES FAVORIS" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_people.xml b/indra/newview/skins/default/xui/fr/panel_people.xml index 3be6bae52a..e096b5cfe0 100644 --- a/indra/newview/skins/default/xui/fr/panel_people.xml +++ b/indra/newview/skins/default/xui/fr/panel_people.xml @@ -40,6 +40,7 @@ Pour rechercher des résidents avec qui passer du temps, utilisez [secondlife://  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="En ligne"/>  				<accordion_tab name="tab_all" title="Tout"/> +				<accordion_tab name="tab_suggested_friends" title="Personnes avec lesquelles vous aimeriez peut-être devenir ami(e)"/>  			</accordion>  		</panel>  		<panel label="GROUPES" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_classified.xml b/indra/newview/skins/default/xui/fr/panel_profile_classified.xml new file mode 100644 index 0000000000..b223684c60 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Modéré +	</panel.string> +	<panel.string name="type_pg"> +		Contenu Général +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] téléporter, [MAP] carte, [PROFILE] profile +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Activé +	</panel.string> +	<panel.string name="auto_renew_off"> +		Désactivé +	</panel.string> +	<panel.string name="location_notice"> +		(mise à jour après enregistrement) +	</panel.string> +	<string name="publish_label"> +		Publier +	</string> +	<string name="save_label"> +		Enregistrer +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Cliquer pour sélectionner une image"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Endroit :"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Type de contenu :"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Catégorie :"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Date de création :"/> +					<text_editor name="creation_date" tool_tip="Date de création" value="[date]"/> +					<text name="price_for_listing_label" value="Coût de l'annonce :"/> +					<text_editor name="price_for_listing" tool_tip="Coût de l’annonce."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Clics :"/> +					<text_editor name="click_through_text" tool_tip="Parcourir les données en cliquant" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Renouv. auto :"/> +					<text name="auto_renew" value="Activé"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Description :"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Titre : +				</text> +				<text name="description_label"> +					Description : +				</text> +				<text name="location_label"> +					Endroit : +				</text> +				<text name="classified_location_edit"> +					en cours de chargement... +				</text> +				<button label="Définir sur l’emplacement actuel" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Catégorie :"/> +				<text name="content_type_label" value="Type de contenu :"/> +				<icons_combo_box label="Contenu Général" name="content_type_edit"> +					<icons_combo_box.item label="Contenu Modéré" name="mature_ci" value="Adulte"/> +					<icons_combo_box.item label="Contenu Général" name="pg_ci" value="PG"/> +				</icons_combo_box> +				<check_box label="Renouvellement auto toutes les semaines" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Coût de l'annonce :"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Coût de l’annonce." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Téléportation" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Carte" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Modifier" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Annuler" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml new file mode 100644 index 0000000000..adb3501422 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Petite annonce" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="Pas de petites annonces"/> +	<button label="Nouveau..." name="new_btn"/> +	<button label="Supprimer..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		En cours de chargement... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/es/floater_picks.xml b/indra/newview/skins/default/xui/fr/panel_profile_firstlife.xml index 255aa5dcdc..0f65090209 100644 --- a/indra/newview/skins/default/xui/es/floater_picks.xml +++ b/indra/newview/skins/default/xui/fr/panel_profile_firstlife.xml @@ -1,2 +1,2 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destacados"/> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_interests.xml b/indra/newview/skins/default/xui/fr/panel_profile_interests.xml new file mode 100644 index 0000000000..e8212817d2 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Centres d'intérêt" name="panel_profile_interests"> +	<text name="I Want To:"> +		Je veux : +	</text> +	<check_box label="Construire" name="chk0"/> +	<check_box label="Explorer" name="chk1"/> +	<check_box label="Rencontrer" name="chk2"/> +	<check_box label="Être recruté" name="chk6"/> +	<check_box label="Grouper" name="chk3"/> +	<check_box label="Acheter" name="chk4"/> +	<check_box label="Vendre" name="chk5"/> +	<check_box label="Louer" name="chk7"/> +	<line_editor name="want_to_edit"> +		(en cours de chargement...) +	</line_editor> +	<text name="Skills:"> +		Compétences : +	</text> +	<check_box label="Textures" name="schk0"/> +	<check_box label="Architecture" name="schk1"/> +	<check_box label="Modèle" name="schk3"/> +	<check_box label="Planification des événements" name="schk2"/> +	<check_box label="Langage de scripts" name="schk4"/> +	<check_box label="Personnages personnalisés" name="schk5"/> +	<line_editor name="skills_edit"> +		(en cours de chargement...) +	</line_editor> +	<text name="Languages:"> +		Langues : +	</text> +	<line_editor name="languages_edit"> +		(en cours de chargement...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_notes.xml b/indra/newview/skins/default/xui/fr/panel_profile_notes.xml new file mode 100644 index 0000000000..03fb37d72b --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notes & respect de la vie privée" name="panel_notes"> +	<text name="status_message" value="Notes personnelles sur cet avatar:"/> +	<text name="status_message2" value="Autoriser cet avatar à :"/> +	<check_box label="Voir quand je suis en ligne" name="status_check"/> +	<check_box label="Me trouver sur la carte du monde" name="map_check"/> +	<check_box label="Modifier, supprimer ou prendre mes objets" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_pick.xml b/indra/newview/skins/default/xui/fr/panel_profile_pick.xml new file mode 100644 index 0000000000..017fcff88a --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(mise à jour après enregistrement) +	</panel.string> +	<line_editor name="pick_location"> +		En cours de chargement... +	</line_editor> +	<button label="Téléportation" name="teleport_btn"/> +	<button label="Voir sur la carte" name="show_on_map_btn"/> +	<button label="Définir l'emplacement" name="set_to_curr_location_btn" tool_tip="Définir sur l’emplacement actuel"/> +	<button label="Enregistrer les favoris" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_picks.xml b/indra/newview/skins/default/xui/fr/panel_profile_picks.xml new file mode 100644 index 0000000000..1644722813 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Favoris" name="panel_picks"> +	<string name="no_picks" value="Pas de favoris"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Faites connaître aux autres résidents vos endroits favoris dans Second Life. +	</text> +	<button label="Nouveau..." name="new_btn"/> +	<button label="Supprimer..." name="delete_btn"/> +	<text name="picks_panel_text"> +		En cours de chargement... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml new file mode 100644 index 0000000000..de9cbf6dce --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> +	<string name="status_online"> +		Actuellement connecté +	</string> +	<string name="status_offline"> +		Actuellement déconnecté +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Aucun"/> +	<string name="no_group_text" value="Aucun"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Développeur"/> +	<string name="FSSupp" value="Assistance"/> +	<string name="FSQualityAssurance" value="Suivi des anomalies"/> +	<string name="FSGW" value="Portail"/> +	<text name="name_label" value="Nom :"/> +	<button label="Nom :" name="set_name" tool_tip="Définir un nom d'affichage"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(en cours de chargement...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Statut inconnu"/> +			<text name="label" value="Date de naissance dans Second Life :"/> +			<text name="label2" value="Compte :"/> +			<text name="partner_label" value="Partenaire :"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Groupes :"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Inviter dans le groupe"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="À propos :"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Donner des objets :"/> +			<text name="Give inventory" tool_tip="Placer les objets de l'inventaire ici pour les donner à cette personne"> +				Placer les objets de l'inventaire ici. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Situer sur la carte" label_selected="Situer sur la carte" name="show_on_map_btn" tool_tip="Localiser le Résident sur la carte"/> +			<button label="Payer" label_selected="Payer" name="pay" tool_tip="Payer le résident"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Proposer de téléporter" label_selected="Proposer de téléporter" name="teleport" tool_tip="Proposer une téléportation au Résident"/> +			<button label="Message instantané" label_selected="Message instantané" name="im" tool_tip="Ouvrir une session IM."/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Ajouter un ami" label_selected="Ajouter un ami" name="add_friend" tool_tip="Proposer à ce résident de devenir votre ami"/> +			<button label="Bloquer" name="block" tool_tip="Bloquer ce Résident"/> +			<button label="Débloquer" name="unblock" tool_tip="Débloquer ce Résident"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Afficher avec la recherche" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_web.xml b/indra/newview/skins/default/xui/fr/panel_profile_web.xml new file mode 100644 index 0000000000..70e145ade9 --- /dev/null +++ b/indra/newview/skins/default/xui/fr/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Heure de chargement : [TIME] secondes"/> +	<line_editor name="url_edit"> +		(en cours de chargement..) +	</line_editor> +	<flyout_button label="Charger" name="load" tool_tip="Charger ce profil avec le navigateur Web incorporé"> +		<flyout_button.item label="Ouvrir dans mon navigateur Web" name="open_item"/> +		<flyout_button.item label="Ouvrir dans un navigateur externe" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Profil de fenêtres web"/> +</panel> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 16423503e7..943d1635cd 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -357,6 +357,24 @@ Veuillez réessayer de vous connecter dans une minute.  	<string name="TestingDisconnect">  		Test de déconnexion du client  	</string> +	<string name="SocialFacebookConnecting"> +		Connexion à Facebook… +	</string> +	<string name="SocialFacebookPosting"> +		Publication… +	</string> +	<string name="SocialFacebookDisconnecting"> +		Déconnexion de Facebook… +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Un problème est survenu lors de la connexion à Facebook. +	</string> +	<string name="SocialFacebookErrorPosting"> +		Un problème est survenu lors de la publication sur Facebook. +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Un problème est survenu lors de la déconnexion à Facebook. +	</string>  	<string name="SocialFlickrConnecting">  		Connexion à Flickr...  	</string> @@ -2579,9 +2597,21 @@ Si vous continuez de recevoir ce message, contactez l’assistance Second Life   	<string name="NoPicksClassifiedsText">  		Vous n'avez pas créé de favoris ni de petites annonces Cliquez sur le bouton Plus pour créer un favori ou une petite annonce.  	</string> +	<string name="NoPicksText"> +		Vous n'avez pas créé de favoris Cliquer sur le bouton Nouveau pour créer un favori +	</string> +	<string name="NoClassifiedsText"> +		Vous n'avez pas créé de petites annonces Cliquer sur le bouton Nouveau pour créer une petite annonce. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		L'utilisateur n'a ni favoris ni petites annonces.  	</string> +	<string name="NoAvatarPicksText"> +		L'utilisateur n'a pas de favoris +	</string> +	<string name="NoAvatarClassifiedsText"> +		L'utilisateur n'a pas de petites annonces +	</string>  	<string name="PicksClassifiedsLoadingText">  		Chargement...  	</string> @@ -4559,6 +4589,9 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  	<string name="share_alert">  		Faire glisser les objets de l'inventaire ici  	</string> +	<string name="facebook_post_success"> +		Vous avez publié sur Facebook. +	</string>  	<string name="flickr_post_success">  		Vous avez publié sur Flickr.  	</string> diff --git a/indra/newview/skins/default/xui/it/floater_preview_texture.xml b/indra/newview/skins/default/xui/it/floater_preview_texture.xml index 8e8d020067..02f15b6b7b 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Copia nell'Inventario  	</floater.string> -	<text name="desc txt"> -		Descrizione: -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		Antreprima rapporto di visualizzazione -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Anteprima con rapporto di visualizzazione fisso"> -		<combo_item name="Unconstrained"> -			Libero -		</combo_item> -		<combo_item name="1:1" tool_tip="Logo del gruppo o profilo nel mondo reale"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="Profilo [SECOND_LIFE]"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Annunci e inserzioni, punti di riferimento"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="Informazioni sul terreno"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Preferiti del Profilo"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Elimina" name="Discard"/> -	<button label="Salva con nome" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Descrizione: +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				Antreprima rapporto di visualizzazione +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Anteprima con rapporto di visualizzazione fisso"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Elimina" name="Discard"/> +			<button label="Salva con nome" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/it/floater_profile.xml b/indra/newview/skins/default/xui/it/floater_profile.xml new file mode 100644 index 0000000000..7e23f9bbbb --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profilo"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="Interessi" name="panel_profile_interests"/> +			<panel label="Preferiti" name="panel_profile_picks"/> +			<panel label="Annuncio" name="panel_profile_classifieds"/> +			<panel label="Vita reale" name="panel_profile_firstlife"/> +			<panel label="Note" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Salva modifiche al profilo e chiudi"/> +		<button label="Annulla" label_selected="Annulla" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml index d21c206f6f..c9f71a167e 100644 --- a/indra/newview/skins/default/xui/it/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		Invio e-mail in corso  	</string> +	<string name="facebook_progress_str"> +		Pubblicazione su Facebook in corso +	</string>  	<string name="profile_progress_str">  		Caricamento post  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Salvataggio sul computer in corso  	</string> +	<string name="facebook_succeeded_str"> +		Immagine caricata +	</string>  	<string name="profile_succeeded_str">  		Immagine caricata  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Salvato sul computer.  	</string> +	<string name="facebook_failed_str"> +		Caricamento immagine sul diario di Facebook non riuscito. +	</string>  	<string name="profile_failed_str">  		Caricamento immagine sul feed del profilo non riuscito.  	</string> diff --git a/indra/newview/skins/default/xui/it/menu_name_field.xml b/indra/newview/skins/default/xui/it/menu_name_field.xml new file mode 100644 index 0000000000..9ac863323c --- /dev/null +++ b/indra/newview/skins/default/xui/it/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Copia Nome Visualizzato" name="copy_display"/> +	<menu_item_call label="Copia Nome Agente" name="copy_name"/> +	<menu_item_call label="Copia ID Agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 1c43013255..a69fa07c50 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2685,6 +2685,9 @@ Prova a selezionare una parte di terreno più piccola.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/it/panel_edit_classified.xml b/indra/newview/skins/default/xui/it/panel_edit_classified.xml index ad827696ff..57e422a25b 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="Annulla" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_friends.xml b/indra/newview/skins/default/xui/it/panel_facebook_friends.xml index c1c0489f88..28769a010f 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_friends.xml @@ -1,12 +1,12 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_friends"> -	<string name="facebook_friends_empty" value="Attualmente non hai amici su Facebook che sono anche residenti in Second Life. Invita i tuoi amici di Facebook a partecipare a Second Life!"/> -	<string name="facebook_friends_no_connected" value="Attualmente non sei in collegamento con Facebook. Accedi alla scheda Stato per collegarti e attivare questa funzionalità."/> +	<string name="facebook_friends_empty" value="Attualmente non hai amici su Facebook che sono anche residenti Second Life. Invita ora i tuoi amici di Facebook a unirsi a Second Life!"/> +	<string name="facebook_friends_no_connected" value="Non sei connesso a Facebook. Accedi alla scheda Stato per collegarti e attivare questa funzionalità."/>  	<accordion name="friends_accordion">  		<accordion_tab name="tab_second_life_friends" title="Amici SL"/>  		<accordion_tab name="tab_suggested_friends" title="Aggiungi queste persone come amici SL"/>  	</accordion>  	<text name="facebook_friends_status"> -		Non in collegamento con Facebook. +		Non connesso a Facebook.  	</text>  </panel> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_photo.xml b/indra/newview/skins/default/xui/it/panel_facebook_photo.xml index 044b8b6164..8d66f35c3c 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_photo.xml @@ -1,13 +1,13 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_photo"> -	<combo_box name="resolution_combobox" tool_tip="Risoluzione immagini"> +	<combo_box name="resolution_combobox" tool_tip="Risoluzione immagine">  		<combo_box.item label="Finestra attuale" name="CurrentWindow"/>  		<combo_box.item label="640x480" name="640x480"/>  		<combo_box.item label="800x600" name="800x600"/>  		<combo_box.item label="1024x768" name="1024x768"/>  		<combo_box.item label="1200x630" name="1200x630"/>  	</combo_box> -	<combo_box name="filters_combobox" tool_tip="Filtri immagini"> +	<combo_box name="filters_combobox" tool_tip="Filtri immagine">  		<combo_box.item label="Nessun filtro" name="NoFilter"/>  	</combo_box>  	<button label="Aggiorna" name="new_snapshot_btn" tool_tip="Fai clic per aggiornare"/> diff --git a/indra/newview/skins/default/xui/it/panel_facebook_status.xml b/indra/newview/skins/default/xui/it/panel_facebook_status.xml index 9b5171043a..7fb1cec78e 100644 --- a/indra/newview/skins/default/xui/it/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/it/panel_facebook_status.xml @@ -1,13 +1,13 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_status"> -	<string name="facebook_connected" value="Sei in collegamento con Facebook come:"/> -	<string name="facebook_disconnected" value="Non in collegamento con Facebook"/> +	<string name="facebook_connected" value="Sei connesso a Facebook come:"/> +	<string name="facebook_disconnected" value="Non connesso a Facebook"/>  	<text name="account_caption_label"> -		Non in collegamento con Facebook. +		Non connesso a Facebook.  	</text>  	<panel name="panel_buttons"> -		<button label="Collegamento..." name="connect_btn"/> -		<button label="Interrompi collegamento" name="disconnect_btn"/> +		<button label="Connessione in corso..." name="connect_btn"/> +		<button label="Disconnetti" name="disconnect_btn"/>  		<text name="account_learn_more_label">  			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Come pubblicare su Facebook]  		</text> diff --git a/indra/newview/skins/default/xui/it/panel_group_general.xml b/indra/newview/skins/default/xui/it/panel_group_general.xml index 60028e6098..168524d1ad 100644 --- a/indra/newview/skins/default/xui/it/panel_group_general.xml +++ b/indra/newview/skins/default/xui/it/panel_group_general.xml @@ -46,7 +46,7 @@ Muovi il tuo mouse sopra le opzioni per maggiore aiuto.  		<check_box label="Chiunque può aderire" name="open_enrollement" tool_tip="Imposta se questo gruppo permette ai nuovi membri di aderire senza essere invitati."/>  		<check_box label="Quota di adesione" name="check_enrollment_fee" tool_tip="Imposta se richiedere una tassa d'iscrizione per aderire al gruppo"/>  		<spinner label="L$" left_delta="136" name="spin_enrollment_fee" tool_tip="I nuovi soci devono pagare questa tassa d'iscrizione quando è selezionata." width="60"/> -		<combo_box name="group_mature_check" tool_tip="Le categorie di accesso definiscono il tipo di contenuti e di comportamenti ammessi in un gruppo"> +		<combo_box name="group_mature_check" tool_tip="Determina se il tuo gruppo contiene informazioni contrassegnate come Moderate opppure no">  			<combo_item name="select_mature">  				- Seleziona categoria di accesso -  			</combo_item> diff --git a/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml new file mode 100644 index 0000000000..72e644008c --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Sconosciuto"/> +	<button name="info_btn" tool_tip="Maggiori informazioni"/> +	<button name="profile_btn" tool_tip="Vedi profilo"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_me.xml b/indra/newview/skins/default/xui/it/panel_me.xml deleted file mode 100644 index a134f6f1de..0000000000 --- a/indra/newview/skins/default/xui/it/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Il mio profilo" name="panel_me"> -	<panel label="I MIEI PREFERITI" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml index 3df2368ae0..9eb93a26e5 100644 --- a/indra/newview/skins/default/xui/it/panel_people.xml +++ b/indra/newview/skins/default/xui/it/panel_people.xml @@ -40,6 +40,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Online"/>  				<accordion_tab name="tab_all" title="Tutto"/> +				<accordion_tab name="tab_suggested_friends" title="Persone che potresti voler aggiungere agli amici"/>  			</accordion>  		</panel>  		<panel label="GRUPPI" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/it/panel_profile_classified.xml b/indra/newview/skins/default/xui/it/panel_profile_classified.xml new file mode 100644 index 0000000000..3c88fbe92f --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Moderato +	</panel.string> +	<panel.string name="type_pg"> +		Contenuto Generale +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] teletrasporto, [MAP] mappa, [PROFILE] profilo +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Abilitato +	</panel.string> +	<panel.string name="auto_renew_off"> +		Disabilitato +	</panel.string> +	<panel.string name="location_notice"> +		(si aggiornerà dopo il salvataggio) +	</panel.string> +	<string name="publish_label"> +		Pubblica +	</string> +	<string name="save_label"> +		Salva +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Fai clic per selezionare un'immagine"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Posizione:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Tipo di contenuto:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Categoria:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Data di creazione:"/> +					<text_editor name="creation_date" tool_tip="Data di creazione" value="[date]"/> +					<text name="price_for_listing_label" value="Prezzo per inserzione:"/> +					<text_editor name="price_for_listing" tool_tip="Prezzo per inserzione."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Clic:"/> +					<text_editor name="click_through_text" tool_tip="Numero di clic" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Rinnovo automatico:"/> +					<text name="auto_renew" value="Abilitato"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Descrizione:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Titolo: +				</text> +				<text name="description_label"> +					Descrizione: +				</text> +				<text name="location_label"> +					Posizione: +				</text> +				<text name="classified_location_edit"> +					caricamento in corso... +				</text> +				<button label="Imposta come Luogo Attuale" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Categoria:"/> +				<text name="content_type_label" value="Tipo di contenuto:"/> +				<icons_combo_box label="Contenuto Generale" name="content_type_edit"> +					<icons_combo_box.item label="Contenuto Moderato" name="mature_ci" value="Per adulti"/> +					<icons_combo_box.item label="Contenuto Generale" name="pg_ci" value="PG"/> +				</icons_combo_box> +				<check_box label="Rinnovo automatico ogni settimana" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Prezzo per inserzione:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Prezzo per inserzione." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Teletrasporto" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Mappa" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Modifica" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Annulla" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml new file mode 100644 index 0000000000..6fc0fd0729 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Annuncio" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="Nessuno annuncio"/> +	<button label="Nuovo..." name="new_btn"/> +	<button label="Elimina..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Caricamento in corso... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml new file mode 100644 index 0000000000..bf8ccef273 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profilo" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/it/panel_profile_interests.xml b/indra/newview/skins/default/xui/it/panel_profile_interests.xml new file mode 100644 index 0000000000..9fe7331e5c --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interessi" name="panel_profile_interests"> +	<text name="I Want To:"> +		Desidero: +	</text> +	<check_box label="Costruire" name="chk0"/> +	<check_box label="Esplorare" name="chk1"/> +	<check_box label="Incontrare" name="chk2"/> +	<check_box label="Essere assunto" name="chk6"/> +	<check_box label="Gruppo" name="chk3"/> +	<check_box label="Acquistare" name="chk4"/> +	<check_box label="Vendere" name="chk5"/> +	<check_box label="Assumere" name="chk7"/> +	<line_editor name="want_to_edit"> +		(caricamento in corso...) +	</line_editor> +	<text name="Skills:"> +		Abilità: +	</text> +	<check_box label="Texture" name="schk0"/> +	<check_box label="Architettura" name="schk1"/> +	<check_box label="Realizzazione modelli 3D" name="schk3"/> +	<check_box label="Organizzazione eventi" name="schk2"/> +	<check_box label="Scripting" name="schk4"/> +	<check_box label="Personaggi personalizzati" name="schk5"/> +	<line_editor name="skills_edit"> +		(caricamento in corso...) +	</line_editor> +	<text name="Languages:"> +		Lingue: +	</text> +	<line_editor name="languages_edit"> +		(caricamento in corso...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_notes.xml b/indra/newview/skins/default/xui/it/panel_profile_notes.xml new file mode 100644 index 0000000000..abd5a347c3 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Note e Privacy" name="panel_notes"> +	<text name="status_message" value="Annotazioni private su questo avatar:"/> +	<text name="status_message2" value="Consenti a questo avatar di:"/> +	<check_box label="Vedere quando sono in linea" name="status_check"/> +	<check_box label="Trovarmi sulla mappa del mondo" name="map_check"/> +	<check_box label="Modificare, eliminare o prendere i miei oggetti" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_pick.xml b/indra/newview/skins/default/xui/it/panel_profile_pick.xml new file mode 100644 index 0000000000..5d2b145565 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(si aggiornerà dopo il salvataggio) +	</panel.string> +	<line_editor name="pick_location"> +		Caricamento in corso... +	</line_editor> +	<button label="Teletrasporto" name="teleport_btn"/> +	<button label="Mostra sulla mappa" name="show_on_map_btn"/> +	<button label="Imposta Luogo" name="set_to_curr_location_btn" tool_tip="Imposta come Luogo Attuale"/> +	<button label="Salva Luogo preferito" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_picks.xml b/indra/newview/skins/default/xui/it/panel_profile_picks.xml new file mode 100644 index 0000000000..37cffcf622 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Preferiti" name="panel_picks"> +	<string name="no_picks" value="Nessun preferito"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Comunica a tutti quali sono i tuoi posti preferiti in Second Life. +	</text> +	<button label="Nuovo..." name="new_btn"/> +	<button label="Elimina..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Caricamento in corso... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml new file mode 100644 index 0000000000..47af1960a5 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profilo" name="panel_profile"> +	<string name="status_online"> +		Ora in linea +	</string> +	<string name="status_offline"> +		Ora non in linea +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Nessuno"/> +	<string name="no_group_text" value="Nessuno"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Sviluppatore"/> +	<string name="FSSupp" value="Assistenza"/> +	<string name="FSQualityAssurance" value="Bug Hunter"/> +	<string name="FSGW" value="Gateway"/> +	<text name="name_label" value="Nome:"/> +	<button label="Nome:" name="set_name" tool_tip="Imposta nome visualizzato"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(caricamento in corso...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Stato Sconosciuto"/> +			<text name="label" value="Compleanno Second Life:"/> +			<text name="label2" value="Account:"/> +			<text name="partner_label" value="Partner:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Gruppi:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Invita al gruppo:"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="Informazioni generali:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Consegna oggetto:"/> +			<text name="Give inventory" tool_tip="Rilascia gli oggetti dell’inventario per consegnarli a questa persona."> +				Rilascia l’oggetto dell’inventario qui. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Trova sulla mappa" label_selected="Trova sulla mappa" name="show_on_map_btn" tool_tip="Localizza il Residente sulla mappa"/> +			<button label="Paga" label_selected="Paga" name="pay" tool_tip="Paga del denaro al Residente"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Offri Teletrasporto" label_selected="Offri Teletrasporto" name="teleport" tool_tip="Offri il teletrasporto al Residente"/> +			<button label="Messaggio istantaneo" label_selected="Messaggio istantaneo" name="im" tool_tip="Apri sessione di messaggistica istantanea"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Aggiungi come amico" label_selected="Aggiungi come amico" name="add_friend" tool_tip="Offri amicizia al Residente"/> +			<button label="Blocca" name="block" tool_tip="Blocca questo Residente"/> +			<button label="Sblocca" name="unblock" tool_tip="Sblocca questo Residente"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Mostra nella ricerca" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_profile_web.xml b/indra/newview/skins/default/xui/it/panel_profile_web.xml new file mode 100644 index 0000000000..0c3a8ddcf5 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Tempo di caricamento: [TIME] secondi"/> +	<line_editor name="url_edit"> +		(caricamento in corso..) +	</line_editor> +	<flyout_button label="Carica" name="load" tool_tip="Carica la pagina profilo con il browser Web integrato."> +		<flyout_button.item label="Apri browser interno" name="open_item"/> +		<flyout_button.item label="Apri browser esterno" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Profilo web a comparsa"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index ea972e5a13..52f5f7af18 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -353,6 +353,24 @@ Prova ad accedere nuovamente tra un minuto.  	<string name="TestingDisconnect">  		Verifica scollegamento viewer  	</string> +	<string name="SocialFacebookConnecting"> +		Connessione a Facebook in corso... +	</string> +	<string name="SocialFacebookPosting"> +		Caricamento post... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Disconnessione da Facebook in corso... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Problemi con la connessione a Facebook +	</string> +	<string name="SocialFacebookErrorPosting"> +		Problemi con la connessione a Facebook +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Problemi con la disconnessione da Facebook +	</string>  	<string name="SocialFlickrConnecting">  		Collegamento a Flickr...  	</string> @@ -2557,9 +2575,21 @@ Se continui a ricevere questo messaggio, contatta l'assistenza Second Life  	<string name="NoPicksClassifiedsText">  		Non hai creato luoghi preferiti né inserzioni. Clicca il pulsante + qui sotto per creare un luogo preferito o un'inserzione.  	</string> +	<string name="NoPicksText"> +		Non hai creato Luoghi preferiti. Fai clic sul pulsante Nuovo per creare un Luogo preferito. +	</string> +	<string name="NoClassifiedsText"> +		Non hai creato Annunci. Fai clic sul pulsante Nuovo per creare un Annuncio. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		L'utente non ha luoghi preferiti né inserzioni  	</string> +	<string name="NoAvatarPicksText"> +		L'utente non ha luoghi preferiti +	</string> +	<string name="NoAvatarClassifiedsText"> +		L'utente non ha annunci +	</string>  	<string name="PicksClassifiedsLoadingText">  		Caricamento in corso...  	</string> @@ -4474,6 +4504,9 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].  	<string name="inventory_folder_offered-im">  		Offerta cartella di inventario "[ITEM_NAME]"  	</string> +	<string name="facebook_post_success"> +		Hai pubblicato su Facebook. +	</string>  	<string name="flickr_post_success">  		Hai pubblicato su Flickr.  	</string> diff --git a/indra/newview/skins/default/xui/ja/floater_picks.xml b/indra/newview/skins/default/xui/ja/floater_picks.xml deleted file mode 100644 index 359585eb86..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="ピック"/> diff --git a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml index 4617fd1d92..66ef13948a 100644 --- a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		インベントリにコピー  	</floater.string> -	<text name="desc txt"> -		説明: -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		縦横比のプレビュー -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="固定した縦横比のプレビュー"> -		<combo_item name="Unconstrained"> -			非拘束 -		</combo_item> -		<combo_item name="1:1" tool_tip="グループ記章か現実世界のプロフィール"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="[SECOND_LIFE] プロフィール"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="クラシファイド広告、検索一覧、ランドマーク"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="土地情報"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="プロフィールのピック"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="処分する" name="Discard"/> -	<button label="別名で保存" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				説明: +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				縦横比のプレビュー +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="固定した縦横比のプレビュー"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="処分する" name="Discard"/> +			<button label="別名で保存" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/ja/floater_profile.xml b/indra/newview/skins/default/xui/ja/floater_profile.xml new file mode 100644 index 0000000000..e06cd6e8f6 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="プロフィール"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="趣味" name="panel_profile_interests"/> +			<panel label="ピック" name="panel_profile_picks"/> +			<panel label="クラシファイド広告" name="panel_profile_classifieds"/> +			<panel label="リアルライフ(現実世界)" name="panel_profile_firstlife"/> +			<panel label="メモ" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="プロフィールの変更を保存して閉じる"/> +		<button label="キャンセル" label_selected="キャンセル" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_snapshot.xml b/indra/newview/skins/default/xui/ja/floater_snapshot.xml index f04193d034..64f292c75c 100644 --- a/indra/newview/skins/default/xui/ja/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/ja/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		メールの送信  	</string> +	<string name="facebook_progress_str"> +		Facebook へ投稿中 +	</string>  	<string name="profile_progress_str">  		投稿  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		コンピュータに保存  	</string> +	<string name="facebook_succeeded_str"> +		画像がアップロードされました +	</string>  	<string name="profile_succeeded_str">  		画像がアップロードされました  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		コンピュータに保存されました  	</string> +	<string name="facebook_failed_str"> +		Facebook のタイムラインに画像をアップロードできませんでした。 +	</string>  	<string name="profile_failed_str">  		プロフィールフィードに画像をアップロードできませんでした。  	</string> diff --git a/indra/newview/skins/default/xui/ja/menu_name_field.xml b/indra/newview/skins/default/xui/ja/menu_name_field.xml new file mode 100644 index 0000000000..8c37d95073 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="表示名をコピー" name="copy_display"/> +	<menu_item_call label="エージェント名をコピー" name="copy_name"/> +	<menu_item_call label="エージェント ID をコピー" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index a66552d3fe..92952f4c8a 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2727,6 +2727,9 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml index cf5f2489f1..619e9de65a 100644 --- a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="キャンセル" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml b/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml index c48f13456b..ee57d178e8 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_photo.xml @@ -16,5 +16,5 @@  		コメント (オプション):  	</text>  	<button label="投稿" name="post_photo_btn"/> -	<button label="取り消し" name="cancel_photo_btn"/> +	<button label="キャンセル" name="cancel_photo_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_place.xml b/indra/newview/skins/default/xui/ja/panel_facebook_place.xml index 61138f90c1..e97422a9df 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_place.xml @@ -5,5 +5,5 @@  	</text>  	<check_box initial_value="false" label="場所の俯瞰図を含める" name="add_place_view_cb"/>  	<button label="投稿" name="post_place_btn"/> -	<button label="取り消し" name="cancel_place_btn"/> +	<button label="キャンセル" name="cancel_place_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_facebook_status.xml b/indra/newview/skins/default/xui/ja/panel_facebook_status.xml index 9d962c9d62..1f48c9c8c7 100644 --- a/indra/newview/skins/default/xui/ja/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/ja/panel_facebook_status.xml @@ -9,12 +9,12 @@  		<button label="接続..." name="connect_btn"/>  		<button label="切断" name="disconnect_btn"/>  		<text name="account_learn_more_label"> -			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Facebook への投稿について]] +			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Facebook への投稿について]  		</text>  	</panel>  	<text name="status_caption_label">  		今、何を考えている?  	</text>  	<button label="投稿" name="post_status_btn"/> -	<button label="取り消し" name="cancel_status_btn"/> +	<button label="キャンセル" name="cancel_status_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml new file mode 100644 index 0000000000..77d3d8f391 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="不明"/> +	<button name="info_btn" tool_tip="詳細"/> +	<button name="profile_btn" tool_tip="プロフィールの表示"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml deleted file mode 100644 index 9b1cf1c8a4..0000000000 --- a/indra/newview/skins/default/xui/ja/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="プロフィール" name="panel_me"> -	<panel label="マイ ピック" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_people.xml b/indra/newview/skins/default/xui/ja/panel_people.xml index 0a295855d0..be00a3c122 100644 --- a/indra/newview/skins/default/xui/ja/panel_people.xml +++ b/indra/newview/skins/default/xui/ja/panel_people.xml @@ -40,6 +40,7 @@  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="オンライン"/>  				<accordion_tab name="tab_all" title="全員"/> +				<accordion_tab name="tab_suggested_friends" title="友だちになりたくない人"/>  			</accordion>  		</panel>  		<panel label="グループ" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_classified.xml b/indra/newview/skins/default/xui/ja/panel_profile_classified.xml new file mode 100644 index 0000000000..2d1bc07e2c --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Moderate +	</panel.string> +	<panel.string name="type_pg"> +		General コンテンツ +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] テレポート、 [MAP] 地図、 [PROFILE] プロフィール +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		有効 +	</panel.string> +	<panel.string name="auto_renew_off"> +		無効 +	</panel.string> +	<panel.string name="location_notice"> +		(掲載後更新) +	</panel.string> +	<string name="publish_label"> +		掲載 +	</string> +	<string name="save_label"> +		保存 +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="クリックして画像を選択"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="場所:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="コンテンツの種類:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="カテゴリ:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="制作日:"/> +					<text_editor name="creation_date" tool_tip="制作日" value="[date]"/> +					<text name="price_for_listing_label" value="掲載価格:"/> +					<text_editor name="price_for_listing" tool_tip="掲載価格。"> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="クリック数:"/> +					<text_editor name="click_through_text" tool_tip="クリックスルーデータ" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="自動更新:"/> +					<text name="auto_renew" value="有効"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="説明:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					タイトル: +				</text> +				<text name="description_label"> +					説明: +				</text> +				<text name="location_label"> +					場所: +				</text> +				<text name="classified_location_edit"> +					ロード中... +				</text> +				<button label="現在地に設定" name="set_to_curr_location_btn"/> +				<text name="category_label" value="カテゴリ:"/> +				<text name="content_type_label" value="コンテンツの種類:"/> +				<icons_combo_box label="General コンテンツ" name="content_type_edit"> +					<icons_combo_box.item label="Moderate コンテンツ" name="mature_ci" value="Mature"/> +					<icons_combo_box.item label="General コンテンツ" name="pg_ci" value="PG"/> +				</icons_combo_box> +				<check_box label="毎週自動更新" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="掲載価格:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="掲載価格。" value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="テレポート" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="地図" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="編集" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="キャンセル" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml new file mode 100644 index 0000000000..1980c0fa62 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="クラシファイド広告" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="クラシファイド広告なし"/> +	<button label="新規…" name="new_btn"/> +	<button label="削除…" name="delete_btn"/> +	<text name="classifieds_panel_text"> +		ロード中... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml new file mode 100644 index 0000000000..a4ee262cb3 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="プロフィール" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_interests.xml b/indra/newview/skins/default/xui/ja/panel_profile_interests.xml new file mode 100644 index 0000000000..93cde6ffec --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="趣味" name="panel_profile_interests"> +	<text name="I Want To:"> +		次の内容を実行: +	</text> +	<check_box label="作る" name="chk0"/> +	<check_box label="探検" name="chk1"/> +	<check_box label="出会う" name="chk2"/> +	<check_box label="雇ってもらう" name="chk6"/> +	<check_box label="グループ" name="chk3"/> +	<check_box label="買う" name="chk4"/> +	<check_box label="販売する" name="chk5"/> +	<check_box label="雇う" name="chk7"/> +	<line_editor name="want_to_edit"> +		(ロード中...) +	</line_editor> +	<text name="Skills:"> +		スキル: +	</text> +	<check_box label="テクスチャ" name="schk0"/> +	<check_box label="建築" name="schk1"/> +	<check_box label="モデリング" name="schk3"/> +	<check_box label="イベント計画" name="schk2"/> +	<check_box label="スクリプト" name="schk4"/> +	<check_box label="キャラクターのカスタマイズ" name="schk5"/> +	<line_editor name="skills_edit"> +		(ロード中...) +	</line_editor> +	<text name="Languages:"> +		言語: +	</text> +	<line_editor name="languages_edit"> +		(ロード中...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_notes.xml b/indra/newview/skins/default/xui/ja/panel_profile_notes.xml new file mode 100644 index 0000000000..4b4e0d5e4e --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="メモとプライバシー" name="panel_notes"> +	<text name="status_message" value="このアバターのプライベートメモ:"/> +	<text name="status_message2" value="このアバターに次の許可を与える:"/> +	<check_box label="自分のオンラインステータスを表示する" name="status_check"/> +	<check_box label="世界地図で自分を探せるようにする" name="map_check"/> +	<check_box label="自分のオブジェクトを編集・削除・取得できるようにする" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_pick.xml b/indra/newview/skins/default/xui/ja/panel_profile_pick.xml new file mode 100644 index 0000000000..0a20c04ad6 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(掲載後更新) +	</panel.string> +	<line_editor name="pick_location"> +		ロード中... +	</line_editor> +	<button label="テレポート" name="teleport_btn"/> +	<button label="地図に表示" name="show_on_map_btn"/> +	<button label="場所を設定" name="set_to_curr_location_btn" tool_tip="現在地に設定"/> +	<button label="ピックを保存" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_picks.xml b/indra/newview/skins/default/xui/ja/panel_profile_picks.xml new file mode 100644 index 0000000000..4cbfadd09d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="ピック" name="panel_picks"> +	<string name="no_picks" value="ピックなし"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Second Life のお気に入りの場所を紹介しましょう。 +	</text> +	<button label="新規…" name="new_btn"/> +	<button label="削除…" name="delete_btn"/> +	<text name="picks_panel_text"> +		ロード中... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml new file mode 100644 index 0000000000..5470dc6c82 --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="プロフィール" name="panel_profile"> +	<string name="status_online"> +		オンライン中 +	</string> +	<string name="status_offline"> +		オフライン中 +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="なし"/> +	<string name="no_group_text" value="なし"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="開発者"/> +	<string name="FSSupp" value="サポート"/> +	<string name="FSQualityAssurance" value="バグハンター"/> +	<string name="FSGW" value="ゲートウェイ"/> +	<text name="name_label" value="名前:"/> +	<button label="名前:" name="set_name" tool_tip="表示名を設定"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(ロード中...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="ステータス不明"/> +			<text name="label" value="Second Life 生年月日:"/> +			<text name="label2" value="アカウント:"/> +			<text name="partner_label" value="パートナー:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="グループ:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="グループに招待"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="詳細:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="アイテムを渡す:"/> +			<text name="Give inventory" tool_tip="インベントリのアイテムをここにドロップしてこの人に渡します。"> +				インベントリのアイテムをここにドロップしてください。 +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="地図上で見つける" label_selected="地図上で見つける" name="show_on_map_btn" tool_tip="住人を地図上で探す"/> +			<button label="お金を払う" label_selected="お金を払う" name="pay" tool_tip="住人にお金を支払う"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="テレポートを送る" label_selected="テレポートを送る" name="teleport" tool_tip="住人にテレポートを送る"/> +			<button label="インスタントメッセージ" label_selected="インスタントメッセージ" name="im" tool_tip="インスタントメッセージを開きます"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="フレンド登録" label_selected="フレンド登録" name="add_friend" tool_tip="フレンド登録を申し出ます"/> +			<button label="ブロック" name="block" tool_tip="この住人をブロックする"/> +			<button label="ブロック解除" name="unblock" tool_tip="この住人のブロックを解除する"/> +		</layout_panel> +	</layout_stack> +	<check_box label="検索に表示" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_web.xml b/indra/newview/skins/default/xui/ja/panel_profile_web.xml new file mode 100644 index 0000000000..4f56a7e98d --- /dev/null +++ b/indra/newview/skins/default/xui/ja/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="ロード時間:[TIME] 秒"/> +	<line_editor name="url_edit"> +		(ロード中...) +	</line_editor> +	<flyout_button label="ロード" name="load" tool_tip="このプロフィールページを、組み込み Web ブラウザでロードします。"> +		<flyout_button.item label="ビューワ内のブラウザを開く" name="open_item"/> +		<flyout_button.item label="外部ブラウザを開く" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Web プロフィールのポップアウト"/> +</panel> diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml index 04dfc0176d..f222a4d61a 100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml @@ -3,7 +3,7 @@  	<button label="ディスクに保存" name="save_to_computer_btn"/>  	<button label="持ち物に保存(L$[AMOUNT])" name="save_to_inventory_btn"/>  	<button label="プロフィールフィードで共有する" name="save_to_profile_btn"/> -	<button label="Facebook で共有する" name="send_to_facebook_btn"/> +	<button label="Facebook でシェア" name="send_to_facebook_btn"/>  	<button label="Twitter で共有する" name="send_to_twitter_btn"/>  	<button label="Flickr で共有する" name="send_to_flickr_btn"/>  	<button label="メールにより送信" name="save_to_email_btn"/> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 344f9fcd94..c5bba021ac 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -356,6 +356,24 @@ support@secondlife.com にお問い合わせください。  	<string name="TestingDisconnect">  		ビューワの接続を切るテスト中  	</string> +	<string name="SocialFacebookConnecting"> +		Facebook に接続中... +	</string> +	<string name="SocialFacebookPosting"> +		投稿中... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Facebook から切断中... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Facebook への接続時のエラー +	</string> +	<string name="SocialFacebookErrorPosting"> +		Facebook への投稿時のエラー +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Facebook からの切断時のエラー +	</string>  	<string name="SocialFlickrConnecting">  		Flickr に接続中...  	</string> @@ -2577,9 +2595,21 @@ support@secondlife.com にお問い合わせください。  	<string name="NoPicksClassifiedsText">  		ピックやクラシファイド広告を作成していません。 作成するには、下にある「プラス」ボタンをクリックします。  	</string> +	<string name="NoPicksText"> +		ピックを作成していません。[新規] ボタンをクリックしてピックを作成する。 +	</string> +	<string name="NoClassifiedsText"> +		クラシファイド広告を作成していません。[新規] ボタンをクリックしてクラシファイド広告を作成する。 +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		ピック、またはクラシファイド広告がありません  	</string> +	<string name="NoAvatarPicksText"> +		ピックがありません +	</string> +	<string name="NoAvatarClassifiedsText"> +		クラシファイド広告がありません +	</string>  	<string name="PicksClassifiedsLoadingText">  		ローディング...  	</string> @@ -4557,6 +4587,9 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ  	<string name="share_alert">  		インベントリからここにアイテムをドラッグします  	</string> +	<string name="facebook_post_success"> +		Facebook に投稿しました。 +	</string>  	<string name="flickr_post_success">  		Flickr に投稿しました。  	</string> diff --git a/indra/newview/skins/default/xui/pl/floater_picks.xml b/indra/newview/skins/default/xui/pl/floater_picks.xml deleted file mode 100644 index a329e834db..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<floater name="floater_picks" title="Miejsca" /> diff --git a/indra/newview/skins/default/xui/pl/panel_me.xml b/indra/newview/skins/default/xui/pl/panel_me.xml deleted file mode 100644 index 431929420a..0000000000 --- a/indra/newview/skins/default/xui/pl/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel label="Mój Profil" name="panel_me"> -	<panel label="MIEJSCA" name="panel_picks" /> -</panel> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml index c50d7dcda0..a43dec4e7b 100644 --- a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@  	<check_box label="Gestos" name="check_gesture"/>  	<check_box label="Landmarks" name="check_landmark"/>  	<check_box label="Anotações" name="check_notecard"/> -	<check_box label="Meshes:" name="check_mesh"/> +	<check_box label="Malhas" name="check_mesh"/>  	<check_box label="Objetos" name="check_object"/>  	<check_box label="Scripts" name="check_script"/>  	<check_box label="Sons" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/pt/floater_picks.xml b/indra/newview/skins/default/xui/pt/floater_picks.xml deleted file mode 100644 index 9766196319..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Destaques"/> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_texture.xml b/indra/newview/skins/default/xui/pt/floater_preview_texture.xml index 6f39635240..90102023a3 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Copiar para inventário  	</floater.string> -	<text name="desc txt"> -		Descrição: -	</text> -	<text name="dimensions"> -		[WIDTH]px x [HEIGHT]px -	</text> -	<text name="aspect_ratio"> -		Visualizar relação de aspecto -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Visualizar com proporção de aspecto fixa"> -		<combo_item name="Unconstrained"> -			Sem limites -		</combo_item> -		<combo_item name="1:1" tool_tip="Símbolo ou perfil RW do grupo"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="[SECOND_LIFE] perfil"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Procurar anúncios classificados e marcos"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="Sobre terrenos"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Perfis destacados"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Descartar" name="Discard"/> -	<button label="Salvar como" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Descrição: +			</text> +			<text name="dimensions"> +				[WIDTH]px x [HEIGHT]px +			</text> +			<text name="aspect_ratio"> +				Visualizar relação de aspecto +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Visualizar com proporção de aspecto fixa"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Descartar" name="Discard"/> +			<button label="Salvar como" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_profile.xml b/indra/newview/skins/default/xui/pt/floater_profile.xml new file mode 100644 index 0000000000..0327211d8f --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Perfil"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="Interesses" name="panel_profile_interests"/> +			<panel label="Destaques" name="panel_profile_picks"/> +			<panel label="Anúncio" name="panel_profile_classifieds"/> +			<panel label="Vida real" name="panel_profile_firstlife"/> +			<panel label="Observações" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Salvar alterações do perfil e fechar"/> +		<button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml index e3812ed708..89901b539f 100644 --- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		Enviando e-mail  	</string> +	<string name="facebook_progress_str"> +		Como publicar no Facebook +	</string>  	<string name="profile_progress_str">  		Postando  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Salvo no computador  	</string> +	<string name="facebook_succeeded_str"> +		Imagem carregada +	</string>  	<string name="profile_succeeded_str">  		Imagem carregada  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Salvo no computador!  	</string> +	<string name="facebook_failed_str"> +		Falha ao carregar a imagem na sua linha do tempo no Facebook. +	</string>  	<string name="profile_failed_str">  		Falha ao carregar a imagem no feed do seu perfil.  	</string> diff --git a/indra/newview/skins/default/xui/pt/menu_name_field.xml b/indra/newview/skins/default/xui/pt/menu_name_field.xml new file mode 100644 index 0000000000..2157de9813 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Exibir Cópia do Nome" name="copy_display"/> +	<menu_item_call label="Copiar Nome do Agente" name="copy_name"/> +	<menu_item_call label="Copiar Id do Agente" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index bd1185bdd2..733ec2c709 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2673,6 +2673,9 @@ Selecione só um objeto.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_classified.xml b/indra/newview/skins/default/xui/pt/panel_edit_classified.xml index 23e00bfc3a..7b27c811f5 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="Cancelar" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/pt/panel_group_general.xml b/indra/newview/skins/default/xui/pt/panel_group_general.xml index 64a7d13fdb..f6c6d11b87 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_general.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_general.xml @@ -46,7 +46,7 @@ Para obter mais ajuda, passe o mouse sobre as opções.  		<check_box label="Qualquer um pode entrar" name="open_enrollement" tool_tip="Controla a entrada de novos membros, com ou sem convite."/>  		<check_box label="Taxa de inscrição" name="check_enrollment_fee" tool_tip="Controla a cobrança de uma taxa de associação ao grupo."/>  		<spinner label="L$" left_delta="120" name="spin_enrollment_fee" tool_tip="Se a opção 'Taxa de associação' estiver marcada, novos membros precisam pagar o valor definido para entrar no grupo." width="60"/> -		<combo_box name="group_mature_check" tool_tip="Os níveis de maturidade determinam o tipo de conteúdo e comportamento permitidos em um grupo" width="170"> +		<combo_box name="group_mature_check" tool_tip="Definir se o seu grupo contém informações classificadas como Moderado" width="170">  			<combo_item name="select_mature">  				- Selecione o nível de maturidade -  			</combo_item> diff --git a/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml new file mode 100644 index 0000000000..0490878507 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Desconhecido"/> +	<button name="info_btn" tool_tip="Mais informações"/> +	<button name="profile_btn" tool_tip="Ver perfil"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_me.xml b/indra/newview/skins/default/xui/pt/panel_me.xml deleted file mode 100644 index 281c886bd4..0000000000 --- a/indra/newview/skins/default/xui/pt/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Meu perfil" name="panel_me"> -	<panel label="MEUS DESTAQUES" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_people.xml b/indra/newview/skins/default/xui/pt/panel_people.xml index 2ef01841c5..ce50449b03 100644 --- a/indra/newview/skins/default/xui/pt/panel_people.xml +++ b/indra/newview/skins/default/xui/pt/panel_people.xml @@ -40,6 +40,7 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Online"/>  				<accordion_tab name="tab_all" title="Todos"/> +				<accordion_tab name="tab_suggested_friends" title="Pessoas que talvez você deseje adicionar"/>  			</accordion>  		</panel>  		<panel label="GRUPOS" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_classified.xml b/indra/newview/skins/default/xui/pt/panel_profile_classified.xml new file mode 100644 index 0000000000..b43a0ad9f2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Moderado +	</panel.string> +	<panel.string name="type_pg"> +		Conteúdo Geral +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE]- +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] teletransporte, [MAP] mapa, [PROFILE] perfil +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Ativado +	</panel.string> +	<panel.string name="auto_renew_off"> +		Desativado +	</panel.string> +	<panel.string name="location_notice"> +		(salvar para atualizar) +	</panel.string> +	<string name="publish_label"> +		Publicar +	</string> +	<string name="save_label"> +		Salvar +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Selecione uma imagem"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Localização:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Tipo de conteúdo:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Categoria:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Data de criação:"/> +					<text_editor name="creation_date" tool_tip="Data de criação" value="[date]"/> +					<text name="price_for_listing_label" value="Preço do anúncio:"/> +					<text_editor name="price_for_listing" tool_tip="Preço do anúncio."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Cliques:"/> +					<text_editor name="click_through_text" tool_tip="Dados de click-through" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Renovação automática:"/> +					<text name="auto_renew" value="Ativado"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Descrição:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Título: +				</text> +				<text name="description_label"> +					Descrição: +				</text> +				<text name="location_label"> +					Localização: +				</text> +				<text name="classified_location_edit"> +					Carregando... +				</text> +				<button label="Usar configuração local" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Categoria:"/> +				<text name="content_type_label" value="Tipo de conteúdo:"/> +				<icons_combo_box label="Conteúdo Geral" name="content_type_edit"> +					<icons_combo_box.item label="Conteúdo Moderado" name="mature_ci" value="Moderado"/> +					<icons_combo_box.item label="Conteúdo Geral" name="pg_ci" value="Adequado para menores"/> +				</icons_combo_box> +				<check_box label="Renovar automaticamente todas as semanas" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Preço do anúncio:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Preço do anúncio." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Teletransportar" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Mapa" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Editar" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Cancelar" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml new file mode 100644 index 0000000000..f8369954fd --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anúncio" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="Nenhum classificado"/> +	<button label="Novo..." name="new_btn"/> +	<button label="Excluir..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Carregando... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/it/floater_picks.xml b/indra/newview/skins/default/xui/pt/panel_profile_firstlife.xml index dfc539da66..0fb502e441 100644 --- a/indra/newview/skins/default/xui/it/floater_picks.xml +++ b/indra/newview/skins/default/xui/pt/panel_profile_firstlife.xml @@ -1,2 +1,2 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Preferiti"/> +<panel label="Perfil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_interests.xml b/indra/newview/skins/default/xui/pt/panel_profile_interests.xml new file mode 100644 index 0000000000..edf74115f2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Interesses" name="panel_profile_interests"> +	<text name="I Want To:"> +		Quero: +	</text> +	<check_box label="Crie" name="chk0"/> +	<check_box label="Explore" name="chk1"/> +	<check_box label="Encontrar" name="chk2"/> +	<check_box label="Seja contratado" name="chk6"/> +	<check_box label="Grupo" name="chk3"/> +	<check_box label="Comprar" name="chk4"/> +	<check_box label="Venda" name="chk5"/> +	<check_box label="Contratar" name="chk7"/> +	<line_editor name="want_to_edit"> +		(carregando...) +	</line_editor> +	<text name="Skills:"> +		Habilidades: +	</text> +	<check_box label="Texturas" name="schk0"/> +	<check_box label="Arquitetura" name="schk1"/> +	<check_box label="Modelo" name="schk3"/> +	<check_box label="Planejamento de evento" name="schk2"/> +	<check_box label="Scripts" name="schk4"/> +	<check_box label="Personagens personalizados" name="schk5"/> +	<line_editor name="skills_edit"> +		(carregando...) +	</line_editor> +	<text name="Languages:"> +		Idiomas: +	</text> +	<line_editor name="languages_edit"> +		(carregando...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_notes.xml b/indra/newview/skins/default/xui/pt/panel_profile_notes.xml new file mode 100644 index 0000000000..499e371bb7 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Anotações e Privacidade" name="panel_notes"> +	<text name="status_message" value="Notas particulares neste avatar:"/> +	<text name="status_message2" value="Permitir que esse avatar:"/> +	<check_box label="Ver quando eu estiver conectado" name="status_check"/> +	<check_box label="Encontre-me no mapa-múndi" name="map_check"/> +	<check_box label="Pegar, editar ou excluir objetos meus" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_pick.xml b/indra/newview/skins/default/xui/pt/panel_profile_pick.xml new file mode 100644 index 0000000000..2dd37b38f9 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(salvar para atualizar) +	</panel.string> +	<line_editor name="pick_location"> +		Carregando... +	</line_editor> +	<button label="Teletransportar" name="teleport_btn"/> +	<button label="Mostrar no mapa" name="show_on_map_btn"/> +	<button label="Definir Localização" name="set_to_curr_location_btn" tool_tip="Usar configuração local"/> +	<button label="Salvar destaque" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_picks.xml b/indra/newview/skins/default/xui/pt/panel_profile_picks.xml new file mode 100644 index 0000000000..f9ead974dc --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Destaques" name="panel_picks"> +	<string name="no_picks" value="Nenhum"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Conte a todos sobre os seu lugares favoritos no Second Life. +	</text> +	<button label="Novo..." name="new_btn"/> +	<button label="Excluir..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Carregando... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml new file mode 100644 index 0000000000..8723b1bf58 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Perfil" name="panel_profile"> +	<string name="status_online"> +		Atualmente Online +	</string> +	<string name="status_offline"> +		Atualmente Offline +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Nenhum"/> +	<string name="no_group_text" value="Nenhum"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Desenvolvedor"/> +	<string name="FSSupp" value="Suporte"/> +	<string name="FSQualityAssurance" value="Caçador de Bug"/> +	<string name="FSGW" value="Gateway"/> +	<text name="name_label" value="Nome:"/> +	<button label="Nome:" name="set_name" tool_tip="Definir nome de tela"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(carregando...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Status desconhecido"/> +			<text name="label" value="Aniversário Second Life:"/> +			<text name="label2" value="Conta:"/> +			<text name="partner_label" value="Parceiro(a):"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Grupos:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Convidar para entrar no grupo"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="Sobre:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Dar o item:"/> +			<text name="Give inventory" tool_tip="Arraste e solte o item novo do inventário aqui para dá-los a esta pessoa."> +				Arraste e solte o item novo do inventário aqui. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Localizar no mapa" label_selected="Localizar no mapa" name="show_on_map_btn" tool_tip="Localizar o Residente no mapa"/> +			<button label="Pagar" label_selected="Pagar" name="pay" tool_tip="Pague em dinheiro para o Residente"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Teletransportar?" label_selected="Teletransportar?" name="teleport" tool_tip="Oferecer teletransporte ao Residente"/> +			<button label="Mensagem instantânea" label_selected="Mensagem instantânea" name="im" tool_tip="Abrir sessão de mensagem instantânea"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Adicionar amigo" label_selected="Adicionar amigo" name="add_friend" tool_tip="Oferecer amizade ao residente"/> +			<button label="Bloquear" name="block" tool_tip="Bloquear este Residente"/> +			<button label="Desbloquear" name="unblock" tool_tip="Desbloquear este Residente"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Mostrar nos resultados de busca" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_profile_web.xml b/indra/newview/skins/default/xui/pt/panel_profile_web.xml new file mode 100644 index 0000000000..0f556c7dad --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Carregar tempo: [TIME] segundos"/> +	<line_editor name="url_edit"> +		(carregando..) +	</line_editor> +	<flyout_button label="Carregar" name="load" tool_tip="Carregar esta página de perfil com navegador embutido"> +		<flyout_button.item label="Abrir no visualizador do navegador" name="open_item"/> +		<flyout_button.item label="Abrir no navegador externo" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Abra o perfil da web"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 7c593ab3be..7a425a2622 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -313,6 +313,24 @@ Aguarde um minuto antes que tentar logar-se novamente.  	<string name="TestingDisconnect">  		Teste de desconexão  	</string> +	<string name="SocialFacebookConnecting"> +		Conectando ao Facebook... +	</string> +	<string name="SocialFacebookPosting"> +		Publicando... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Desconectando do Facebook... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Problema ao conectar ao Facebook +	</string> +	<string name="SocialFacebookErrorPosting"> +		Problema ao publicar no Facebook +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Problema ao desconectar do Facebook +	</string>  	<string name="SocialFlickrConnecting">  		Conectando ao Flickr...  	</string> @@ -2517,9 +2535,21 @@ Se você continuar a receber essa mensagem, entre em contato com o suporte do Se  	<string name="NoPicksClassifiedsText">  		Você não criou nenhum Destaque ou Anúncio.  Clique no botão "+" para criar um Destaque ou Anúncio.  	</string> +	<string name="NoPicksText"> +		Você não criou nenhuma Escolha. Clique em Novo Botão para criar um Escolher +	</string> +	<string name="NoClassifiedsText"> +		Você criou nenhum Anúncio. Clique em Novo Botão para criar um Classificado +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		O usuário não tem nenhum destaque ou anúncio  	</string> +	<string name="NoAvatarPicksText"> +		Usuário não tem escolha +	</string> +	<string name="NoAvatarClassifiedsText"> +		Usuário não tem anúncio +	</string>  	<string name="PicksClassifiedsLoadingText">  		Carregando...  	</string> @@ -4433,6 +4463,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="inventory_folder_offered-im">  		Pasta do inventário '[ITEM_NAME]' oferecida  	</string> +	<string name="facebook_post_success"> +		Você publicou no Facebook. +	</string>  	<string name="flickr_post_success">  		Você publicou no Flickr.  	</string> diff --git a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml index 7c1d3b52c5..bf90d898f9 100644 --- a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@  	<check_box label="Жесты" name="check_gesture"/>  	<check_box label="Закладки" name="check_landmark"/>  	<check_box label="Заметки" name="check_notecard"/> -	<check_box label="Меши" name="check_mesh"/> +	<check_box label="Полисетки" name="check_mesh"/>  	<check_box label="Объекты" name="check_object"/>  	<check_box label="Скрипты" name="check_script"/>  	<check_box label="Звуки" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/ru/floater_picks.xml b/indra/newview/skins/default/xui/ru/floater_picks.xml deleted file mode 100644 index e0ae8d6f03..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Подборка"/> diff --git a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml index 46d2a37503..e3921a75ac 100644 --- a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Копировать в инвентарь  	</floater.string> -	<text name="desc txt"> -		Описание: -	</text> -	<text name="dimensions"> -		[WIDTH]пикселей x [HEIGHT]пикселей -	</text> -	<text name="aspect_ratio"> -		Просмотр изображения с соотношением сторон -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с фиксированным соотношением сторон"> -		<combo_item name="Unconstrained"> -			Без ограничения -		</combo_item> -		<combo_item name="1:1" tool_tip="Символ группы или профиль в реальном мире"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="Профиль для [SECOND_LIFE]"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="Реклама, поиск и закладки"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="О земле"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Профиль подборки"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="OK" name="Keep"/> -	<button label="Отменить" name="Discard"/> -	<button label="Сохранить как" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Описание: +			</text> +			<text name="dimensions"> +				[WIDTH]пикселей x [HEIGHT]пикселей +			</text> +			<text name="aspect_ratio"> +				Предварительный просмотр соотношения сторон +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с фиксированным соотношением сторон"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="OK" name="Keep"/> +			<button label="Сбросить" name="Discard"/> +			<button label="Сохранить как" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/ru/floater_profile.xml b/indra/newview/skins/default/xui/ru/floater_profile.xml new file mode 100644 index 0000000000..6f8daf0a62 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Профиль"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Веб" name="panel_profile_web"/> +			<panel label="Круг интересов" name="panel_profile_interests"/> +			<panel label="Подборка" name="panel_profile_picks"/> +			<panel label="Объявление" name="panel_profile_classifieds"/> +			<panel label="Реальная жизнь" name="panel_profile_firstlife"/> +			<panel label="Примечания" name="panel_profile_notes"/> +		</tab_container> +		<button label="OK" name="ok_btn" tool_tip="Сохранить изменения в профиле и закрыть"/> +		<button label="Отменить" label_selected="Отменить" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_report_abuse.xml b/indra/newview/skins/default/xui/ru/floater_report_abuse.xml index 3ac8cb74b4..89a453d9cd 100644 --- a/indra/newview/skins/default/xui/ru/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/ru/floater_report_abuse.xml @@ -67,7 +67,7 @@  		<combo_box.item label="Земля > Посягательство > Объекты или текстуры" name="Land__Encroachment__Objects_textures"/>  		<combo_box.item label="Земля > Посягательство > Частицы" name="Land__Encroachment__Particles"/>  		<combo_box.item label="Земля > Посягательство > Деревья/растения" name="Land__Encroachment__Trees_plants"/> -		<combo_box.item label="Нарушение правил игр на ловкость" name="Wagering_gambling"/> +		<combo_box.item label="Нарушение игровых правил" name="Wagering_gambling"/>  		<combo_box.item label="Другое" name="Other"/>  	</combo_box>  	<text name="abuser_name_title"> diff --git a/indra/newview/skins/default/xui/ru/floater_snapshot.xml b/indra/newview/skins/default/xui/ru/floater_snapshot.xml index 97de279b8f..a796d942f3 100644 --- a/indra/newview/skins/default/xui/ru/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/ru/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		Отправка письма  	</string> +	<string name="facebook_progress_str"> +		Публикация в Facebook +	</string>  	<string name="profile_progress_str">  		Публикация  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Сохранение на компьютере  	</string> +	<string name="facebook_succeeded_str"> +		Изображение загружено +	</string>  	<string name="profile_succeeded_str">  		Изображение отправлено  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Сохранено на компьютере!  	</string> +	<string name="facebook_failed_str"> +		Не удалось передать изображение на вашу хронику Facebook. +	</string>  	<string name="profile_failed_str">  		Не удалось передать изображение в ваш профиль.  	</string> diff --git a/indra/newview/skins/default/xui/ru/menu_name_field.xml b/indra/newview/skins/default/xui/ru/menu_name_field.xml new file mode 100644 index 0000000000..889f3c37ab --- /dev/null +++ b/indra/newview/skins/default/xui/ru/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Копировать отображаемое имя" name="copy_display"/> +	<menu_item_call label="Копировать имя агента" name="copy_name"/> +	<menu_item_call label="Копировать Id агента" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index bfcda798be..e75fd1fd82 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -2682,6 +2682,9 @@  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/ru/panel_edit_classified.xml b/indra/newview/skins/default/xui/ru/panel_edit_classified.xml index a2f06dbadf..ec457c4565 100644 --- a/indra/newview/skins/default/xui/ru/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/ru/panel_edit_classified.xml @@ -46,8 +46,8 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> -				<button label="Отмена" name="cancel_btn"/> +			<layout_panel name="cancel_btn_lp"> +				<button label="Отменить" name="cancel_btn"/>  			</layout_panel>  		</layout_stack>  	</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml b/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml index 746da8d523..1e4d1346f7 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_friends.xml @@ -1,6 +1,6 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_friends"> -	<string name="facebook_friends_empty" value="Сейчас у вас нет друзей по Facebook, которые также были бы жителями Second Life. Предложите своим друзьям по Facebook присоединиться к Second Life!"/> +	<string name="facebook_friends_empty" value="Сейчас у вас нет друзей в Facebook, которые являются также жителями Second Life. Предложите своим друзьям в Facebook присоединиться к Second Life!"/>  	<string name="facebook_friends_no_connected" value="Сейчас вы не подключены к Facebook. Перейдите на вкладку «Статус», чтобы подключиться и включить эту функцию."/>  	<accordion name="friends_accordion">  		<accordion_tab name="tab_second_life_friends" title="Друзья по SL"/> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml b/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml index 143a57fec7..50296778ff 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_photo.xml @@ -2,19 +2,19 @@  <panel name="panel_facebook_photo">  	<combo_box name="resolution_combobox" tool_tip="Разрешение изображения">  		<combo_box.item label="Текущее окно" name="CurrentWindow"/> -		<combo_box.item label="640x480" name="640x480"/> -		<combo_box.item label="800x600" name="800x600"/> -		<combo_box.item label="1024x768" name="1024x768"/> -		<combo_box.item label="1200x630" name="1200x630"/> +		<combo_box.item label="640 x 480" name="640x480"/> +		<combo_box.item label="800 x 600" name="800x600"/> +		<combo_box.item label="1024 x 768" name="1024x768"/> +		<combo_box.item label="1200 x 630" name="1200x630"/>  	</combo_box>  	<combo_box name="filters_combobox" tool_tip="Фильтры изображений">  		<combo_box.item label="Без фильтра" name="NoFilter"/>  	</combo_box> -	<button label="Обновить" name="new_snapshot_btn" tool_tip="Щелкните для обновления"/> -	<button label="Просмотр" name="big_preview_btn" tool_tip="Щелкните для смены вида"/> +	<button label="Обновить" name="new_snapshot_btn" tool_tip="Щелкнуть для обновления"/> +	<button label="Предпросмотр" name="big_preview_btn" tool_tip="Щелкнуть для смены вида"/>  	<text name="caption_label">  		Комментарий (не обязательно):  	</text>  	<button label="Опубликовать" name="post_photo_btn"/> -	<button label="Отмена" name="cancel_photo_btn"/> +	<button label="Отменить" name="cancel_photo_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_place.xml b/indra/newview/skins/default/xui/ru/panel_facebook_place.xml index 7d0917a43a..a7fadca059 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_place.xml @@ -1,9 +1,9 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_place">  	<text name="place_caption_label"> -		Напишите о том, где вы: +		Сообщите, где вы находитесь:  	</text>  	<check_box initial_value="false" label="Включить вид места сверху" name="add_place_view_cb"/>  	<button label="Опубликовать" name="post_place_btn"/> -	<button label="Отмена" name="cancel_place_btn"/> +	<button label="Отменить" name="cancel_place_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_facebook_status.xml b/indra/newview/skins/default/xui/ru/panel_facebook_status.xml index c651a8087c..826ac6a08c 100644 --- a/indra/newview/skins/default/xui/ru/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/ru/panel_facebook_status.xml @@ -1,20 +1,20 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_status">  	<string name="facebook_connected" value="Вы подключились к Facebook как:"/> -	<string name="facebook_disconnected" value="Не подключено к Facebook"/> +	<string name="facebook_disconnected" value="Нет подключения к Facebook"/>  	<text name="account_caption_label"> -		Не подключено к Facebook. +		Нет подключения к Facebook.  	</text>  	<panel name="panel_buttons"> -		<button label="Подключение..." name="connect_btn"/> -		<button label="Отключить" name="disconnect_btn"/> +		<button label="Соединение..." name="connect_btn"/> +		<button label="Разъединить" name="disconnect_btn"/>  		<text name="account_learn_more_label"> -			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 О публикации в Facebook] +			[http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Узнать о публикации в Facebook]  		</text>  	</panel>  	<text name="status_caption_label">  		О чем вы думаете?  	</text>  	<button label="Опубликовать" name="post_status_btn"/> -	<button label="Отмена" name="cancel_status_btn"/> +	<button label="Отменить" name="cancel_status_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml new file mode 100644 index 0000000000..3408969d09 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Неизвестно"/> +	<button name="info_btn" tool_tip="Больше информации"/> +	<button name="profile_btn" tool_tip="Посмотреть профиль"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_me.xml b/indra/newview/skins/default/xui/ru/panel_me.xml deleted file mode 100644 index 21a125af87..0000000000 --- a/indra/newview/skins/default/xui/ru/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Мой профиль" name="panel_me"> -	<panel label="МОЯ ПОДБОРКА" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_people.xml b/indra/newview/skins/default/xui/ru/panel_people.xml index 0812eb7433..8170c8d26f 100644 --- a/indra/newview/skins/default/xui/ru/panel_people.xml +++ b/indra/newview/skins/default/xui/ru/panel_people.xml @@ -40,6 +40,7 @@  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Онлайн"/>  				<accordion_tab name="tab_all" title="Все"/> +				<accordion_tab name="tab_suggested_friends" title="С кем вы можете подружиться"/>  			</accordion>  		</panel>  		<panel label="ГРУППЫ" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_classified.xml b/indra/newview/skins/default/xui/ru/panel_profile_classified.xml new file mode 100644 index 0000000000..2d3ed685c0 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Умеренная +	</panel.string> +	<panel.string name="type_pg"> +		Общий контент +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		Телепорт [TELEPORT], карта [MAP], профиль [PROFILE] +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Включен +	</panel.string> +	<panel.string name="auto_renew_off"> +		Отключен +	</panel.string> +	<panel.string name="location_notice"> +		(будет обновлено после сохранения) +	</panel.string> +	<string name="publish_label"> +		Опубликовать +	</string> +	<string name="save_label"> +		Сохранить +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Щелкнуть для выбора изображения"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Местоположение:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="Тип контента:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Категория:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Дата создания:"/> +					<text_editor name="creation_date" tool_tip="Дата создания" value="[date]"/> +					<text name="price_for_listing_label" value="Стоимость размещения:"/> +					<text_editor name="price_for_listing" tool_tip="Цена за размещение."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Клики:"/> +					<text_editor name="click_through_text" tool_tip="Информация о переходах" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Автоматическое продление:"/> +					<text name="auto_renew" value="Включен"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Описание:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Название: +				</text> +				<text name="description_label"> +					Описание: +				</text> +				<text name="location_label"> +					Местоположение: +				</text> +				<text name="classified_location_edit"> +					загрузка... +				</text> +				<button label="Установить в текущее местоположение" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Категория:"/> +				<text name="content_type_label" value="Тип контента:"/> +				<icons_combo_box label="Общий контент" name="content_type_edit"> +					<icons_combo_box.item label="Умеренный контент" name="mature_ci" value="Возрастной"/> +					<icons_combo_box.item label="Общий контент" name="pg_ci" value="C разрешения родителей"/> +				</icons_combo_box> +				<check_box label="Автоматическое обновление каждую неделю" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="Стоимость размещения:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="Цена за размещение." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Телепорт" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Карта" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Редактировать" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="Отменить" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml new file mode 100644 index 0000000000..fac494682a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Объявление" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="Нет рекламы"/> +	<button label="Новый..." name="new_btn"/> +	<button label="Удалить..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Загрузка... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml new file mode 100644 index 0000000000..f5ac5e906a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Профиль" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_interests.xml b/indra/newview/skins/default/xui/ru/panel_profile_interests.xml new file mode 100644 index 0000000000..ba1c3d0357 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Круг интересов" name="panel_profile_interests"> +	<text name="I Want To:"> +		Я собираюсь: +	</text> +	<check_box label="Построить" name="chk0"/> +	<check_box label="Просмотреть" name="chk1"/> +	<check_box label="Встретить" name="chk2"/> +	<check_box label="Получить работу" name="chk6"/> +	<check_box label="Группа" name="chk3"/> +	<check_box label="Купить" name="chk4"/> +	<check_box label="Продать" name="chk5"/> +	<check_box label="Нанять" name="chk7"/> +	<line_editor name="want_to_edit"> +		(загрузка…) +	</line_editor> +	<text name="Skills:"> +		Навыки: +	</text> +	<check_box label="Текстуры" name="schk0"/> +	<check_box label="Архитектура" name="schk1"/> +	<check_box label="Моделирование" name="schk3"/> +	<check_box label="Планирование мероприятия" name="schk2"/> +	<check_box label="Создавать сценарии" name="schk4"/> +	<check_box label="Пользовательские символы" name="schk5"/> +	<line_editor name="skills_edit"> +		(загрузка…) +	</line_editor> +	<text name="Languages:"> +		Языки: +	</text> +	<line_editor name="languages_edit"> +		(загрузка…) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_notes.xml b/indra/newview/skins/default/xui/ru/panel_profile_notes.xml new file mode 100644 index 0000000000..41117c743a --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Примечания и конфиденциальность" name="panel_notes"> +	<text name="status_message" value="Личные заметки об этом аватаре:"/> +	<text name="status_message2" value="Разрешить этому аватару:"/> +	<check_box label="Смотреть, когда я в сети" name="status_check"/> +	<check_box label="Найти меня на карте мира" name="map_check"/> +	<check_box label="Редактировать, удалять или брать мои объекты" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_pick.xml b/indra/newview/skins/default/xui/ru/panel_profile_pick.xml new file mode 100644 index 0000000000..a2ff5710ea --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(будет обновлено после сохранения) +	</panel.string> +	<line_editor name="pick_location"> +		Загрузка... +	</line_editor> +	<button label="Телепорт" name="teleport_btn"/> +	<button label="Показать на карте" name="show_on_map_btn"/> +	<button label="Указать местоположение" name="set_to_curr_location_btn" tool_tip="Установить в текущее местоположение"/> +	<button label="Сохранить подборку" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_picks.xml b/indra/newview/skins/default/xui/ru/panel_profile_picks.xml new file mode 100644 index 0000000000..227b3f82b8 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Подборка" name="panel_picks"> +	<string name="no_picks" value="Нет подборки"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Сообщить всем о ваших избранных службах в Second Life. +	</text> +	<button label="Новый..." name="new_btn"/> +	<button label="Удалить..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Загрузка... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml new file mode 100644 index 0000000000..e7a66ba29e --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Профиль" name="panel_profile"> +	<string name="status_online"> +		В настоящее время в режиме онлайн +	</string> +	<string name="status_offline"> +		В настоящее время в режиме оффлайн +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Никто"/> +	<string name="no_group_text" value="Никто"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Разработчик"/> +	<string name="FSSupp" value="Поддержка"/> +	<string name="FSQualityAssurance" value="Отладчик"/> +	<string name="FSGW" value="Межсетевой интерфейс"/> +	<text name="name_label" value="Имя:"/> +	<button label="Имя:" name="set_name" tool_tip="Задать отображаемое имя"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(загрузка…)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Статус неизвестен"/> +			<text name="label" value="Дата рождения в Second Life:"/> +			<text name="label2" value="Аккаунт:"/> +			<text name="partner_label" value="Партнер:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Группы:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Пригласить в группу"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="О нас:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Передать вещь:"/> +			<text name="Give inventory" tool_tip="Сбросить вещи из инвентаря здесь для передачи их этому игроку."> +				Сбросить вещь из инвентаря здесь. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Найти на карте" label_selected="Найти на карте" name="show_on_map_btn" tool_tip="Найти жителя на карте"/> +			<button label="Оплатить" label_selected="Оплатить" name="pay" tool_tip="Выплатить деньги резиденту"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Предложить телепорт" label_selected="Предложить телепорт" name="teleport" tool_tip="Предложить телепорт этому жителю"/> +			<button label="Мгновенное сообщение" label_selected="Мгновенное сообщение" name="im" tool_tip="Начать сеанс IM"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Добавить друга" label_selected="Добавить друга" name="add_friend" tool_tip="Предложить дружбу этому жителю"/> +			<button label="Заблокировать" name="block" tool_tip="Заблокировать этого жителя"/> +			<button label="Разблокировать" name="unblock" tool_tip="Разблокировать этого жителя"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Показать в поиске" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/panel_profile_web.xml b/indra/newview/skins/default/xui/ru/panel_profile_web.xml new file mode 100644 index 0000000000..18a17e2586 --- /dev/null +++ b/indra/newview/skins/default/xui/ru/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Веб" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Время загрузки: [TIME] секунд"/> +	<line_editor name="url_edit"> +		(загрузка…) +	</line_editor> +	<flyout_button label="Загрузить" name="load" tool_tip="Загрузить эту страницу с профилем с помощью встроенного веб-браузера."> +		<flyout_button.item label="Открыть в просмотрщике браузера" name="open_item"/> +		<flyout_button.item label="Открыть во внешнем браузере" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Всплывающий веб-профиль"/> +</panel> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 95b1664279..c0dc32340a 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -357,6 +357,24 @@ support@secondlife.com.  	<string name="TestingDisconnect">  		Тестирование отключения клиента  	</string> +	<string name="SocialFacebookConnecting"> +		Подключение к Facebook... +	</string> +	<string name="SocialFacebookPosting"> +		Публикация... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Отключение от Facebook... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Проблема с подключением к Facebook +	</string> +	<string name="SocialFacebookErrorPosting"> +		Проблемы при публикации в Facebook +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Проблема с отключением от Facebook +	</string>  	<string name="SocialFlickrConnecting">  		Подключение к Flickr...  	</string> @@ -2576,9 +2594,21 @@ support@secondlife.com.  	<string name="NoPicksClassifiedsText">  		Вы не создали подборки или рекламы. Нажмите кнопку со знаком «плюс» ниже, чтобы создать подборку или рекламу  	</string> +	<string name="NoPicksText"> +		Вы не сделали никакой подборки. Нажмите кнопку Создать, чтобы сделать подборку. +	</string> +	<string name="NoClassifiedsText"> +		Вы не сделали никакой рекламы. Нажмите кнопку Создать, чтобы сделать рекламу. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		У жителя нет подборки или рекламы  	</string> +	<string name="NoAvatarPicksText"> +		У пользователя нет подборки +	</string> +	<string name="NoAvatarClassifiedsText"> +		У пользователя нет объявлений +	</string>  	<string name="PicksClassifiedsLoadingText">  		Загрузка...  	</string> @@ -4553,6 +4583,9 @@ support@secondlife.com.  	<string name="share_alert">  		Перетаскивайте вещи из инвентаря сюда  	</string> +	<string name="facebook_post_success"> +		Вы опубликовали сообщение в Facebook. +	</string>  	<string name="flickr_post_success">  		Вы опубликовали сообщение в Flickr.  	</string> diff --git a/indra/newview/skins/default/xui/tr/floater_facebook.xml b/indra/newview/skins/default/xui/tr/floater_facebook.xml index 656a4a81c9..d8cbd84ed1 100644 --- a/indra/newview/skins/default/xui/tr/floater_facebook.xml +++ b/indra/newview/skins/default/xui/tr/floater_facebook.xml @@ -3,7 +3,7 @@  	<tab_container name="tabs">  		<panel label="DURUM" name="panel_facebook_status"/>  		<panel label="FOTOĞRAF" name="panel_facebook_photo"/> -		<panel label="KONUMA GİRİŞ YAPIN" name="panel_facebook_place"/> +		<panel label="GİRİŞ YAP" name="panel_facebook_place"/>  		<panel label="ARKADAŞLAR" name="panel_facebook_friends"/>  	</tab_container>  	<text name="connection_error_text"> diff --git a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml index accb1ed71c..caa8497d3a 100644 --- a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@  	<check_box label="Mimikler" name="check_gesture"/>  	<check_box label="Yer İmleri" name="check_landmark"/>  	<check_box label="Not Kartları" name="check_notecard"/> -	<check_box label="Örgüler" name="check_mesh"/> +	<check_box label="Ağlar" name="check_mesh"/>  	<check_box label="Nesneler" name="check_object"/>  	<check_box label="Komut Dosyaları" name="check_script"/>  	<check_box label="Sesler" name="check_sound"/> diff --git a/indra/newview/skins/default/xui/tr/floater_picks.xml b/indra/newview/skins/default/xui/tr/floater_picks.xml deleted file mode 100644 index 5aee6ae091..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="Seçimler"/> diff --git a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml index 8302c62070..8ba9123545 100644 --- a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		Envantere Kopyala  	</floater.string> -	<text name="desc txt"> -		Açıklama: -	</text> -	<text name="dimensions"> -		[WIDTH] pks x [HEIGHT] pks -	</text> -	<text name="aspect_ratio"> -		En boy oranını önizle -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="Sabit en boy oranında önizle"> -		<combo_item name="Unconstrained"> -			Kısıtsız -		</combo_item> -		<combo_item name="1:1" tool_tip="Grup işaretleri veya Real World profili"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="[SECOND_LIFE] profili"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="İlanlar ve arama listeleri, yer imleri"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="Arazi hakkında"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="Profil seçmeleri"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="Tamam" name="Keep"/> -	<button label="At" name="Discard"/> -	<button label="Farklı Kaydet" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				Açıklama: +			</text> +			<text name="dimensions"> +				[WIDTH]pks x [HEIGHT]pks +			</text> +			<text name="aspect_ratio"> +				En boy oranını önizle +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="Sabit en boy oranında önizle"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="Tamam" name="Keep"/> +			<button label="At" name="Discard"/> +			<button label="Farklı Kaydet" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/tr/floater_profile.xml b/indra/newview/skins/default/xui/tr/floater_profile.xml new file mode 100644 index 0000000000..bb158ddf66 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="Profil"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="Second Life" name="panel_profile_secondlife"/> +			<panel label="Web" name="panel_profile_web"/> +			<panel label="İlgi alanları" name="panel_profile_interests"/> +			<panel label="Favoriler" name="panel_profile_picks"/> +			<panel label="İlan" name="panel_profile_classifieds"/> +			<panel label="Gerçek Hayat" name="panel_profile_firstlife"/> +			<panel label="Notlar" name="panel_profile_notes"/> +		</tab_container> +		<button label="Tamam" name="ok_btn" tool_tip="Değişiklikleri profile kaydet ve kapat"/> +		<button label="İptal Et" label_selected="İptal Et" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_snapshot.xml b/indra/newview/skins/default/xui/tr/floater_snapshot.xml index be6c58e8cf..8496194700 100644 --- a/indra/newview/skins/default/xui/tr/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/tr/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		E-posta Gönderiliyor  	</string> +	<string name="facebook_progress_str"> +		Facebook'ta yayınlanıyor +	</string>  	<string name="profile_progress_str">  		Yayınlanıyor  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		Bilgisayara Kaydediliyor  	</string> +	<string name="facebook_succeeded_str"> +		Görüntü yüklendi +	</string>  	<string name="profile_succeeded_str">  		Görüntü yüklendi  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		Bilgisayara Kaydedildi!  	</string> +	<string name="facebook_failed_str"> +		Görüntü Facebook zaman tünelinize yüklenemedi. +	</string>  	<string name="profile_failed_str">  		Görüntü Profil Akışınıza yüklenemedi.  	</string> diff --git a/indra/newview/skins/default/xui/tr/menu_name_field.xml b/indra/newview/skins/default/xui/tr/menu_name_field.xml new file mode 100644 index 0000000000..b1afd737c3 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="Görünen Adı Kopyala" name="copy_display"/> +	<menu_item_call label="Aracı Adını Kopyala" name="copy_name"/> +	<menu_item_call label="Aracı Kimliğini Kopyala" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 5403a78f22..17d2969d19 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -2682,6 +2682,9 @@ Daha küçük bir arazi parçası seçmeyi deneyin.  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml index fc444f21f6..78c34a3ac0 100644 --- a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="İptal Et" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml b/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml index 8184d6d7cf..edbe87d74c 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_friends.xml @@ -1,12 +1,12 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_friends"> -	<string name="facebook_friends_empty" value="Şu an için aynı zamanda bir Second Life sakini olan hiçbir Facebook arkadaşınız yok. Facebook arkadaşlarınızı bugün Second Life'a katılmaya davet edin!"/> +	<string name="facebook_friends_empty" value="Şu anda aynı zamanda bir Second Life sakini olan hiçbir Facebook arkadaşınız yok. Facebook arkadaşlarınızdan bugün Second Life'a katılmalarını isteyin!"/>  	<string name="facebook_friends_no_connected" value="Şu anda Facebook'a bağlı değilsiniz. Bağlanmak ve bu özelliği etkinleştirmek için lütfen Durum sekmesine gidin."/>  	<accordion name="friends_accordion">  		<accordion_tab name="tab_second_life_friends" title="SL arkadaşları"/>  		<accordion_tab name="tab_suggested_friends" title="Bu kişileri SL arkadaşları olarak ekle"/>  	</accordion>  	<text name="facebook_friends_status"> -		Facebook'a bağlanılmadı. +		Facebook'a bağlanılamadı.  	</text>  </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml b/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml index d772aff937..e3150f258d 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_photo.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_photo">  	<combo_box name="resolution_combobox" tool_tip="Görüntü çözünürlüğü"> -		<combo_box.item label="Mevcut Pencere" name="CurrentWindow"/> +		<combo_box.item label="Geçerli Pencere" name="CurrentWindow"/>  		<combo_box.item label="640x480" name="640x480"/>  		<combo_box.item label="800x600" name="800x600"/>  		<combo_box.item label="1024x768" name="1024x768"/> @@ -11,10 +11,10 @@  		<combo_box.item label="Filtre Yok" name="NoFilter"/>  	</combo_box>  	<button label="Yenile" name="new_snapshot_btn" tool_tip="Yenilemek için tıklayın"/> -	<button label="Önizleme" name="big_preview_btn" tool_tip="Önizleme ayarları arasında geçiş yapmak için tıklayın"/> +	<button label="Önizleme" name="big_preview_btn" tool_tip="Önizlemeye geçmek için tıklayın"/>  	<text name="caption_label">  		Yorum (isteğe bağlı):  	</text>  	<button label="Yayınla" name="post_photo_btn"/> -	<button label="İptal" name="cancel_photo_btn"/> +	<button label="İptal Et" name="cancel_photo_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_place.xml b/indra/newview/skins/default/xui/tr/panel_facebook_place.xml index 85b401a1a0..96c34d03d0 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_place.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_place.xml @@ -5,5 +5,5 @@  	</text>  	<check_box initial_value="false" label="Konumun üstten görünümünü ekle" name="add_place_view_cb"/>  	<button label="Yayınla" name="post_place_btn"/> -	<button label="İptal" name="cancel_place_btn"/> +	<button label="İptal Et" name="cancel_place_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_facebook_status.xml b/indra/newview/skins/default/xui/tr/panel_facebook_status.xml index e6feff5949..f5dba088de 100644 --- a/indra/newview/skins/default/xui/tr/panel_facebook_status.xml +++ b/indra/newview/skins/default/xui/tr/panel_facebook_status.xml @@ -1,9 +1,9 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_facebook_status">  	<string name="facebook_connected" value="Facebook'a şu kimlikle bağlandınız:"/> -	<string name="facebook_disconnected" value="Facebook'a bağlanılmadı"/> +	<string name="facebook_disconnected" value="Facebook'a bağlanılamadı"/>  	<text name="account_caption_label"> -		Facebook'a bağlanılmadı. +		Facebook'a bağlanılamadı.  	</text>  	<panel name="panel_buttons">  		<button label="Bağlan..." name="connect_btn"/> @@ -13,8 +13,8 @@  		</text>  	</panel>  	<text name="status_caption_label"> -		Ne düşünüyorsunuz? +		Aklınızdan ne geçiyor?  	</text>  	<button label="Yayınla" name="post_status_btn"/> -	<button label="İptal" name="cancel_status_btn"/> +	<button label="İptal Et" name="cancel_status_btn"/>  </panel> diff --git a/indra/newview/skins/default/xui/tr/panel_group_general.xml b/indra/newview/skins/default/xui/tr/panel_group_general.xml index c666778c69..5578b36f3f 100644 --- a/indra/newview/skins/default/xui/tr/panel_group_general.xml +++ b/indra/newview/skins/default/xui/tr/panel_group_general.xml @@ -45,7 +45,7 @@ Daha fazla yardım edinmek için farenizi seçeneklerin üzerine getirin.  		<check_box label="Herkes katılabilir" name="open_enrollement" tool_tip="Bu grubun davet edilmeden yeni üyelerin katılmasına imkan tanıyıp tanımayacağını belirler."/>  		<check_box label="Katılma ücreti" name="check_enrollment_fee" tool_tip="Bu gruba katılmak için bir kayıt ücretinin gerekip gerekmeyeceğini belirler"/>  		<spinner label="L$" name="spin_enrollment_fee" tool_tip="Kayıt Ücreti işaretlendiğinde yeni üyeler gruba katılmak için bu ücreti ödemelidir."/> -		<combo_box name="group_mature_check" tool_tip="Erişkinlik dereceleri bir grupta izin verilen içerik ve davranış türlerini belirler"> +		<combo_box name="group_mature_check" tool_tip="Grubunuzun Orta olarak sınıflandırılmış bilgiler içerip içermeyeceğini belirler">  			<combo_item name="select_mature">  				- Erişkinlik seviyesini seçin -  			</combo_item> diff --git a/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml new file mode 100644 index 0000000000..0ed905ed35 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="Bilinmiyor"/> +	<button name="info_btn" tool_tip="Ek bilgi"/> +	<button name="profile_btn" tool_tip="Profili görüntüle"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_me.xml b/indra/newview/skins/default/xui/tr/panel_me.xml deleted file mode 100644 index d9e79d171c..0000000000 --- a/indra/newview/skins/default/xui/tr/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Profilim" name="panel_me"> -	<panel label="SEÇTİKLERİM" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_people.xml b/indra/newview/skins/default/xui/tr/panel_people.xml index 25d29fcbb5..acbcd2a544 100644 --- a/indra/newview/skins/default/xui/tr/panel_people.xml +++ b/indra/newview/skins/default/xui/tr/panel_people.xml @@ -40,6 +40,7 @@ Birlikte takılacak kişiler mi arıyorsunuz? [secondlife:///app/worldmap Dünya  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="Çevrimiçi"/>  				<accordion_tab name="tab_all" title="Tümü"/> +				<accordion_tab name="tab_suggested_friends" title="Arkadaş olmak isteyebileceğiniz kişiler"/>  			</accordion>  		</panel>  		<panel label="GRUPLAR" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_classified.xml b/indra/newview/skins/default/xui/tr/panel_profile_classified.xml new file mode 100644 index 0000000000..805de24c11 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		Orta +	</panel.string> +	<panel.string name="type_pg"> +		Genel İçerik +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] ışınlanma, [MAP] harita, [PROFILE] profil +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		Etkin +	</panel.string> +	<panel.string name="auto_renew_off"> +		Devre dışı +	</panel.string> +	<panel.string name="location_notice"> +		(kaydedildikten sonra güncellenir) +	</panel.string> +	<string name="publish_label"> +		Yayınla +	</string> +	<string name="save_label"> +		Kaydet +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="Bir görüntü seçmek için tıklayın"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="Konum:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="İçerik Türü:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="Kategori:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="Oluşturma tarihi:"/> +					<text_editor name="creation_date" tool_tip="Oluşturma tarihi" value="[date]"/> +					<text name="price_for_listing_label" value="İlan fiyatı:"/> +					<text_editor name="price_for_listing" tool_tip="İlan fiyatı."> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="Tıklama sayısı:"/> +					<text_editor name="click_through_text" tool_tip="Tıklama verileri" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="Otomatik yenileme:"/> +					<text name="auto_renew" value="Etkin"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="Açıklama:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					Başlık: +				</text> +				<text name="description_label"> +					Açıklama: +				</text> +				<text name="location_label"> +					Konum: +				</text> +				<text name="classified_location_edit"> +					yükleniyor... +				</text> +				<button label="Geçerli Konuma Ayarla" name="set_to_curr_location_btn"/> +				<text name="category_label" value="Kategori:"/> +				<text name="content_type_label" value="İçerik türü:"/> +				<icons_combo_box label="Genel İçerik" name="content_type_edit"> +					<icons_combo_box.item label="Orta İçerik" name="mature_ci" value="Yetişkin"/> +					<icons_combo_box.item label="Genel İçerik" name="pg_ci" value="PG"/> +				</icons_combo_box> +				<check_box label="Her hafta otomatik yenile" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="İlan fiyatı:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="İlan fiyatı." value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="Işınlanma" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="Harita" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="Düzenle" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="İptal Et" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml new file mode 100644 index 0000000000..0edae1ab2a --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="İlan" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="İlan Yok"/> +	<button label="Yeni..." name="new_btn"/> +	<button label="Sil..." name="delete_btn"/> +	<text name="classifieds_panel_text"> +		Yükleniyor... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml new file mode 100644 index 0000000000..0f65090209 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_interests.xml b/indra/newview/skins/default/xui/tr/panel_profile_interests.xml new file mode 100644 index 0000000000..b068aa3dad --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="İlgi alanları" name="panel_profile_interests"> +	<text name="I Want To:"> +		Şunu Yapmak İstiyorum: +	</text> +	<check_box label="İnşa Et" name="chk0"/> +	<check_box label="Keşfet" name="chk1"/> +	<check_box label="Tanış" name="chk2"/> +	<check_box label="İşe Gir" name="chk6"/> +	<check_box label="Gruplandır" name="chk3"/> +	<check_box label="Satın Al" name="chk4"/> +	<check_box label="Sat" name="chk5"/> +	<check_box label="İşe Al" name="chk7"/> +	<line_editor name="want_to_edit"> +		(yükleniyor...) +	</line_editor> +	<text name="Skills:"> +		Beceriler: +	</text> +	<check_box label="Dokular" name="schk0"/> +	<check_box label="Mimari" name="schk1"/> +	<check_box label="Modelleme" name="schk3"/> +	<check_box label="Etkinlik Planlama" name="schk2"/> +	<check_box label="Kodlama" name="schk4"/> +	<check_box label="Özel Karakterler" name="schk5"/> +	<line_editor name="skills_edit"> +		(yükleniyor...) +	</line_editor> +	<text name="Languages:"> +		Diller: +	</text> +	<line_editor name="languages_edit"> +		(yükleniyor...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_notes.xml b/indra/newview/skins/default/xui/tr/panel_profile_notes.xml new file mode 100644 index 0000000000..fff75dd685 --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Notlar ve Gizlilik" name="panel_notes"> +	<text name="status_message" value="Bu avatar ile ilgili özel notlar:"/> +	<text name="status_message2" value="Bu avatar için şunlara izin ver:"/> +	<check_box label="Çevrimiçi olduğumu görme" name="status_check"/> +	<check_box label="Beni dünya haritasında bulma" name="map_check"/> +	<check_box label="Nesnelerimi düzenleme, silme veya alma" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_pick.xml b/indra/newview/skins/default/xui/tr/panel_profile_pick.xml new file mode 100644 index 0000000000..d42c1eff7f --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(kaydedildikten sonra güncellenir) +	</panel.string> +	<line_editor name="pick_location"> +		Yükleniyor... +	</line_editor> +	<button label="Işınlanma" name="teleport_btn"/> +	<button label="Haritada Göster" name="show_on_map_btn"/> +	<button label="Konumu Ayarla" name="set_to_curr_location_btn" tool_tip="Geçerli Konuma Ayarla"/> +	<button label="Favoriyi Kaydet" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_picks.xml b/indra/newview/skins/default/xui/tr/panel_profile_picks.xml new file mode 100644 index 0000000000..7222a2fc2e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Favoriler" name="panel_picks"> +	<string name="no_picks" value="Favori Yok"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		Second Life'ta favori yerlerinizi herkese anlatın! +	</text> +	<button label="Yeni..." name="new_btn"/> +	<button label="Sil..." name="delete_btn"/> +	<text name="picks_panel_text"> +		Yükleniyor... +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml new file mode 100644 index 0000000000..00e81d005e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Profil" name="panel_profile"> +	<string name="status_online"> +		Şu Anda Çevrimiçi +	</string> +	<string name="status_offline"> +		Şu Anda Çevrimdışı +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="Yok"/> +	<string name="no_group_text" value="Yok"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="Geliştirici"/> +	<string name="FSSupp" value="Destek"/> +	<string name="FSQualityAssurance" value="Böcek bilimci"/> +	<string name="FSGW" value="Ağ geçidi"/> +	<text name="name_label" value="Ad:"/> +	<button label="Ad:" name="set_name" tool_tip="Görünen Adı Ayarla"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(yükleniyor...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="Durum Bilinmiyor"/> +			<text name="label" value="Second Life Doğum Tarihi:"/> +			<text name="label2" value="Hesap:"/> +			<text name="partner_label" value="Ortak:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="Gruplar:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="Gruba Davet Et"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="Hakkında:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="Öğe ver:"/> +			<text name="Give inventory" tool_tip="Envanter öğelerini bu kişiye vermek için buraya bırakın."> +				Envanter öğesini buraya bırakın. +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="Haritada Bul" label_selected="Haritada Bul" name="show_on_map_btn" tool_tip="Sakini haritada bul"/> +			<button label="Öde" label_selected="Öde" name="pay" tool_tip="Sakine para öde"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="Işınlanma Teklif Et" label_selected="Işınlanma Teklif Et" name="teleport" tool_tip="Sakine ışınlanma teklif et"/> +			<button label="Anlık İleti" label_selected="Anlık İleti" name="im" tool_tip="Anlık ileti oturumu aç"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="Arkadaş Ekle" label_selected="Arkadaş Ekle" name="add_friend" tool_tip="Sakine arkadaşlık teklif et"/> +			<button label="Engelle" name="block" tool_tip="Bu Sakini engelle"/> +			<button label="Engellemeyi Kaldır" name="unblock" tool_tip="Bu Sakinin engellemesini kaldır"/> +		</layout_panel> +	</layout_stack> +	<check_box label="Aramada göster" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/panel_profile_web.xml b/indra/newview/skins/default/xui/tr/panel_profile_web.xml new file mode 100644 index 0000000000..265b1fee7e --- /dev/null +++ b/indra/newview/skins/default/xui/tr/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="Web" name="panel_profile_web"> +	<panel.string name="LoadTime" value="Yükleme Süresi: [TIME] saniye"/> +	<line_editor name="url_edit"> +		(yükleniyor..) +	</line_editor> +	<flyout_button label="Yükle" name="load" tool_tip="Bu profil sayfasını tümleşik web tarayıcı ile yükleyin."> +		<flyout_button.item label="Görüntüleyici içindeki tarayıcıda aç" name="open_item"/> +		<flyout_button.item label="Dış tarayıcıda aç" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="Açılır web profili"/> +</panel> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 74a6b3cac3..d1076b8b79 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -357,6 +357,24 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.  	<string name="TestingDisconnect">  		Görüntüleyici bağlantısının kesilmesi test ediliyor  	</string> +	<string name="SocialFacebookConnecting"> +		Facebook ile bağlantı kuruluyor... +	</string> +	<string name="SocialFacebookPosting"> +		Yayınlanıyor... +	</string> +	<string name="SocialFacebookDisconnecting"> +		Facebook bağlantısı kesiliyor... +	</string> +	<string name="SocialFacebookErrorConnecting"> +		Facebook ile bağlantı kurulurken sorun oluştu +	</string> +	<string name="SocialFacebookErrorPosting"> +		Facebook'ta yayınlarken sorun oluştu +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		Facebook bağlantısı kesilirken sorun oluştu +	</string>  	<string name="SocialFlickrConnecting">  		Flickr bağlantısı kuruluyor...  	</string> @@ -2576,9 +2594,21 @@ Bu mesaj size gelmeye devam ederse lütfen http://support.secondlife.com adresin  	<string name="NoPicksClassifiedsText">  		Herhangi bir Seçme veya İlan oluşturmadınız. Bir Seçme veya İlan oluşturmak için aşağıdaki Artı düğmesine tıklayın.  	</string> +	<string name="NoPicksText"> +		Herhangi bir Favori oluşturmadınız. Bir Favori oluşturmak için Yeni düğmesine tıklayın. +	</string> +	<string name="NoClassifiedsText"> +		Herhangi bir İlan oluşturmadınız. Bir İlan oluşturmak için Yeni düğmesine tıklayın. +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		Kullanıcının herhangi bir seçmesi veya ilanı yok  	</string> +	<string name="NoAvatarPicksText"> +		Kullanıcının favorisi yok +	</string> +	<string name="NoAvatarClassifiedsText"> +		Kullanıcının ilanı yok +	</string>  	<string name="PicksClassifiedsLoadingText">  		Yükleniyor...  	</string> @@ -4556,6 +4586,9 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.  	<string name="share_alert">  		Envanterinizden buraya öğeler sürükleyin  	</string> +	<string name="facebook_post_success"> +		Facebook'ta yayınladınız. +	</string>  	<string name="flickr_post_success">  		Flickr'da yayınladınız.  	</string> diff --git a/indra/newview/skins/default/xui/zh/floater_picks.xml b/indra/newview/skins/default/xui/zh/floater_picks.xml deleted file mode 100644 index a8bfcd99e3..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_picks.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_picks" title="精選地點"/> diff --git a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml index 2b6eac48b3..9213cc212d 100644 --- a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml @@ -6,42 +6,23 @@  	<floater.string name="Copy">  		覆製到收納區  	</floater.string> -	<text name="desc txt"> -		描述: -	</text> -	<text name="dimensions"> -		[WIDTH]像素 x [HEIGHT]像素 -	</text> -	<text name="aspect_ratio"> -		預覽長寬比 -	</text> -	<combo_box name="combo_aspect_ratio" tool_tip="以固定長寬比預覽"> -		<combo_item name="Unconstrained"> -			不受限 -		</combo_item> -		<combo_item name="1:1" tool_tip="群組徽章或現實世界小檔案"> -			1:1 -		</combo_item> -		<combo_item name="4:3" tool_tip="[SECOND_LIFE] 檔案"> -			4:3 -		</combo_item> -		<combo_item name="10:7" tool_tip="個人廣告和搜索刊登廣告、地標"> -			10:7 -		</combo_item> -		<combo_item name="3:2" tool_tip="土地資料"> -			3:2 -		</combo_item> -		<combo_item name="16:10"> -			16:10 -		</combo_item> -		<combo_item name="16:9" tool_tip="個人檔案精選"> -			16:9 -		</combo_item> -		<combo_item name="2:1"> -			2:1 -		</combo_item> -	</combo_box> -	<button label="確定" name="Keep"/> -	<button label="丟棄" name="Discard"/> -	<button label="另存為" name="save_tex_btn"/> +	<layout_stack name="preview_stack"> +		<layout_panel name="texture_panel"> +			<text name="desc txt"> +				描述: +			</text> +			<text name="dimensions"> +				[WIDTH]像素 x [HEIGHT]像素 +			</text> +			<text name="aspect_ratio"> +				預覽長寬比 +			</text> +			<combo_box name="combo_aspect_ratio" tool_tip="以固定長寬比預覽"/> +		</layout_panel> +		<layout_panel name="buttons_panel"> +			<button label="確定" name="Keep"/> +			<button label="丟棄" name="Discard"/> +			<button label="另存為" name="save_tex_btn"/> +		</layout_panel> +	</layout_stack>  </floater> diff --git a/indra/newview/skins/default/xui/zh/floater_profile.xml b/indra/newview/skins/default/xui/zh/floater_profile.xml new file mode 100644 index 0000000000..0f73f527a9 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/floater_profile.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="avatarinfo" title="簡覽"> +	<panel name="panel_profile_view"> +		<tab_container name="panel_profile_tabs"> +			<panel label="第二人生" name="panel_profile_secondlife"/> +			<panel label="網頁" name="panel_profile_web"/> +			<panel label="興趣" name="panel_profile_interests"/> +			<panel label="精選地點" name="panel_profile_picks"/> +			<panel label="分類廣告" name="panel_profile_classifieds"/> +			<panel label="真實世界" name="panel_profile_firstlife"/> +			<panel label="筆記" name="panel_profile_notes"/> +		</tab_container> +		<button label="確定" name="ok_btn" tool_tip="儲存變更到個人檔案後關閉"/> +		<button label="取消" label_selected="取消" name="cancel_btn"/> +	</panel> +</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_snapshot.xml b/indra/newview/skins/default/xui/zh/floater_snapshot.xml index 4090248083..6e1a156762 100644 --- a/indra/newview/skins/default/xui/zh/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/zh/floater_snapshot.xml @@ -6,6 +6,9 @@  	<string name="postcard_progress_str">  		正在發送電郵  	</string> +	<string name="facebook_progress_str"> +		發佈到臉書 +	</string>  	<string name="profile_progress_str">  		發佈  	</string> @@ -15,6 +18,9 @@  	<string name="local_progress_str">  		正在存到電腦  	</string> +	<string name="facebook_succeeded_str"> +		圖像已上傳 +	</string>  	<string name="profile_succeeded_str">  		圖像已上傳  	</string> @@ -27,6 +33,9 @@  	<string name="local_succeeded_str">  		成功存入電腦!  	</string> +	<string name="facebook_failed_str"> +		上傳圖像到你的臉書時間線時失敗。 +	</string>  	<string name="profile_failed_str">  		上傳圖像到你的檔案訊息發佈時出錯。  	</string> diff --git a/indra/newview/skins/default/xui/zh/menu_name_field.xml b/indra/newview/skins/default/xui/zh/menu_name_field.xml new file mode 100644 index 0000000000..5eaf3461cd --- /dev/null +++ b/indra/newview/skins/default/xui/zh/menu_name_field.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<toggleable_menu name="CopyMenu"> +	<menu_item_call label="複製顯示名稱" name="copy_display"/> +	<menu_item_call label="複製代理名稱" name="copy_name"/> +	<menu_item_call label="複製代理ID" name="copy_id"/> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index cfde824349..4d0f1cb85b 100644 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -2666,6 +2666,9 @@ SHA1 指紋:[MD5_DIGEST]  	<notification name="SystemMessage">  		[MESSAGE]  	</notification> +	<notification name="FacebookConnect"> +		[MESSAGE] +	</notification>  	<notification name="FlickrConnect">  		[MESSAGE]  	</notification> diff --git a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml index b06ece02ad..4d3248db46 100644 --- a/indra/newview/skins/default/xui/zh/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/zh/panel_edit_classified.xml @@ -46,7 +46,7 @@  			<layout_panel name="save_changes_btn_lp">  				<button label="[LABEL]" name="save_changes_btn"/>  			</layout_panel> -			<layout_panel name="show_on_map_btn_lp"> +			<layout_panel name="cancel_btn_lp">  				<button label="取消" name="cancel_btn"/>  			</layout_panel>  		</layout_stack> diff --git a/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml new file mode 100644 index 0000000000..fec4bb572a --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_group_list_item_short.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="group_list_item"> +	<text name="group_name" value="未知"/> +	<button name="info_btn" tool_tip="詳情"/> +	<button name="profile_btn" tool_tip="察看檔案"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_me.xml b/indra/newview/skins/default/xui/zh/panel_me.xml deleted file mode 100644 index aad1348e46..0000000000 --- a/indra/newview/skins/default/xui/zh/panel_me.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="我的個人檔案" name="panel_me"> -	<panel label="我的精選地點" name="panel_picks"/> -</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_people.xml b/indra/newview/skins/default/xui/zh/panel_people.xml index b0e60218cf..b95dd96026 100644 --- a/indra/newview/skins/default/xui/zh/panel_people.xml +++ b/indra/newview/skins/default/xui/zh/panel_people.xml @@ -40,6 +40,7 @@  			<accordion name="friends_accordion">  				<accordion_tab name="tab_online" title="上線"/>  				<accordion_tab name="tab_all" title="全部"/> +				<accordion_tab name="tab_suggested_friends" title="你可能想要加為好友的人"/>  			</accordion>  		</panel>  		<panel label="群組" name="groups_panel"> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_classified.xml b/indra/newview/skins/default/xui/zh/panel_profile_classified.xml new file mode 100644 index 0000000000..4eee4e8855 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_classified.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_profile_classified"> +	<panel.string name="type_mature"> +		適度成人 +	</panel.string> +	<panel.string name="type_pg"> +		一般普級內容 +	</panel.string> +	<panel.string name="l$_price"> +		L$[PRICE] +	</panel.string> +	<panel.string name="click_through_text_fmt"> +		[TELEPORT] 瞬間傳送,[MAP] 地圖,[PROFILE] 檔案 +	</panel.string> +	<panel.string name="date_fmt"> +		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] +	</panel.string> +	<panel.string name="auto_renew_on"> +		已啟用 +	</panel.string> +	<panel.string name="auto_renew_off"> +		已停用 +	</panel.string> +	<panel.string name="location_notice"> +		(儲存後將會更新) +	</panel.string> +	<string name="publish_label"> +		發布 +	</string> +	<string name="save_label"> +		儲存 +	</string> +	<scroll_container name="profile_scroll"> +		<panel name="info_scroll_content_panel"> +			<icon label="" name="edit_icon" tool_tip="點按以選擇圖像"/> +			<layout_stack name="info_panel"> +				<layout_panel name="main_info_panel"> +					<text_editor name="classified_name"> +						[name] +					</text_editor> +					<text name="classified_location_label" value="位置:"/> +					<text_editor name="classified_location" value="[loading...]"/> +					<text name="content_type_label" value="內容類型:"/> +					<text_editor name="content_type" value="[content type]"/> +					<text name="category_label" value="分類:"/> +					<text_editor name="category" value="[category]"/> +					<text name="creation_date_label" value="建立日期:"/> +					<text_editor name="creation_date" tool_tip="建立日期" value="[date]"/> +					<text name="price_for_listing_label" value="刊登費:"/> +					<text_editor name="price_for_listing" tool_tip="刊登費。"> +						[PRICE] +					</text_editor> +				</layout_panel> +				<layout_panel name="clickthrough_layout_panel"> +					<text name="click_through_label" value="點按狀況:"/> +					<text_editor name="click_through_text" tool_tip="點按資料" value="[clicks]"/> +				</layout_panel> +				<layout_panel name="auto_renew_layout_panel"> +					<text name="auto_renew_label" value="自動續訂:"/> +					<text name="auto_renew" value="已啟用"/> +				</layout_panel> +				<layout_panel name="descr_layout_panel"> +					<text name="classified_desc_label" value="描述:"/> +					<text_editor name="classified_desc" value="[description]"/> +				</layout_panel> +			</layout_stack> +			<panel name="edit_panel"> +				<text name="Name:"> +					標題: +				</text> +				<text name="description_label"> +					描述: +				</text> +				<text name="location_label"> +					位置: +				</text> +				<text name="classified_location_edit"> +					載入中... +				</text> +				<button label="設定為目前位置" name="set_to_curr_location_btn"/> +				<text name="category_label" value="分類:"/> +				<text name="content_type_label" value="內容類型:"/> +				<icons_combo_box label="一般普級內容" name="content_type_edit"> +					<icons_combo_box.item label="適度成人內容" name="mature_ci" value="適度成人"/> +					<icons_combo_box.item label="一般普級內容" name="pg_ci" value="一般普級"/> +				</icons_combo_box> +				<check_box label="每星期自動續訂" name="auto_renew_edit"/> +				<text name="price_for_listing_edit_label" value="刊登費:"/> +				<spinner label="L$" name="price_for_listing_edit" tool_tip="刊登費。" value="50"/> +			</panel> +		</panel> +	</scroll_container> +	<layout_stack name="edit_btns_pnl"> +		<layout_panel name="teleport_btn_lp"> +			<button label="瞬間傳送" name="teleport_btn"/> +		</layout_panel> +		<layout_panel name="map_btn_lp"> +			<button label="地圖" name="show_on_map_btn"/> +		</layout_panel> +		<layout_panel name="edit_btn_lp"> +			<button label="編輯" name="edit_btn"/> +		</layout_panel> +		<layout_panel name="save_btn_lp"> +			<button label="[LABEL]" name="save_changes_btn"/> +		</layout_panel> +		<layout_panel name="cancel_btn_lp"> +			<button label="取消" name="cancel_btn"/> +		</layout_panel> +	</layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml b/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml new file mode 100644 index 0000000000..89b5cdf641 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_classifieds.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="分類廣告" name="panel_profile_classifieds"> +	<string name="no_classifieds" value="禁止個人廣告"/> +	<button label="新增…" name="new_btn"/> +	<button label="刪除…" name="delete_btn"/> +	<text name="classifieds_panel_text"> +		載入中… +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml new file mode 100644 index 0000000000..9370661d7f --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_firstlife.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="簡覽" name="panel_profile_firstlife"/> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_interests.xml b/indra/newview/skins/default/xui/zh/panel_profile_interests.xml new file mode 100644 index 0000000000..150f3cca4f --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_interests.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="興趣" name="panel_profile_interests"> +	<text name="I Want To:"> +		我想要: +	</text> +	<check_box label="建造" name="chk0"/> +	<check_box label="探索" name="chk1"/> +	<check_box label="見面" name="chk2"/> +	<check_box label="受雇" name="chk6"/> +	<check_box label="群組" name="chk3"/> +	<check_box label="購買" name="chk4"/> +	<check_box label="出售" name="chk5"/> +	<check_box label="招人" name="chk7"/> +	<line_editor name="want_to_edit"> +		(載入中...) +	</line_editor> +	<text name="Skills:"> +		技能: +	</text> +	<check_box label="材質" name="schk0"/> +	<check_box label="架構" name="schk1"/> +	<check_box label="建模" name="schk3"/> +	<check_box label="計畫活動" name="schk2"/> +	<check_box label="建腳本" name="schk4"/> +	<check_box label="定製角色" name="schk5"/> +	<line_editor name="skills_edit"> +		(載入中...) +	</line_editor> +	<text name="Languages:"> +		語言: +	</text> +	<line_editor name="languages_edit"> +		(載入中...) +	</line_editor> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_notes.xml b/indra/newview/skins/default/xui/zh/panel_profile_notes.xml new file mode 100644 index 0000000000..17e1a997da --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_notes.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="筆記和隱私" name="panel_notes"> +	<text name="status_message" value="關於這化身的私人筆記:"/> +	<text name="status_message2" value="允許這個化身:"/> +	<check_box label="看見我何時上線" name="status_check"/> +	<check_box label="在世界地圖上找到我" name="map_check"/> +	<check_box label="邊輯,刪除或取下我的物件" name="objects_check"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_pick.xml b/indra/newview/skins/default/xui/zh/panel_profile_pick.xml new file mode 100644 index 0000000000..5f8d6a2ba5 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_pick.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="panel_pick_info"> +	<panel.string name="location_notice"> +		(儲存後將會更新) +	</panel.string> +	<line_editor name="pick_location"> +		載入中… +	</line_editor> +	<button label="瞬間傳送" name="teleport_btn"/> +	<button label="顯示在地圖上" name="show_on_map_btn"/> +	<button label="設定位置" name="set_to_curr_location_btn" tool_tip="設定為目前位置"/> +	<button label="儲存精選地點" name="save_changes_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_picks.xml b/indra/newview/skins/default/xui/zh/panel_profile_picks.xml new file mode 100644 index 0000000000..8f189d1308 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_picks.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="精選地點" name="panel_picks"> +	<string name="no_picks" value="無精選地點"/> +	<text name="Tell everyone about your favorite places in Second Life."> +		告訴大家你在Second Life中最愛的去處。 +	</text> +	<button label="新增…" name="new_btn"/> +	<button label="刪除…" name="delete_btn"/> +	<text name="picks_panel_text"> +		載入中… +	</text> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml new file mode 100644 index 0000000000..da4aafce55 --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_secondlife.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="簡覽" name="panel_profile"> +	<string name="status_online"> +		目前在線 +	</string> +	<string name="status_offline"> +		目前離線 +	</string> +	<string name="CaptionTextAcctInfo"> +		[ACCTTYPE] +[PAYMENTINFO] +	</string> +	<string name="payment_update_link_url"> +		http://www.secondlife.com/account/billing.php?lang=en +	</string> +	<string name="partner_edit_link_url"> +		http://www.secondlife.com/account/partners.php?lang=en +	</string> +	<string name="my_account_link_url" value="http://secondlife.com/account"/> +	<string name="no_partner_text" value="無"/> +	<string name="no_group_text" value="無"/> +	<string name="RegisterDateFormat"> +		[REG_DATE] +	</string> +	<string name="name_text_args"> +		[NAME] +	</string> +	<string name="display_name_text_args"> +		[DISPLAY_NAME] +	</string> +	<string name="FSDev" value="開發者"/> +	<string name="FSSupp" value="支援"/> +	<string name="FSQualityAssurance" value="除錯獵人"/> +	<string name="FSGW" value="網關"/> +	<text name="name_label" value="名稱:"/> +	<button label="名稱:" name="set_name" tool_tip="設定顯示名稱"/> +	<panel name="name_holder"> +		<text_editor name="complete_name" value="(載入中...)"/> +	</panel> +	<layout_stack name="imagepositioner"> +		<layout_panel name="label_stack"> +			<text name="status" value="狀態不明"/> +			<text name="label" value="Second Life生日:"/> +			<text name="label2" value="帳戶:"/> +			<text name="partner_label" value="伴侶:"/> +		</layout_panel> +	</layout_stack> +	<text name="Groups:" value="群組:"/> +	<button label="+" label_selected="+" name="group_invite" tool_tip="邀請加入群組"/> +	<layout_stack name="aboutpositioner"> +		<layout_panel name="about_stack"> +			<text name="About:" value="關於:"/> +		</layout_panel> +		<layout_panel name="give_stack"> +			<text name="Give item:" value="贈與物品:"/> +			<text name="Give inventory" tool_tip="把收納區物品放到這裡,送給此人。"> +				把收納區物品放到這裡。 +			</text> +		</layout_panel> +	</layout_stack> +	<layout_stack name="buttonstack"> +		<layout_panel name="left_buttonstack"> +			<button label="在地圖上查找" label_selected="在地圖上查找" name="show_on_map_btn" tool_tip="在地圖上找出這個居民"/> +			<button label="支付" label_selected="支付" name="pay" tool_tip="付款給這個居民"/> +		</layout_panel> +		<layout_panel name="middle_buttonstack"> +			<button label="發出瞬間傳送邀請" label_selected="發出瞬間傳送邀請" name="teleport" tool_tip="向這個居民發出瞬間傳送邀請"/> +			<button label="即時訊息" label_selected="即時訊息" name="im" tool_tip="開啟即時訊息會話"/> +		</layout_panel> +		<layout_panel name="right_buttonstack"> +			<button label="加為朋友" label_selected="加為朋友" name="add_friend" tool_tip="向這個居民發出交友邀請"/> +			<button label="封鎖" name="block" tool_tip="封鎖這位居民"/> +			<button label="解除封鎖" name="unblock" tool_tip="不再封鎖這位居民"/> +		</layout_panel> +	</layout_stack> +	<check_box label="在搜尋結果中顯示" name="show_in_search_checkbox"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/panel_profile_web.xml b/indra/newview/skins/default/xui/zh/panel_profile_web.xml new file mode 100644 index 0000000000..566651dceb --- /dev/null +++ b/indra/newview/skins/default/xui/zh/panel_profile_web.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel label="網頁" name="panel_profile_web"> +	<panel.string name="LoadTime" value="載入時間:[TIME]秒"/> +	<line_editor name="url_edit"> +		(載入中…) +	</line_editor> +	<flyout_button label="載入" name="load" tool_tip="用內嵌瀏覽器載入此個人檔案頁面。"> +		<flyout_button.item label="開啓内部瀏覽器" name="open_item"/> +		<flyout_button.item label="開啓外部瀏覽器" name="home_item"/> +	</flyout_button> +	<button name="web_profile_popout_btn" tool_tip="彈出式個人檔案網頁"/> +</panel> diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index a8d5fd90bb..a4e1b21ce6 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -353,6 +353,24 @@ http://secondlife.com/viewer-access-faq  	<string name="TestingDisconnect">  		測試瀏覽器斷線  	</string> +	<string name="SocialFacebookConnecting"> +		連通臉書中… +	</string> +	<string name="SocialFacebookPosting"> +		發佈中… +	</string> +	<string name="SocialFacebookDisconnecting"> +		臉書連通中斷中… +	</string> +	<string name="SocialFacebookErrorConnecting"> +		連通臉書時出問題 +	</string> +	<string name="SocialFacebookErrorPosting"> +		發佈到臉書時出問題 +	</string> +	<string name="SocialFacebookErrorDisconnecting"> +		試圖中斷臉書連通時出問題 +	</string>  	<string name="SocialFlickrConnecting">  		連通 Flickr 中…  	</string> @@ -2569,9 +2587,21 @@ http://secondlife.com/support 求助解決問題。  	<string name="NoPicksClassifiedsText">  		你尚未建立任何精選地點或個人廣告。 點按下面的 + 按鈕建立精選地點或個人廣告。  	</string> +	<string name="NoPicksText"> +		你尚未建立任何精選地點。 點按「新增」按鈕建立精選地點。 +	</string> +	<string name="NoClassifiedsText"> +		你尚未建立任何分類廣告。 點按「新增」按鈕建立分類廣告。 +	</string>  	<string name="NoAvatarPicksClassifiedsText">  		使用者無精選地點或個人廣告  	</string> +	<string name="NoAvatarPicksText"> +		使用者沒有精選地點 +	</string> +	<string name="NoAvatarClassifiedsText"> +		使用者沒有分類廣告 +	</string>  	<string name="PicksClassifiedsLoadingText">  		載入中...  	</string> @@ -4549,6 +4579,9 @@ http://secondlife.com/support 求助解決問題。  	<string name="share_alert">  		將收納區物品拖曳到這裡  	</string> +	<string name="facebook_post_success"> +		成功發佈到臉書。 +	</string>  	<string name="flickr_post_success">  		成功發佈到 Flickr。  	</string> diff --git a/indra/newview/tests/llviewercontrollistener_test.cpp b/indra/newview/tests/llviewercontrollistener_test.cpp new file mode 100644 index 0000000000..6d100ef984 --- /dev/null +++ b/indra/newview/tests/llviewercontrollistener_test.cpp @@ -0,0 +1,174 @@ +/** + * @file   llviewercontrollistener_test.cpp + * @author Nat Goodspeed + * @date   2022-06-09 + * @brief  Test for llviewercontrollistener. + *  + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llviewercontrollistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h" // catch_what() +#include "commoncontrol.h" +#include "llcontrol.h"              // LLControlGroup +#include "llviewercontrollistener.h" + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    void ensure_contains(const std::string& msg, const std::string& substr) +    { +        ensure_contains("Exception does not contain " + substr, msg, substr); +    } + +    struct llviewercontrollistener_data +    { +        LLControlGroup Global{"FakeGlobal"}; + +        llviewercontrollistener_data() +        { +            Global.declareString("strvar", "woof", "string variable"); +            // together we will stroll the boolvar, ma cherie +            Global.declareBOOL("boolvar",  TRUE, "bool variable"); +        } +    }; +    typedef test_group<llviewercontrollistener_data> llviewercontrollistener_group; +    typedef llviewercontrollistener_group::object object; +    llviewercontrollistener_group llviewercontrollistenergrp("llviewercontrollistener"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("CommonControl no listener"); +        // Not implemented: the linker drags in LLViewerControlListener when +        // we bring in LLViewerControl. +    } + +    template<> template<> +    void object::test<2>() +    { +        set_test_name("CommonControl bad group"); +        std::string threw{ catch_what<LL::CommonControl::ParamError>( +                [](){ LL::CommonControl::get("Nonexistent", "Variable"); }) }; +        ensure_contains(threw, "group"); +        ensure_contains(threw, "Nonexistent"); +    } + +    template<> template<> +    void object::test<3>() +    { +        set_test_name("CommonControl bad variable"); +        std::string threw{ catch_what<LL::CommonControl::ParamError>( +                [](){ LL::CommonControl::get("FakeGlobal", "Nonexistent"); }) }; +        ensure_contains(threw, "key"); +        ensure_contains(threw, "Nonexistent"); +    } + +    template<> template<> +    void object::test<4>() +    { +        set_test_name("CommonControl toggle string"); +        std::string threw{ catch_what<LL::CommonControl::ParamError>( +                [](){ LL::CommonControl::toggle("FakeGlobal", "strvar"); }) }; +        ensure_contains(threw, "non-boolean"); +        ensure_contains(threw, "strvar"); +    } + +    template<> template<> +    void object::test<5>() +    { +        set_test_name("CommonControl list bad group"); +        std::string threw{ catch_what<LL::CommonControl::ParamError>( +                [](){ LL::CommonControl::get_vars("Nonexistent"); }) }; +        ensure_contains(threw, "group"); +        ensure_contains(threw, "Nonexistent"); +    } + +    template<> template<> +    void object::test<6>() +    { +        set_test_name("CommonControl get"); +        auto strvar{ LL::CommonControl::get("FakeGlobal", "strvar") }; +        ensure_equals(strvar, "woof"); +        auto boolvar{ LL::CommonControl::get("FakeGlobal", "boolvar") }; +        ensure(boolvar); +    } + +    template<> template<> +    void object::test<7>() +    { +        set_test_name("CommonControl set, set_default, toggle"); + +        std::string newstr{ LL::CommonControl::set("FakeGlobal", "strvar", "mouse").asString() }; +        ensure_equals(newstr, "mouse"); +        ensure_equals(LL::CommonControl::get("FakeGlobal", "strvar").asString(), "mouse"); +        ensure_equals(LL::CommonControl::set_default("FakeGlobal", "strvar").asString(), "woof"); + +        bool newbool{ LL::CommonControl::set("FakeGlobal", "boolvar", false) }; +        ensure(! newbool); +        ensure(! LL::CommonControl::get("FakeGlobal", "boolvar").asBoolean()); +        ensure(LL::CommonControl::set_default("FakeGlobal", "boolvar").asBoolean()); +        ensure(! LL::CommonControl::toggle("FakeGlobal", "boolvar").asBoolean()); +    } + +    template<> template<> +    void object::test<8>() +    { +        set_test_name("CommonControl get_def"); +        LLSD def{ LL::CommonControl::get_def("FakeGlobal", "strvar") }; +        ensure_equals( +            def, +            llsd::map("name", "strvar", +                      "type", "String", +                      "value", "woof", +                      "comment", "string variable")); +    } + +    template<> template<> +    void object::test<9>() +    { +        set_test_name("CommonControl get_groups"); +        std::vector<std::string> groups{ LL::CommonControl::get_groups() }; +        ensure_equals(groups.size(), 1); +        ensure_equals(groups[0], "FakeGlobal"); +    } + +    template<> template<> +    void object::test<10>() +    { +        set_test_name("CommonControl get_vars"); +        LLSD vars{ LL::CommonControl::get_vars("FakeGlobal") }; +        // convert from array (unpredictable order) to map +        LLSD varsmap{ LLSD::emptyMap() }; +        for (auto& var : llsd::inArray(vars)) +        { +            varsmap[var["name"].asString()] = var; +        } +        // comparing maps is order-insensitive +        ensure_equals( +            varsmap, +            llsd::map( +                "strvar", +                llsd::map("name", "strvar", +                          "type", "String", +                          "value", "woof", +                          "comment", "string variable"), +                "boolvar", +                llsd::map("name", "boolvar", +                          "type", "Boolean", +                          "value", TRUE, +                          "comment", "bool variable"))); +    } +} // namespace tut diff --git a/indra/test/test.cpp b/indra/test/test.cpp index bb48216b2b..28f25087ac 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -401,7 +401,7 @@ public:  	{  		// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages  		std::string result; -		BOOST_FOREACH(char c, str) +		for (char c : str)  		{  			switch (c)  			{  | 
