Ansariel 2021-05-02 13:50:45 +02:00
commit c516f1fc9a
128 changed files with 2287 additions and 1707 deletions

View File

@ -2405,18 +2405,18 @@
<key>archive</key>
<map>
<key>hash</key>
<string>c541838a933e0714a954e9ef6c89345d</string>
<string>40a87f5d505a141b2ec79513a6197c35</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/73387/708088/llca-202012011600.553112-common-553112.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76516/728250/llca-202102021657.555615-common-555615.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>202012011600.553112</string>
<string>202102021657.555615</string>
</map>
<key>llphysicsextensions_source</key>
<map>
@ -2839,26 +2839,14 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<string>open-libndofdev</string>
<key>platforms</key>
<map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>246ed298944fd5200e4cac3703d6e075</string>
<key>url</key>
<string>http://3p.firestormviewer.org/open_libndofdev-0.9.183150124-linux-183150124.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>db8a7126178e7230fd6917a28cd67bd7</string>
<string>88fb222412b98a7f371d6bf2ff42a973</string>
<key>url</key>
<string>http://3p.firestormviewer.org/open_libndofdev-0.9.183150121-linux64-183150121.tar.bz2</string>
<string>http://3p.firestormviewer.org/open_libndofdev-0.13.211211036-linux64-211211036.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
@ -3346,9 +3334,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>d463360491b6b5cb7a57cd67a90ececb</string>
<string>60f008c5fd31641ad4e61ac751ce15d1</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54838/510050/uriparser-0.8.0.1-darwin64-538968.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75748/723495/uriparser-0.9.4-darwin64-555117.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3370,9 +3358,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>df570f2b9c0087438604a8ba4dc37a85</string>
<string>0d6832fd958ec127f089e683c9b67169</string>
<key>url</key>
<string>http://3p.firestormviewer.org/uriparser-0.8.0.1-linux64-180841550.tar.bz2</string>
<string>http://3p.firestormviewer.org/uriparser-0.9.4-linux64-211210958.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
@ -3382,9 +3370,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>57a88be57694de6cf9f516125af2c4c9</string>
<string>00aff37a6f5e1fe08456702d28706cf6</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54963/511746/uriparser-0.8.0.1-windows-538968.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75751/723507/uriparser-0.9.4-windows-555117.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3394,16 +3382,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>f39cc91f2a5dad13790ec18269844ae4</string>
<string>ff27a91f3941c7bef5e1613a064cb048</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54962/511739/uriparser-0.8.0.1-windows64-538968.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/75750/723506/uriparser-0.9.4-windows64-555117.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>0.8.0.1</string>
<string>0.9.4</string>
</map>
<key>viewer-manager</key>
<map>
@ -3424,9 +3412,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>c5ab9d9d7482e48cd76f4bf391900a8c</string>
<string>6989053898b8e81e904e75553e378820</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43369/385585/viewer_manager-2.0.531000-darwin64-531000.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77523/735051/viewer_manager-2.0.556340-darwin64-556340.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3460,9 +3448,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>6b10d7407686d9e12e63576256581e3e</string>
<string>3446c1e54bb32542677caad0ec0d42ac</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43370/385592/viewer_manager-2.0.531000-windows-531000.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77525/735058/viewer_manager-2.0.556340-windows-556340.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3473,7 +3461,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>hg</string>
<key>version</key>
<string>2.0.531000</string>
<string>2.0.556340</string>
</map>
<key>vlc-bin</key>
<map>

View File

@ -228,6 +228,7 @@ Ansariel Hiller
SL-13364
SL-13858
SL-13697
SL-3136
Aralara Rajal
Arare Chantilly
CHUIBUG-191
@ -265,11 +266,11 @@ Benja Kepler
Benjamin Bigdipper
Beq Janus
BUG-227094
Beth Walcher
Beq Janus
SL-10288
SL-13583
SL-14766
SL-11300
Beth Walcher
Bezilon Kasei
Biancaluce Robbiani
CT-225

View File

@ -61,6 +61,7 @@ if(WINDOWS)
nghttp2.dll
glod.dll
libhunspell.dll
uriparser.dll
)
# <FS:Ansariel> Only copy OpenJPEG dll if needed
@ -197,6 +198,9 @@ elseif(DARWIN)
libnghttp2.dylib
libnghttp2.14.dylib
libnghttp2.14.19.0.dylib
liburiparser.dylib
liburiparser.1.dylib
liburiparser.1.0.27.dylib
libgrowl.dylib
libgrowl++.dylib
)

View File

@ -29,7 +29,7 @@ else (USESYSTEMLIBS)
set(URIPARSER_PRELOAD_ARCHIVES -Wl,--whole-archive uriparser -Wl,--no-whole-archive)
set(URIPARSER_LIBRARIES uriparser)
elseif (DARWIN)
set(URIPARSER_LIBRARIES uriparser)
set(URIPARSER_LIBRARIES liburiparser.dylib)
endif (WINDOWS)
set(URIPARSER_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/uriparser)
endif (USESYSTEMLIBS)

View File

@ -56,10 +56,6 @@
#include "stringize.h"
#include "llexception.h"
#if LL_WINDOWS
#include <excpt.h>
#endif
// static
LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)
{
@ -252,29 +248,13 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
void LLCoros::winlevel(const callable_t& callable)
{
__try
{
callable();
}
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
__except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
// convert to C++ styled exception
// Note: it might be better to use _se_set_translator

View File

@ -24,11 +24,14 @@
// `_GNU_SOURCE` macro or `BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED` if
// _Unwind_Backtrace is available without `_GNU_SOURCE`."
#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
#if LL_WINDOWS
// On Windows, header-only implementation causes macro collisions -- use
// prebuilt library
#define BOOST_STACKTRACE_LINK
#include <excpt.h>
#endif // LL_WINDOWS
#include <boost/stacktrace.hpp>
// other Linden headers
#include "llerror.h"
@ -85,3 +88,25 @@ void annotate_exception_(boost::exception& exc)
// Anyway, which of us is really going to examine more than 100 frames?
exc << errinfo_stacktrace(boost::stacktrace::stacktrace(1, 100));
}
#if LL_WINDOWS
// For windows SEH exception handling we sometimes need a filter that will
// separate C++ exceptions from C SEH exceptions
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
#endif //LL_WINDOWS

View File

@ -102,4 +102,14 @@ void crash_on_unhandled_exception_(const char*, int, const char*, const std::str
log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
void log_unhandled_exception_(const char*, int, const char*, const std::string&);
#if LL_WINDOWS
// SEH exception filtering for use in __try __except
// Separates C++ exceptions from C SEH exceptions
// Todo: might be good idea to do some kind of seh_to_msc_wrapper(function, ARGS&&);
U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop);
#endif //LL_WINDOWS
#endif /* ! defined(LL_LLEXCEPTION_H) */

View File

@ -55,6 +55,7 @@
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_float.hpp>
#include "llfasttimer.h"
using namespace llsd;
@ -741,10 +742,7 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32
// Sigh, this shouldn't be a static method, then we wouldn't have to
// reload this data separately from refresh()
// <FS:ND> We only care for a subset of what loadStatsMap calculates. Pass true to skip the expensive stuff
// LLSD statsMap(loadStatsMap());
LLSD statsMap( loadStatsMap( true ) );
// </FS:ND>
LLSD statsMap(loadStatsMap());
avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
@ -880,12 +878,12 @@ LLMemoryInfo& LLMemoryInfo::refresh()
return *this;
}
// <FS:ND> Add aProcessMemoryOnly, which for Windows will only call GlobalMemoryStatusEx
// This avoids calling GetPerformanceInfo which can be expensive.
//LLSD LLMemoryInfo::loadStatsMap()
LLSD LLMemoryInfo::loadStatsMap( bool aProcessMemoryOnly )
// </FS:ND>
static LLTrace::BlockTimerStatHandle FTM_MEMINFO_LOAD_STATS("MemInfo Load Stats");
LLSD LLMemoryInfo::loadStatsMap()
{
LL_RECORD_BLOCK_TIME(FTM_MEMINFO_LOAD_STATS);
// This implementation is derived from stream() code (as of 2011-06-29).
Stats stats;
@ -915,29 +913,11 @@ LLSD LLMemoryInfo::loadStatsMap( bool aProcessMemoryOnly )
stats.add("Avail Virtual KB", llclamp(state.ullAvailVirtual/div, U64(0), U64(S32_MAX)));
// </FS:Ansariel>
// <FS:ND> Early out in case only process memory is requested.
if( aProcessMemoryOnly )
return stats.get();
// </FS:ND>
PERFORMANCE_INFORMATION perf;
perf.cb = sizeof(perf);
GetPerformanceInfo(&perf, sizeof(perf));
SIZE_T pagekb(perf.PageSize/1024);
stats.add("CommitTotal KB", perf.CommitTotal * pagekb);
stats.add("CommitLimit KB", perf.CommitLimit * pagekb);
stats.add("CommitPeak KB", perf.CommitPeak * pagekb);
stats.add("PhysicalTotal KB", perf.PhysicalTotal * pagekb);
stats.add("PhysicalAvail KB", perf.PhysicalAvailable * pagekb);
stats.add("SystemCache KB", perf.SystemCache * pagekb);
stats.add("KernelTotal KB", perf.KernelTotal * pagekb);
stats.add("KernelPaged KB", perf.KernelPaged * pagekb);
stats.add("KernelNonpaged KB", perf.KernelNonpaged * pagekb);
stats.add("PageSize KB", pagekb);
stats.add("HandleCount", perf.HandleCount);
stats.add("ProcessCount", perf.ProcessCount);
stats.add("ThreadCount", perf.ThreadCount);
// SL-12122 - Call to GetPerformanceInfo() was removed here. Took
// on order of 10 ms, causing unacceptable frame time spike every
// second, and results were never used. If this is needed in the
// future, must find a way to avoid frame time impact (e.g. move
// to another thread, call much less often).
PROCESS_MEMORY_COUNTERS_EX pmem;
pmem.cb = sizeof(pmem);

View File

@ -134,12 +134,7 @@ public:
private:
// set mStatsMap
// <FS:ND> Add aProcessMemoryOnly, which for Windows will only call GlobalMemoryStatusEx
// This avoids calling GetPerformanceInfo which can be expensive.
// static LLSD loadStatsMap();
static LLSD loadStatsMap( bool aProcessMemoryOnly = false );
// </FS:ND>
static LLSD loadStatsMap();
// Memory stats for getStatsMap().
LLSD mStatsMap;

View File

@ -29,14 +29,13 @@
#include "linden_common.h"
#include "lluriparser.h"
#if !LL_WINDOWS
#include <stdint.h>
#if LL_DARWIN
#include <signal.h>
#include <setjmp.h>
#endif
LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedTmp(false), mRes(0)
{
mState.uri = &mUri;
if (u.find("://") == std::string::npos)
{
mNormalizedUri = "http://";
@ -55,7 +54,7 @@ LLUriParser::~LLUriParser()
S32 LLUriParser::parse()
{
mRes = uriParseUriA(&mState, mNormalizedUri.c_str());
mRes = uriParseSingleUriA(&mUri, mNormalizedUri.c_str(), NULL);
return mRes;
}
@ -162,31 +161,69 @@ void LLUriParser::extractParts()
}
}
#if LL_DARWIN
typedef void(*sighandler_t)(int);
jmp_buf return_to_normalize;
void uri_signal_handler(int signal)
{
// Apparently signal handler throwing an exception doesn't work.
// This is ugly and unsafe due to not unwinding content of uriparser library,
// but unless we have a way to catch this as NSexception, jump appears to be the only option.
longjmp(return_to_normalize, 1 /*setjmp will return this value*/);
}
#endif
S32 LLUriParser::normalize()
{
mNormalizedTmp = mTmpScheme;
if (!mRes)
{
mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
#if LL_DARWIN
sighandler_t last_handler;
last_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction
if (setjmp(return_to_normalize))
{
// Issue: external library crashed via signal
// If you encountered this, please try to figure out what's wrong:
// 1. Verify that library's input is 'sane'
// 2. Check if we have an NSexception to work with (unlikely)
// 3. See if passing same string causes exception to repeat
//
// Crash happens at uriNormalizeSyntaxExA
// Warning!!! This does not properly unwind stack,
// if this can be handled by NSexception, it needs to be remade
llassert(0);
if (!mRes)
{
S32 chars_required;
mRes = uriToStringCharsRequiredA(&mUri, &chars_required);
LL_WARNS() << "Uriparser crashed with SIGILL, while processing: " << mNormalizedUri << LL_ENDL;
signal(SIGILL, last_handler);
return 1;
}
#endif
if (!mRes)
{
chars_required++;
std::vector<char> label_buf(chars_required);
mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL);
mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST);
if (!mRes)
{
mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0];
mTmpScheme = false;
}
}
}
#if LL_DARWIN
signal(SIGILL, last_handler);
#endif
if (!mRes)
{
S32 chars_required;
mRes = uriToStringCharsRequiredA(&mUri, &chars_required);
if (!mRes)
{
chars_required++;
std::vector<char> label_buf(chars_required);
mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL);
if (!mRes)
{
mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0];
mTmpScheme = false;
}
}
}
}
if(mTmpScheme)

View File

@ -79,7 +79,6 @@ private:
std::string mFragment;
std::string mNormalizedUri;
UriParserStateA mState;
UriUriA mUri;
S32 mRes;

View File

@ -182,6 +182,7 @@ if (DARWIN)
libaprutil-1.0.dylib
libexception_handler.dylib
libnghttp2*.dylib
liburiparser*.dylib
${EXPAT_COPY}
)

View File

@ -255,7 +255,7 @@ public:
virtual void logAssetStorageInfo() = 0;
void checkForTimeouts();
virtual void checkForTimeouts();
void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,

View File

@ -146,10 +146,10 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
}
LLSD httpResults;
bool success = true;
try
{
bool success = true;
LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("NameCache", sHttpPolicy);
LLSD results = httpAdapter.getAndSuspend(sHttpRequest, url);
@ -164,35 +164,47 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
else
{
httpResults = results["http_result"];
success = httpResults["success"].asBoolean();
if (!httpResults.isMap())
{
success = false;
LL_WARNS("AvNameCache") << " Invalid http_result returned from LLCoreHttpUtil::HttpCoroHandler." << LL_ENDL;
}
else
{
success = httpResults["success"].asBoolean();
if (!success)
{
LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
<< httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
}
}
}
if (LLAvatarNameCache::instanceExists())
{
if (!success)
{
LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
<< httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
{ // on any sort of failure add dummy records for any agent IDs
// in this request that we do not have cached already
std::vector<LLUUID>::const_iterator it = agentIds.begin();
for (; it != agentIds.end(); ++it)
{
const LLUUID& agent_id = *it;
LLAvatarNameCache::getInstance()->handleAgentError(agent_id);
}
return;
}
LLAvatarNameCache::getInstance()->handleAvNameCacheSuccess(results, httpResults);
}
if (!success)
{ // on any sort of failure add dummy records for any agent IDs
// in this request that we do not have cached already
std::vector<LLUUID>::const_iterator it = agentIds.begin();
for ( ; it != agentIds.end(); ++it)
{
const LLUUID& agent_id = *it;
LLAvatarNameCache::getInstance()->handleAgentError(agent_id);
}
return;
}
LLAvatarNameCache::getInstance()->handleAvNameCacheSuccess(results, httpResults);
}
catch (...)
{
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::getName()
<< "('" << url << "', " << agentIds.size()
<< " http result: " << httpResults.asString()
<< " Agent Ids)"));
<< "('" << url << "', "
<< agentIds.size() << "Agent Ids,"
<< " http result: " << S32(success)
<< " has response: " << S32(httpResults.size())
<< ")"));
throw;
}
}

View File

@ -47,7 +47,7 @@ static const std::map<std::string, U32> DefaultPoolSizes{
};
static const U32 DEFAULT_POOL_SIZE = 5;
static const U32 DEFAULT_QUEUE_SIZE = 4096;
const U32 LLCoprocedureManager::DEFAULT_QUEUE_SIZE = 4096;
//=========================================================================
class LLCoprocedurePool: private boost::noncopyable
@ -194,7 +194,7 @@ void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpd
mPropertyDefineFn = updatefn;
// workaround until we get mutex into initializePool
initializePool("VAssetStorage");
initializePool("AssetStorage");
initializePool("Upload");
initializePool("AIS");
initializePool("ExpCache"); // <FS:Ansariel> FIRE-30731: ExpCache coroutine pool crash
@ -283,7 +283,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
mPoolSize(size),
mActiveCoprocsCount(0),
mPending(0),
mPendingCoprocs(boost::make_shared<CoprocQueue_t>(DEFAULT_QUEUE_SIZE)),
mPendingCoprocs(boost::make_shared<CoprocQueue_t>(LLCoprocedureManager::DEFAULT_QUEUE_SIZE)),
mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mCoroMapping()
{
@ -334,7 +334,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
mCoroMapping.insert(CoroAdapterMap_t::value_type(pooledCoro, httpAdapter));
}
LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << DEFAULT_QUEUE_SIZE << LL_ENDL;
LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << LLCoprocedureManager::DEFAULT_QUEUE_SIZE << LL_ENDL;
}
LLCoprocedurePool::~LLCoprocedurePool()

View File

@ -91,6 +91,9 @@ private:
SettingQuery_t mPropertyQueryFn;
SettingUpdate_t mPropertyDefineFn;
public:
static const U32 DEFAULT_QUEUE_SIZE;
};
#endif

View File

@ -28,6 +28,8 @@
#include "llmaterial.h"
#include "../llrender/llglheaders.h"
/**
* Materials cap parameters
*/
@ -105,6 +107,8 @@ LLMaterial::LLMaterial()
, mSpecularLightExponent(LLMaterial::DEFAULT_SPECULAR_LIGHT_EXPONENT)
, mEnvironmentIntensity(LLMaterial::DEFAULT_ENV_INTENSITY)
, mDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
, mDiffuseFormatPrimary(GL_RGBA)
, mDiffuseBaked(false)
, mAlphaMaskCutoff(0)
{
}
@ -311,6 +315,20 @@ void LLMaterial::setEnvironmentIntensity(U8 intensity)
mEnvironmentIntensity = intensity;
}
U8 LLMaterial::getDiffuseAlphaModeRender() const
{
if (mDiffuseBaked
|| mDiffuseFormatPrimary == GL_RGBA
|| mDiffuseFormatPrimary == GL_ALPHA)
{
return mDiffuseAlphaMode;
}
else
{
return DIFFUSE_ALPHA_MODE_NONE;
}
}
U8 LLMaterial::getDiffuseAlphaMode() const
{
return mDiffuseAlphaMode;
@ -321,6 +339,26 @@ void LLMaterial::setDiffuseAlphaMode(U8 alpha_mode)
mDiffuseAlphaMode = alpha_mode;
}
U32 LLMaterial::getDiffuseFormatPrimary() const
{
return mDiffuseFormatPrimary;
}
void LLMaterial::setDiffuseFormatPrimary(U32 format_primary)
{
mDiffuseFormatPrimary = format_primary;
}
bool LLMaterial::getIsDiffuseBaked() const
{
return mDiffuseBaked;
}
void LLMaterial::setDiffuseBaked(bool baked)
{
mDiffuseBaked = baked;
}
U8 LLMaterial::getAlphaMaskCutoff() const
{
return mAlphaMaskCutoff;
@ -437,7 +475,7 @@ U32 LLMaterial::getShaderMask(U32 alpha_mode)
}
else
{
ret = getDiffuseAlphaMode();
ret = getDiffuseAlphaModeRender();
}
llassert(ret < SHADER_COUNT);

View File

@ -115,8 +115,17 @@ public:
void setSpecularLightExponent(U8 exponent);
U8 getEnvironmentIntensity() const;
void setEnvironmentIntensity(U8 intensity);
// getDiffuseAlphaModeRender takes into account if image supports alpha
// and returns value apropriate for render
// getDiffuseAlphaMode() returns value as is
U8 getDiffuseAlphaModeRender() const;
U8 getDiffuseAlphaMode() const;
void setDiffuseAlphaMode(U8 alpha_mode);
U32 getDiffuseFormatPrimary() const;
void setDiffuseFormatPrimary(U32 format_primary);
bool getIsDiffuseBaked() const;
void setDiffuseBaked(bool baked);
U8 getAlphaMaskCutoff() const;
void setAlphaMaskCutoff(U8 cutoff);
@ -147,6 +156,8 @@ protected:
U8 mSpecularLightExponent;
U8 mEnvironmentIntensity;
U8 mDiffuseAlphaMode;
U32 mDiffuseFormatPrimary; // value from texture, LLGLenum, is not included in fromLLSD/asLLSD
bool mDiffuseBaked; // is not included in fromLLSD/asLLSD
U8 mAlphaMaskCutoff;
};

View File

@ -1277,6 +1277,14 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn
LL_INFOS("MESHSKININFO")<<"Material of model is not a subset of reference."<<LL_ENDL;
return false;
}
if (mMaterialList.size() > ref->mMaterialList.size())
{
LL_INFOS("MESHSKININFO") << "Material of model has more materials than a reference." << LL_ENDL;
// We passed isMaterialListSubset, so materials are a subset, but subset isn't supposed to be
// larger than original and if we keep going, reordering will cause a crash
return false;
}
std::map<std::string, U32> index_map;

View File

@ -197,10 +197,32 @@ void LLCheckBoxCtrl::clear()
void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
{
S32 label_top = mLabel->getRect().mTop;
mLabel->reshapeToFitText();
LLRect rect = getRect();
S32 delta_width = width - rect.getWidth();
S32 delta_height = height - rect.getHeight();
LLRect label_rect = mLabel->getRect();
if (delta_width || delta_height)
{
// adjust our rectangle
rect.mRight = getRect().mLeft + width;
rect.mTop = getRect().mBottom + height;
setRect(rect);
}
// reshapeToFitText reshapes label to minimal size according to last bounding box
// it will work fine in case of decrease of space, but if we get more space or text
// becomes longer, label will fail to grow so reinit label's dimentions.
static LLUICachedControl<S32> llcheckboxctrl_hpad("UICheckboxctrlHPad", 0);
LLRect label_rect = mLabel->getRect();
S32 new_width = getRect().getWidth() - label_rect.mLeft - llcheckboxctrl_hpad;
label_rect.mRight = label_rect.mLeft + new_width;
mLabel->setRect(label_rect);
S32 label_top = label_rect.mTop;
mLabel->reshapeToFitText(TRUE);
label_rect = mLabel->getRect();
if (label_top != label_rect.mTop && mWordWrap == WRAP_DOWN)
{
// reshapeToFitText uses LLView::reshape() which always reshapes
@ -220,6 +242,8 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llmax(btn_rect.getWidth(), label_rect.mRight - btn_rect.mLeft),
llmax(label_rect.mTop - btn_rect.mBottom, btn_rect.getHeight()));
mButton->setShape(btn_rect);
updateBoundingRect();
}
//virtual

View File

@ -205,6 +205,7 @@ public:
virtual bool hasChildren() const = 0;
virtual void addChild(LLFolderViewModelItem* child) = 0;
virtual void removeChild(LLFolderViewModelItem* child) = 0;
virtual void clearChildren() = 0;
// This method will be called to determine if a drop can be
// performed, and will set drop to TRUE if a drop is
@ -311,9 +312,8 @@ public:
virtual void clearChildren()
{
// As this is cleaning the whole list of children wholesale, we do need to delete the pointed objects
// This is different and not equivalent to calling removeChild() on each child
std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
// We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest
std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); });
mChildren.clear();
dirtyDescendantsFilter();
dirtyFilter();

View File

@ -166,7 +166,7 @@ void LLLayoutPanel::setVisible( BOOL visible )
void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ )
{
if (width == getRect().getWidth() && height == getRect().getHeight()) return;
if (width == getRect().getWidth() && height == getRect().getHeight() && !LLView::sForceReshape) return;
if (!mIgnoreReshape && mAutoResize == false)
{

View File

@ -3303,7 +3303,7 @@ void hide_top_view( LLView* view )
// x and y are the desired location for the popup, in the spawning_view's
// coordinate frame, NOT necessarily the mouse location
// static
void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x, S32 mouse_y)
{
const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
const S32 CURSOR_WIDTH = 12;
@ -3334,12 +3334,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
}
}
// Save click point for detecting cursor moves before mouse-up.
// Must be in local coords to compare with mouseUp events.
// If the mouse doesn't move, the menu will stay open ala the Mac.
// See also LLContextMenu::show()
S32 mouse_x, mouse_y;
// Resetting scrolling position
if (menu->isScrollable() && menu->isScrollPositionOnShowReset())
{
@ -3350,7 +3344,18 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
menu->needsArrange();
menu->arrangeAndClear();
LLUI::getInstance()->getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
if ((mouse_x == 0) || (mouse_y == 0))
{
// Save click point for detecting cursor moves before mouse-up.
// Must be in local coords to compare with mouseUp events.
// If the mouse doesn't move, the menu will stay open ala the Mac.
// See also LLContextMenu::show()
LLUI::getInstance()->getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
}
LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y);
const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getRect();

View File

@ -520,7 +520,7 @@ public:
void createJumpKeys();
// Show popup at a specific location, in the spawn_view's coordinate frame
static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y);
static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x = 0, S32 mouse_y = 0);
// Whether to drop shadow menu bar
void setDropShadowed( const BOOL shadowed );

View File

@ -1257,7 +1257,7 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (width != getRect().getWidth() || height != getRect().getHeight())
if (width != getRect().getWidth() || height != getRect().getHeight() || LLView::sForceReshape)
{
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;

View File

@ -167,13 +167,13 @@ BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text
}
void LLTextBox::reshapeToFitText()
void LLTextBox::reshapeToFitText(BOOL called_from_parent)
{
reflow();
S32 width = getTextPixelWidth();
S32 height = getTextPixelHeight();
reshape( width + 2 * mHPad, height + 2 * mVPad, FALSE );
reshape( width + 2 * mHPad, height + 2 * mVPad, called_from_parent );
}

View File

@ -60,7 +60,7 @@ public:
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL );
void reshapeToFitText();
void reshapeToFitText(BOOL called_from_parent = FALSE);
S32 getTextPixelWidth();
S32 getTextPixelHeight();

View File

@ -586,11 +586,7 @@ LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
//
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//LLUrlEntryAgent::LLUrlEntryAgent() :
// mAvatarNameCacheConnection()
LLUrlEntryAgent::LLUrlEntryAgent()
// </FS:Ansariel>
{
mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/\\w+",
boost::regex::perl|boost::regex::icase);
@ -622,7 +618,15 @@ void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
const LLAvatarName& av_name)
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//mAvatarNameCacheConnection.disconnect();
//avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
//if (it != mAvatarNameCacheConnections.end())
//{
// if (it->second.connected())
// {
// it->second.disconnect();
// }
// mAvatarNameCacheConnections.erase(it);
//}
std::pair<avatar_name_cache_connection_map_t::iterator, avatar_name_cache_connection_map_t::iterator> range;
range = mAvatarNameCacheConnections.equal_range(id);
for (avatar_name_cache_connection_map_t::iterator it = range.first; it != range.second; ++it)
@ -721,11 +725,16 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
else
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//if (mAvatarNameCacheConnection.connected())
//avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id);
//if (it != mAvatarNameCacheConnections.end())
//{
// mAvatarNameCacheConnection.disconnect();
// if (it->second.connected())
// {
// it->second.disconnect();
// }
// mAvatarNameCacheConnections.erase(it);
//}
//mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2));
//mAvatarNameCacheConnections[agent_id] = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2));
boost::signals2::connection connection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgent::onAvatarNameCache, this, _1, _2));
mAvatarNameCacheConnections.insert(std::make_pair(agent_id, connection));
// </FS:Ansariel>
@ -789,18 +798,22 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url)
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
//
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//LLUrlEntryAgentName::LLUrlEntryAgentName() :
// mAvatarNameCacheConnection()
LLUrlEntryAgentName::LLUrlEntryAgentName()
// </FS:Ansariel>
{}
void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
const LLAvatarName& av_name)
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//mAvatarNameCacheConnection.disconnect();
//avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
//if (it != mAvatarNameCacheConnections.end())
//{
// if (it->second.connected())
// {
// it->second.disconnect();
// }
// mAvatarNameCacheConnections.erase(it);
//}
std::pair<avatar_name_cache_connection_map_t::iterator, avatar_name_cache_connection_map_t::iterator> range;
range = mAvatarNameCacheConnections.equal_range(id);
for (avatar_name_cache_connection_map_t::iterator it = range.first; it != range.second; ++it)
@ -847,11 +860,16 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab
else
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//if (mAvatarNameCacheConnection.connected())
//avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id);
//if (it != mAvatarNameCacheConnections.end())
//{
// mAvatarNameCacheConnection.disconnect();
// if (it->second.connected())
// {
// it->second.disconnect();
// }
// mAvatarNameCacheConnections.erase(it);
//}
//mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2));
//mAvatarNameCacheConnections[agent_id] = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2));
boost::signals2::connection connection = LLAvatarNameCache::get(agent_id, boost::bind(&LLUrlEntryAgentName::onAvatarNameCache, this, _1, _2));
mAvatarNameCacheConnections.insert(std::make_pair(agent_id, connection));
// </FS:Ansariel>

View File

@ -227,11 +227,6 @@ public:
LLUrlEntryAgent();
~LLUrlEntryAgent()
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//if (mAvatarNameCacheConnection.connected())
//{
// mAvatarNameCacheConnection.disconnect();
//}
for (avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.begin(); it != mAvatarNameCacheConnections.end(); ++it)
{
if (it->second.connected())
@ -240,7 +235,6 @@ public:
}
}
mAvatarNameCacheConnections.clear();
// </FS:Ansariel>
}
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getIcon(const std::string &url);
@ -253,10 +247,10 @@ protected:
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//boost::signals2::connection mAvatarNameCacheConnection;
//typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
typedef std::multimap<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
// </FS:Ansariel>
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};
///
@ -270,11 +264,6 @@ public:
LLUrlEntryAgentName();
~LLUrlEntryAgentName()
{
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//if (mAvatarNameCacheConnection.connected())
//{
// mAvatarNameCacheConnection.disconnect();
//}
for (avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.begin(); it != mAvatarNameCacheConnections.end(); ++it)
{
if (it->second.connected())
@ -283,7 +272,6 @@ public:
}
}
mAvatarNameCacheConnections.clear();
// </FS:Ansariel>
}
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ LLStyle::Params getStyle() const;
@ -293,10 +281,10 @@ protected:
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
// <FS:Ansariel> FIRE-11330: Names in chat get stuck as "Loading..."
//boost::signals2::connection mAvatarNameCacheConnection;
//typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
typedef std::multimap<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
// </FS:Ansariel>
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};

View File

@ -1458,7 +1458,9 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft;
S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom;
viewp->translate( delta_x, delta_y );
if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight())
if (child_rect.getWidth() != viewp->getRect().getWidth()
|| child_rect.getHeight() != viewp->getRect().getHeight()
|| sForceReshape)
{
viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
}

View File

@ -272,6 +272,18 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
#endif
}
// static
std::vector<std::string> LLWindow::getDisplaysResolutionList()
{
#if LL_WINDOWS
return LLWindowWin32::getDisplaysResolutionList();
#elif LL_DARWIN
return LLWindowMacOSX::getDisplaysResolutionList();
#else
return std::vector<std::string>();
#endif
}
#define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400)
#define UTF16_IS_LOW_SURROGATE(U) ((U16)((U) - 0xDC00) < 0x0400)
#define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000)

View File

@ -176,6 +176,8 @@ public:
// </FS:TT>
static std::vector<std::string> getDisplaysResolutionList();
// windows only DirectInput8 for joysticks
virtual void* getDirectInput8() { return NULL; };
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };

View File

@ -41,6 +41,7 @@
#include <OpenGL/OpenGL.h>
#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
#include <CoreGraphics/CGDisplayConfiguration.h>
extern BOOL gDebugWindowProc;
BOOL gHiDPISupport = TRUE;
@ -1964,6 +1965,35 @@ void LLWindowMacOSX::interruptLanguageTextInput()
commitCurrentPreedit(mGLView);
}
std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList()
{
std::vector<std::string> resolution_list;
CGDirectDisplayID display_ids[10];
uint32_t found_displays = 0;
CGError err = CGGetActiveDisplayList(10, display_ids, &found_displays);
if (kCGErrorSuccess != err)
{
LL_WARNS() << "Couldn't get a list of active displays" << LL_ENDL;
return std::vector<std::string>();
}
for (uint32_t i = 0; i < found_displays; i++)
{
S32 monitor_width = CGDisplayPixelsWide(display_ids[i]);
S32 monitor_height = CGDisplayPixelsHigh(display_ids[i]);
std::ostringstream sstream;
sstream << monitor_width << "x" << monitor_height;;
std::string res = sstream.str();
resolution_list.push_back(res);
}
return resolution_list;
}
//static
std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
{

View File

@ -116,6 +116,8 @@ public:
/*virtual*/ void openFile(const std::string& file_name);
/*virtual*/ void setTitle(const std::string& title);
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data

View File

@ -38,6 +38,7 @@
// Linden library includes
#include "llerror.h"
#include "llexception.h"
#include "llfasttimer.h"
#include "llgl.h"
#include "llstring.h"
@ -121,7 +122,7 @@ void show_window_creation_error(const std::string& title)
LL_WARNS("Window") << title << LL_ENDL;
}
HGLRC SafeCreateContext(HDC hdc)
HGLRC SafeCreateContext(HDC &hdc)
{
__try
{
@ -133,6 +134,22 @@ HGLRC SafeCreateContext(HDC hdc)
}
}
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
{
__try
{
return ChoosePixelFormat(hdc, ppfd);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// convert to C++ styled exception
// C exception don't allow classes, so it's a regular char array
char integer_string[32];
sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
throw std::exception(integer_string);
}
}
//static
BOOL LLWindowWin32::sIsClassRegistered = FALSE;
@ -404,6 +421,39 @@ LLWinImm::~LLWinImm()
}
class LLMonitorInfo
{
public:
std::vector<std::string> getResolutionsList() { return mResList; }
LLMonitorInfo()
{
EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
}
private:
static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
{
int monitor_width = lprcMonitor->right - lprcMonitor->left;
int monitor_height = lprcMonitor->bottom - lprcMonitor->top;
std::ostringstream sstream;
sstream << monitor_width << "x" << monitor_height;;
std::string res = sstream.str();
LLMonitorInfo* pThis = reinterpret_cast<LLMonitorInfo*>(pData);
pThis->mResList.push_back(res);
return TRUE;
}
std::vector<std::string> mResList;
};
static LLMonitorInfo sMonitorInfo;
LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
@ -1254,7 +1304,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
try
{
// Looks like ChoosePixelFormat can crash in case of faulty driver
if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
if (!(pixel_format = SafeChoosePixelFormat(mhDC, &pfd)))
{
LL_WARNS("Window") << "ChoosePixelFormat failed, code: " << GetLastError() << LL_ENDL;
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
@ -1265,7 +1315,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
}
catch (...)
{
LL_WARNS("Window") << "ChoosePixelFormat failed." << LL_ENDL;
LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
close();
@ -4410,6 +4460,12 @@ F32 LLWindowWin32::getSystemUISize()
return scale_value;
}
//static
std::vector<std::string> LLWindowWin32::getDisplaysResolutionList()
{
return sMonitorInfo.getResolutionsList();
}
//static
std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
{

View File

@ -119,6 +119,7 @@ public:
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();

View File

@ -344,6 +344,7 @@ set(viewer_SOURCE_FILES
llfloaterdeleteprefpreset.cpp
llfloaterdestinations.cpp
llfloaterdisplayname.cpp
llfloatereditenvironmentbase.cpp
llfloatereditextdaycycle.cpp
llfloaterenvironmentadjust.cpp
llfloaterevent.cpp
@ -1115,6 +1116,7 @@ set(viewer_HEADER_FILES
llfloaterdeleteprefpreset.h
llfloaterdestinations.h
llfloaterdisplayname.h
llfloatereditenvironmentbase.h
llfloatereditextdaycycle.h
llfloaterenvironmentadjust.h
llfloaterevent.h
@ -2256,6 +2258,8 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll
${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll
${SHARED_LIB_STAGING_DIR}/Release/uriparser.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/uriparser.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/SLVoice.exe
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libsndfile-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxoal.dll

View File

@ -1 +1 @@
6.4.18
6.4.19

View File

@ -8326,7 +8326,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://map.secondlife.com.s3.amazonaws.com/</string>
<string>https://map.secondlife.com/</string>
</map>
<key>CurrentMapServerURL</key>
<map>
@ -18845,7 +18845,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<real>1</real>
</map>
<key>PoolSizeVAssetStorage</key>
<key>PoolSizeAssetStorage</key>
<map>
<key>Comment</key>
<string>Coroutine Pool size for AssetStorage requests</string>

View File

@ -487,6 +487,16 @@ void FSPanelLogin::show(const LLRect &rect,
gFocusMgr.setDefaultKeyboardFocus(sInstance);
}
//static
void FSPanelLogin::reshapePanel()
{
if (sInstance)
{
LLRect rect = sInstance->getRect();
sInstance->reshape(rect.getWidth(), rect.getHeight());
}
}
// static
void FSPanelLogin::setFields(LLPointer<LLCredential> credential, bool from_startup /* = false*/)
{

View File

@ -53,6 +53,7 @@ public:
static void show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data);
static void reshapePanel();
static void setFields(LLPointer<LLCredential> credential, bool from_startup = false);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 128 KiB

View File

@ -134,6 +134,7 @@
// called again. Since it returned false, do not yet cancel
// frameTimer.
handleQuit();
[[NSApplication sharedApplication] stopModal];
return NSTerminateCancel;
} else {
// pumpMainLoop() returned true: it's done. Okay, done with frameTimer.

View File

@ -1406,7 +1406,16 @@ bool LLAppViewer::init()
// // add LEAP mode command-line argument to whichever of these we selected
// updater.args.add("leap");
// // UpdaterServiceSettings
// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
// {
// // Befor first login, treat this as 'manual' updates,
// // updater won't install anything, but required updates
// updater.args.add("0");
// }
// else
// {
// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// }
// // channel
// updater.args.add(LLVersionInfo::instance().getChannel());
// // testok
@ -1947,6 +1956,7 @@ bool LLAppViewer::doFrame()
}
delete gServicePump;
gServicePump = NULL;
destroyMainloopTimeout();
@ -2009,7 +2019,11 @@ bool LLAppViewer::cleanup()
//dump scene loading monitor results
if (LLSceneMonitor::instanceExists())
{
LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"));
if (!isSecondInstance())
{
LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"));
}
LLSceneMonitor::deleteSingleton();
}
// There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block
@ -4259,6 +4273,12 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList();
for (auto res_iter : resolutions)
{
gDebugInfo["DisplayInfo"].append(res_iter);
}
writeDebugInfo(); // Save out debug_info.log early, in case of crash.
}

View File

@ -313,7 +313,7 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
{
if (isAgentAvatarValid() &&
gAgentAvatarp->isWearingAttachment(*it) &&
!gAgentAvatarp->getWornAttachment(*it)->isTempAttachment() && // <FS:Ansariel> Don't link temp attachments in COF!
!gAgentAvatarp->getWornAttachment(*it)->isTempAttachment() && // Don't link temp attachments in COF!
!LLAppearanceMgr::instance().isLinkedInCOF(*it))
{
LLUUID item_id = *it;

View File

@ -408,6 +408,24 @@ void LLConversationLog::deleteBackupLogs()
}
}
void LLConversationLog::verifyFilename(const LLUUID& session_id, const std::string &expected_filename, const std::string &new_session_name)
{
conversations_vec_t::iterator conv_it = mConversations.begin();
for (; conv_it != mConversations.end(); ++conv_it)
{
if (conv_it->getSessionID() == session_id)
{
if (conv_it->getHistoryFileName() != expected_filename)
{
LLLogChat::renameLogFile(conv_it->getHistoryFileName(), expected_filename);
conv_it->updateHistoryFileName(expected_filename);
conv_it->setConversationName(new_session_name);
}
break;
}
}
}
bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory)
{
@ -543,11 +561,10 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
return false;
}
bool purge_required = false;
// <FS:Beq> FIRE-30705 protect against silly display names that cause lines to exceed max string length
// char buffer[MAX_STRING];
static constexpr int BUFFER_1K { 1024 }; // long enough to handle the most extreme Unicode nonsense and some to spare
char buffer[BUFFER_1K];
// </FS:Beq>
static constexpr int UTF_BUFFER{ 1024 }; // long enough to handle the most extreme Unicode nonsense and some to spare
char buffer[UTF_BUFFER];
char conv_name_buffer[MAX_STRING];
char part_id_buffer[MAX_STRING];
char conv_id_buffer[MAX_STRING];
@ -558,21 +575,15 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
// before CHUI-348 it was a flag of conversation voice state
int prereserved_unused;
// <FS:Beq/> FIRE-30705 protect against silly display names that cause lines to exceed max string length
// while (!feof(fp) && fgets(buffer, MAX_STRING, fp))
// {
// conv_name_buffer[0] = '\0';
// part_id_buffer[0] = '\0';
// conv_id_buffer[0] = '\0';
memset( buffer, '\0', BUFFER_1K );
while (!feof(fp) && fgets(buffer, BUFFER_1K, fp))
memset(buffer, '\0', UTF_BUFFER);
while (!feof(fp) && fgets(buffer, UTF_BUFFER, fp))
{
// force blank for added safety
memset( conv_name_buffer, '\0', MAX_STRING );
memset( part_id_buffer, '\0', MAX_STRING );
memset( conv_id_buffer, '\0', MAX_STRING );
memset( history_file_name, '\0', MAX_STRING );
// </FS:Beq>
// force blank for added safety
memset(conv_name_buffer, '\0', MAX_STRING);
memset(part_id_buffer, '\0', MAX_STRING);
memset(conv_id_buffer, '\0', MAX_STRING);
memset(history_file_name, '\0', MAX_STRING);
sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|",
&time,
&stype,
@ -610,7 +621,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
}
mConversations.push_back(conversation);
memset( buffer, '\0', BUFFER_1K ); // <FS:Beq> FIRE-30705 clear buffer down
memset(buffer, '\0', UTF_BUFFER);
}
fclose(fp);

View File

@ -59,7 +59,7 @@ public:
getTime() const { return mTime; }
bool hasOfflineMessages() const { return mHasOfflineIMs; }
void setConversationName(std::string conv_name) { mConversationName = conv_name; }
void setConversationName(const std::string &conv_name) { mConversationName = conv_name; }
void setOfflineMessages(bool new_messages) { mHasOfflineIMs = new_messages; }
bool isOlderThan(U32Days days) const;
@ -68,6 +68,8 @@ public:
*/
void updateTimestamp();
void updateHistoryFileName(const std::string &new_name) { mHistoryFileName = new_name; }
/*
* Resets flag of unread offline message to false when im floater with this conversation is opened.
*/
@ -137,6 +139,8 @@ public:
* public method which is called on viewer exit to save conversation log
*/
void cache();
// will check if current name is edentical with the one on disk and will rename the one on disk if it isn't
void verifyFilename(const LLUUID& session_id, const std::string &expected_filename, const std::string &new_session_name);
bool moveLog(const std::string &originDirectory, const std::string &targetDirectory);
void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs);
void deleteBackupLogs();

View File

@ -343,11 +343,36 @@ void LLConversationItemSession::removeParticipant(const LLUUID& participant_id)
void LLConversationItemSession::clearParticipants()
{
// clearParticipants function potentially is malfunctioning since it only cleans children of models,
// it does nothing to views that own those models (listeners)
// probably needs to post some kind of 'remove all participants' event
clearChildren();
mIsLoaded = false;
mNeedsRefresh = true;
}
void LLConversationItemSession::clearAndDeparentModels()
{
std::for_each(mChildren.begin(), mChildren.end(),
[](LLFolderViewModelItem* c)
{
if (c->getNumRefs() == 0)
{
// LLConversationItemParticipant can be created but not assigned to any view,
// it was waiting for an "add_participant" event to be processed
delete c;
}
else
{
// Model is still assigned to some view/widget
c->setParent(NULL);
}
}
);
mChildren.clear();
}
LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id)
{
// This is *not* a general tree parsing algorithm. It assumes that a session contains only

View File

@ -168,6 +168,7 @@ public:
void removeParticipant(LLConversationItemParticipant* participant);
void removeParticipant(const LLUUID& participant_id);
void clearParticipants();
void clearAndDeparentModels(); // will delete unowned models and deparent owned ones
LLConversationItemParticipant* findParticipant(const LLUUID& participant_id);
void setParticipantIsMuted(const LLUUID& participant_id, bool is_muted);

View File

@ -33,6 +33,7 @@
#include <boost/bind.hpp>
#include "llagentdata.h"
#include "llavataractions.h"
#include "llconversationmodel.h"
#include "llfloaterimsession.h"
#include "llfloaterimnearbychat.h"
@ -104,6 +105,56 @@ LLConversationViewSession::~LLConversationViewSession()
mFlashTimer->unset();
}
void LLConversationViewSession::destroyView()
{
// Chat can create and parent models(listeners) to session's model before creating
// coresponding views, such participant's models normally will wait for idle cycles
// but since we are deleting session and won't be processing any more events, make
// sure unowned LLConversationItemParticipant models are removed as well.
LLConversationItemSession* vmi = dynamic_cast<LLConversationItemSession*>(getViewModelItem());
// CONV_SESSION_1_ON_1 stores participants as two models that belong to views independent
// from session (nasty! These views are widgets in LLFloaterIMSessionTab, see buildConversationViewParticipant)
if (vmi && vmi->getType() != LLConversationItem::CONV_SESSION_1_ON_1)
{
// Destroy existing views
while (!mItems.empty())
{
LLFolderViewItem *itemp = mItems.back();
mItems.pop_back();
LLFolderViewModelItem* item_vmi = itemp->getViewModelItem();
if (item_vmi) // supposed to exist
{
// unparent to remove from child list
vmi->removeChild(item_vmi);
}
itemp->destroyView();
}
// Not needed in scope of sessions, but just in case
while (!mFolders.empty())
{
LLFolderViewFolder *folderp = mFolders.back();
mFolders.pop_back();
LLFolderViewModelItem* folder_vmi = folderp->getViewModelItem();
if (folder_vmi)
{
vmi->removeChild(folder_vmi);
}
folderp->destroyView();
}
// Now everything that is left in model(listener) is not owned by views,
// only by sessions, deparent so it won't point to soon to be dead model
vmi->clearAndDeparentModels();
}
LLFolderViewFolder::destroyView();
}
void LLConversationViewSession::setFlashState(bool flash_state)
{
if (flash_state && !mFlashStateOn)
@ -434,8 +485,13 @@ void LLConversationViewSession::refresh()
vmi->resetRefresh();
if (mSessionTitle)
{
mSessionTitle->setText(vmi->getDisplayName());
{
if (!highlightFriendTitle(vmi))
{
LLStyle::Params title_style;
title_style.color = LLUIColorTable::instance().getColor("LabelTextColor");
mSessionTitle->setText(vmi->getDisplayName(), title_style);
}
}
// Update all speaking indicators
@ -480,6 +536,22 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi
}
}
bool LLConversationViewSession::highlightFriendTitle(LLConversationItem* vmi)
{
if(vmi->getType() == LLConversationItem::CONV_PARTICIPANT || vmi->getType() == LLConversationItem::CONV_SESSION_1_ON_1)
{
LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID());
if (session && LLAvatarActions::isFriend(session->mOtherParticipantID))
{
LLStyle::Params title_style;
title_style.color = LLUIColorTable::instance().getColor("ConversationFriendColor");
mSessionTitle->setText(vmi->getDisplayName(), title_style);
return true;
}
}
return false;
}
//
// Implementation of conversations list participant (avatar) widgets
//
@ -580,7 +652,14 @@ void LLConversationViewParticipant::draw()
}
else
{
color = mIsSelected ? sHighlightFgColor : sFgColor;
if (LLAvatarActions::isFriend(mUUID))
{
color = LLUIColorTable::instance().getColor("ConversationFriendColor");
}
else
{
color = mIsSelected ? sHighlightFgColor : sFgColor;
}
}
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());

View File

@ -38,6 +38,7 @@
class LLTextBox;
class LLFloater;
class LLFloaterIMContainer;
class LLConversationItem;
class LLConversationViewSession;
class LLConversationViewParticipant;
@ -68,6 +69,8 @@ protected:
public:
virtual ~LLConversationViewSession();
/*virtual*/ void destroyView();
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
@ -95,6 +98,8 @@ public:
LLFloater* getSessionFloater();
bool isInActiveVoiceChannel() { return mIsInActiveVoiceChannel; }
bool highlightFriendTitle(LLConversationItem* vmi);
private:
void onCurrentVoiceSessionChanged(const LLUUID& session_id);

View File

@ -2317,7 +2317,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (mat)
{
switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaModeRender()))
{
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
{
@ -2460,7 +2460,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env);
if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
if (mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
sVertexProgram->setMinimumAlpha(cutoff);

View File

@ -1144,6 +1144,13 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
F32 map_rot = 0.f, map_scaleS = 0.f, map_scaleT = 0.f, map_offsS = 0.f, map_offsT = 0.f;
LLMaterial* mat = orig_tep->getMaterialParams();
if (!mat && map != LLRender::DIFFUSE_MAP)
{
LL_WARNS_ONCE("llface") << "Face is set to use specular or normal map but has no material, defaulting to diffuse" << LL_ENDL;
map = LLRender::DIFFUSE_MAP;
}
switch (map)
{
case LLRender::DIFFUSE_MAP:
@ -1154,26 +1161,26 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs
map_offsT = orig_tep->mOffsetT;
break;
case LLRender::NORMAL_MAP:
if (orig_tep->getMaterialParams()->getNormalID().isNull())
if (mat->getNormalID().isNull())
{
return false;
}
map_rot = orig_tep->getMaterialParams()->getNormalRotation();
map_scaleS = orig_tep->getMaterialParams()->getNormalRepeatX();
map_scaleT = orig_tep->getMaterialParams()->getNormalRepeatY();
map_offsS = orig_tep->getMaterialParams()->getNormalOffsetX();
map_offsT = orig_tep->getMaterialParams()->getNormalOffsetY();
map_rot = mat->getNormalRotation();
map_scaleS = mat->getNormalRepeatX();
map_scaleT = mat->getNormalRepeatY();
map_offsS = mat->getNormalOffsetX();
map_offsT = mat->getNormalOffsetY();
break;
case LLRender::SPECULAR_MAP:
if (orig_tep->getMaterialParams()->getSpecularID().isNull())
if (mat->getSpecularID().isNull())
{
return false;
}
map_rot = orig_tep->getMaterialParams()->getSpecularRotation();
map_scaleS = orig_tep->getMaterialParams()->getSpecularRepeatX();
map_scaleT = orig_tep->getMaterialParams()->getSpecularRepeatY();
map_offsS = orig_tep->getMaterialParams()->getSpecularOffsetX();
map_offsT = orig_tep->getMaterialParams()->getSpecularOffsetY();
map_rot = mat->getSpecularRotation();
map_scaleS = mat->getSpecularRepeatX();
map_scaleT = mat->getSpecularRepeatY();
map_offsS = mat->getSpecularOffsetX();
map_offsT = mat->getSpecularOffsetY();
break;
default: /*make compiler happy*/
break;
@ -1235,7 +1242,7 @@ bool LLFace::canRenderAsMask()
}
LLMaterial* mat = te->getMaterialParams();
if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
if (mat && mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
{
return false;
}
@ -1508,7 +1515,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
else
{
if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
if (!mat || mat->getDiffuseAlphaModeRender() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
shiny_in_alpha = true;
}

View File

@ -513,6 +513,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mUpdateDropDownItems(true),
mRestoreOverflowMenu(false),
mGetPrevItems(true),
mMouseX(0),
mMouseY(0),
mItemsChangedTimer()
{
// Register callback for menus with current registrar (will be parent panel's registrar)
@ -529,12 +531,12 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
// <FS:Ansariel> Allow V3 and FS style favorites bar
//LLTextBox::Params more_button_params(p.more_button);
//mMoreTextBox = LLUICtrlFactory::create<LLTextBox> (more_button_params);
//mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
//mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::onMoreTextBoxClicked, this));
//addChild(mMoreTextBox);
if (p.chevron_button.isProvided())
{
LLButton::Params chevron_button_params(p.chevron_button);
chevron_button_params.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
LLButton::Params chevron_button_params(p.chevron_button);
chevron_button_params.click_callback.function(boost::bind(&LLFavoritesBarCtrl::onMoreTextBoxClicked, this));
mMoreCtrl = LLUICtrlFactory::create<LLButton> (chevron_button_params);
addChild(mMoreCtrl);
}
@ -542,7 +544,7 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
{
LLTextBox::Params more_button_params(p.more_button);
mMoreCtrl = LLUICtrlFactory::create<LLTextBox> (more_button_params);
((LLTextBox*)mMoreCtrl)->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
((LLTextBox*)mMoreCtrl)->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::onMoreTextBoxClicked, this));
addChild(mMoreCtrl);
}
// </FS:Ansariel>
@ -1141,6 +1143,12 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it
return TRUE;
}
void LLFavoritesBarCtrl::onMoreTextBoxClicked()
{
LLUI::getInstance()->getMousePositionScreen(&mMouseX, &mMouseY);
showDropDownMenu();
}
void LLFavoritesBarCtrl::showDropDownMenu()
{
if (mOverflowMenuHandle.isDead())
@ -1299,7 +1307,7 @@ void LLFavoritesBarCtrl::positionAndShowMenu(LLToggleableMenu* menu)
}
}
LLMenuGL::showPopup(this, menu, menu_x, menu_y);
LLMenuGL::showPopup(this, menu, menu_x, menu_y, mMouseX, mMouseY);
}
void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id)

View File

@ -99,6 +99,8 @@ protected:
void showDropDownMenu();
void onMoreTextBoxClicked();
LLHandle<LLView> mOverflowMenuHandle;
LLHandle<LLView> mContextMenuHandle;
@ -170,6 +172,9 @@ private:
BOOL mTabsHighlightEnabled;
S32 mMouseX;
S32 mMouseY;
boost::signals2::connection mEndDragConnection;
};

View File

@ -384,22 +384,6 @@ F32 gpu_benchmark();
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 exception_benchmark_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
// handle it
return EXCEPTION_EXECUTE_HANDLER;
}
}
F32 logExceptionBenchmark()
{
// Todo: make a wrapper/class for SEH exceptions
@ -408,7 +392,7 @@ F32 logExceptionBenchmark()
{
gbps = gpu_benchmark();
}
__except (exception_benchmark_filter(GetExceptionCode(), GetExceptionInformation()))
__except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
// convert to C++ styled exception
char integer_string[32];

View File

@ -49,7 +49,8 @@
#include "lltrans.h"
LLFloaterBuy::LLFloaterBuy(const LLSD& key)
: LLFloater(key)
: LLFloater(key),
mSelectionUpdateSlot()
{
}
@ -182,12 +183,19 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
floater->getChild<LLUICtrl>("buy_text")->setTextArg("[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
floater->getChild<LLUICtrl>("buy_name_text")->setTextArg("[NAME]", owner_name);
floater->showViews(true);
// Must do this after the floater is created, because
// sometimes the inventory is already there and
// the callback is called immediately.
LLViewerObject* obj = selection->getFirstRootObject();
floater->registerVOInventoryListener(obj,NULL);
floater->requestVOInventory();
if (!floater->mSelectionUpdateSlot.connected())
{
floater->mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterBuy::onSelectionChanged, floater));
}
}
void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
@ -283,6 +291,33 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
removeVOInventoryListener();
}
void LLFloaterBuy::onSelectionChanged()
{
if (LLSelectMgr::getInstance()->getEditSelection()->getRootObjectCount() == 0)
{
removeVOInventoryListener();
closeFloater();
}
else if (LLSelectMgr::getInstance()->getEditSelection()->getRootObjectCount() > 1)
{
removeVOInventoryListener();
showViews(false);
reset();
// <FS:PP>
// setTitle(getString("mupliple_selected"));
setTitle(getString("multiple_selected"));
// </FS:PP>
}
}
void LLFloaterBuy::showViews(bool show)
{
getChild<LLUICtrl>("buy_btn")->setEnabled(show);
getChild<LLUICtrl>("buy_text")->setVisible(show);
getChild<LLUICtrl>("buy_name_text")->setVisible(show);
}
void LLFloaterBuy::onClickBuy()
{
// Put the items where we put new folders.
@ -306,5 +341,10 @@ void LLFloaterBuy::onClickCancel()
// virtual
void LLFloaterBuy::onClose(bool app_quitting)
{
if (mSelectionUpdateSlot.connected())
{
mSelectionUpdateSlot.disconnect();
}
mObjectSelection.clear();
}

View File

@ -63,12 +63,17 @@ protected:
S32 serial_num,
void* data);
void onSelectionChanged();
void showViews(bool show);
void onClickBuy();
void onClickCancel();
private:
LLSafeHandle<LLObjectSelection> mObjectSelection;
LLSaleInfo mSaleInfo;
boost::signals2::connection mSelectionUpdateSlot;
};
#endif

View File

@ -565,6 +565,7 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode)
switch (mode)
{
case CAMERA_CTRL_MODE_PRESETS:
case CAMERA_CTRL_MODE_PAN:
sFreeCamera = false;
clear_camera_tool();
@ -575,13 +576,6 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode)
activate_camera_tool();
break;
case CAMERA_CTRL_MODE_PRESETS:
if(sFreeCamera)
{
switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
}
break;
default:
//normally we won't occur here
llassert_always(FALSE);
@ -639,7 +633,6 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA ? camera_floater->switchMode(CAMERA_CTRL_MODE_PAN) : camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
// </FS:Ansariel>
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
}
// <FS:Ansariel> Phototools camera
@ -651,7 +644,6 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA ? camera_floater->switchMode(CAMERA_CTRL_MODE_PAN) : camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
// </FS:Ansariel>
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
@ -664,7 +656,6 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA ? camera_floater->switchMode(CAMERA_CTRL_MODE_PAN) : camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
// </FS:Ansariel>
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
}
@ -766,7 +757,7 @@ void LLFloaterCamera::switchToPreset(const std::string& name)
if (camera_floater)
{
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
camera_floater->switchMode(CAMERA_CTRL_MODE_PRESETS);
}
// <FS:Ansariel> Phototools camera
@ -774,7 +765,7 @@ void LLFloaterCamera::switchToPreset(const std::string& name)
if (camera_floater)
{
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
camera_floater->switchMode(CAMERA_CTRL_MODE_PRESETS);
}
// </FS:Ansariel>
@ -783,19 +774,11 @@ void LLFloaterCamera::switchToPreset(const std::string& name)
if (camera_floater)
{
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
camera_floater->switchMode(CAMERA_CTRL_MODE_PRESETS);
}
// </FS:Ansariel>
}
void LLFloaterCamera::fromFreeToPresets()
{
if (!sFreeCamera && mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA && mPrevMode == CAMERA_CTRL_MODE_PRESETS)
{
switchMode(CAMERA_CTRL_MODE_PRESETS);
}
}
void LLFloaterCamera::populatePresetCombo()
{
LLPresetsManager::getInstance()->setPresetNamesInComboBox(PRESETS_CAMERA, mPresetCombo, EDefaultOptions::DEFAULT_HIDE);

View File

@ -70,10 +70,6 @@ public:
/*switch to one of the camera presets (front, rear, side)*/
static void switchToPreset(const std::string& name);
/* move to CAMERA_CTRL_MODE_PRESETS from CAMERA_CTRL_MODE_FREE_CAMERA if we are on presets panel and
are not in free camera mode*/
void fromFreeToPresets();
virtual void onOpen(const LLSD& key);
virtual void onClose(bool app_quitting);

View File

@ -0,0 +1,479 @@
/**
* @file llfloatereditenvironmentbase.cpp
* @brief Floaters to create and edit fixed settings for sky and water.
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloatereditenvironmentbase.h"
#include <boost/make_shared.hpp>
// libs
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llfilepicker.h"
#include "llsettingspicker.h"
#include "llviewerparcelmgr.h"
// newview
#include "llsettingssky.h"
#include "llsettingswater.h"
#include "llenvironment.h"
#include "llagent.h"
#include "llparcel.h"
#include "llsettingsvo.h"
#include "llinventorymodel.h"
namespace
{
const std::string ACTION_APPLY_LOCAL("apply_local");
const std::string ACTION_APPLY_PARCEL("apply_parcel");
const std::string ACTION_APPLY_REGION("apply_region");
}
//=========================================================================
const std::string LLFloaterEditEnvironmentBase::KEY_INVENTORY_ID("inventory_id");
//=========================================================================
class LLFixedSettingCopiedCallback : public LLInventoryCallback
{
public:
LLFixedSettingCopiedCallback(LLHandle<LLFloater> handle) : mHandle(handle) {}
virtual void fire(const LLUUID& inv_item_id)
{
if (!mHandle.isDead())
{
LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
if (item)
{
LLFloaterEditEnvironmentBase* floater = (LLFloaterEditEnvironmentBase*)mHandle.get();
floater->onInventoryCreated(item->getAssetUUID(), inv_item_id);
}
}
}
private:
LLHandle<LLFloater> mHandle;
};
//=========================================================================
LLFloaterEditEnvironmentBase::LLFloaterEditEnvironmentBase(const LLSD &key) :
LLFloater(key),
mInventoryId(),
mInventoryItem(nullptr),
mIsDirty(false),
mCanCopy(false),
mCanMod(false),
mCanTrans(false),
mCanSave(false)
{
}
LLFloaterEditEnvironmentBase::~LLFloaterEditEnvironmentBase()
{
}
void LLFloaterEditEnvironmentBase::onFocusReceived()
{
if (isInVisibleChain())
{
updateEditEnvironment();
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
}
}
void LLFloaterEditEnvironmentBase::onFocusLost()
{
}
void LLFloaterEditEnvironmentBase::loadInventoryItem(const LLUUID &inventoryId, bool can_trans)
{
if (inventoryId.isNull())
{
mInventoryItem = nullptr;
mInventoryId.setNull();
mCanMod = true;
mCanCopy = true;
mCanTrans = true;
return;
}
mInventoryId = inventoryId;
LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
mInventoryItem = gInventory.getItem(mInventoryId);
if (!mInventoryItem)
{
LL_WARNS("SETTINGS") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
LLNotificationsUtil::add("CantFindInvItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
if (mInventoryItem->getAssetUUID().isNull())
{
LL_WARNS("ENVIRONMENT") << "Asset ID in inventory item is NULL (" << mInventoryId << ")" << LL_ENDL;
LLNotificationsUtil::add("UnableEditItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
mCanSave = true;
mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
mCanTrans = can_trans && mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
mExpectingAssetId = mInventoryItem->getAssetUUID();
LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
[this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
}
void LLFloaterEditEnvironmentBase::checkAndConfirmSettingsLoss(LLFloaterEditEnvironmentBase::on_confirm_fn cb)
{
if (isDirty())
{
LLSD args(LLSDMap("TYPE", getEditSettings()->getSettingsType())
("NAME", getEditSettings()->getName()));
// create and show confirmation textbox
LLNotificationsUtil::add("SettingsConfirmLoss", args, LLSD(),
[cb](const LLSD&notif, const LLSD&resp)
{
S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
if (opt == 0)
cb();
});
}
else if (cb)
{
cb();
}
}
void LLFloaterEditEnvironmentBase::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
{
if (asset_id != mExpectingAssetId)
{
LL_WARNS("ENVDAYEDIT") << "Expecting {" << mExpectingAssetId << "} got {" << asset_id << "} - throwing away." << LL_ENDL;
return;
}
mExpectingAssetId.setNull();
clearDirtyFlag();
if (!settings || status)
{
LLSD args;
args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
closeFloater();
return;
}
if (settings->getFlag(LLSettingsBase::FLAG_NOSAVE))
{
mCanSave = false;
mCanCopy = false;
mCanMod = false;
mCanTrans = false;
}
else
{
if (mInventoryItem)
settings->setName(mInventoryItem->getName());
if (mCanCopy)
settings->clearFlag(LLSettingsBase::FLAG_NOCOPY);
else
settings->setFlag(LLSettingsBase::FLAG_NOCOPY);
if (mCanMod)
settings->clearFlag(LLSettingsBase::FLAG_NOMOD);
else
settings->setFlag(LLSettingsBase::FLAG_NOMOD);
if (mCanTrans)
settings->clearFlag(LLSettingsBase::FLAG_NOTRANS);
else
settings->setFlag(LLSettingsBase::FLAG_NOTRANS);
}
setEditSettingsAndUpdate(settings);
}
void LLFloaterEditEnvironmentBase::onButtonImport()
{
checkAndConfirmSettingsLoss([this](){ doImportFromDisk(); });
}
void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
std::string settings_name = response["message"].asString();
LLInventoryObject::correctInventoryName(settings_name);
if (settings_name.empty())
{
// Ideally notification should disable 'OK' button if name won't fit our requirements,
// for now either display notification, or use some default name
settings_name = "Unnamed";
}
if (mCanMod)
{
doApplyCreateNewInventory(settings_name, settings);
}
else if (mInventoryItem)
{
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
LLUUID parent_id = mInventoryItem->getParentUUID();
if ((marketplacelistings_id == parent_id) || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
{
parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
}
LLPointer<LLInventoryCallback> cb = new LLFixedSettingCopiedCallback(getHandle());
copy_inventory_item(
gAgent.getID(),
mInventoryItem->getPermissions().getOwner(),
mInventoryItem->getUUID(),
parent_id,
settings_name,
cb);
}
else
{
LL_WARNS() << "Failed to copy fixed env setting" << LL_ENDL;
}
}
}
void LLFloaterEditEnvironmentBase::onClickCloseBtn(bool app_quitting)
{
if (!app_quitting)
checkAndConfirmSettingsLoss([this](){ closeFloater(); clearDirtyFlag(); });
else
closeFloater();
}
void LLFloaterEditEnvironmentBase::doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings)
{
if (mInventoryItem)
{
LLUUID parent_id = mInventoryItem->getParentUUID();
U32 next_owner_perm = mInventoryItem->getPermissions().getMaskNextOwner();
LLSettingsVOBase::createInventoryItem(settings, next_owner_perm, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
else
{
LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
// This method knows what sort of settings object to create.
LLSettingsVOBase::createInventoryItem(settings, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
}
void LLFloaterEditEnvironmentBase::doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings)
{
LL_DEBUGS("ENVEDIT") << "Update inventory for " << mInventoryId << LL_ENDL;
if (mInventoryId.isNull())
{
LLSettingsVOBase::createInventoryItem(settings, gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS), std::string(),
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
else
{
LLSettingsVOBase::updateInventoryItem(settings, mInventoryId,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
}
}
void LLFloaterEditEnvironmentBase::doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings)
{
U32 flags(0);
if (mInventoryItem)
{
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOMOD;
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOTRANS;
}
flags |= settings->getFlags();
settings->setFlag(flags);
if (where == ACTION_APPLY_LOCAL)
{
settings->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, settings);
}
else if (where == ACTION_APPLY_PARCEL)
{
LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
{
LL_WARNS("ENVIRONMENT") << "Can not identify parcel. Not applying." << LL_ENDL;
LLNotificationsUtil::add("WLParcelApplyFail");
return;
}
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else if (settings->getSettingsType() == "sky")
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
}
else if (settings->getSettingsType() == "water")
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
}
else if (settings->getSettingsType() == "day")
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsDay>(settings), -1, -1);
}
}
else if (where == ACTION_APPLY_REGION)
{
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateRegion(mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else if (settings->getSettingsType() == "sky")
{
LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
}
else if (settings->getSettingsType() == "water")
{
LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
}
else if (settings->getSettingsType() == "day")
{
LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsDay>(settings), -1, -1);
}
}
else
{
LL_WARNS("ENVIRONMENT") << "Unknown apply '" << where << "'" << LL_ENDL;
return;
}
}
void LLFloaterEditEnvironmentBase::doCloseInventoryFloater(bool quitting)
{
LLFloater* floaterp = mInventoryFloater.get();
if (floaterp)
{
floaterp->closeFloater(quitting);
}
}
void LLFloaterEditEnvironmentBase::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
{
LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
if (inventory_id.isNull() || !results["success"].asBoolean())
{
LLNotificationsUtil::add("CantCreateInventory");
return;
}
onInventoryCreated(asset_id, inventory_id);
}
void LLFloaterEditEnvironmentBase::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id)
{
bool can_trans = true;
if (mInventoryItem)
{
LLPermissions perms = mInventoryItem->getPermissions();
LLInventoryItem *created_item = gInventory.getItem(mInventoryId);
if (created_item)
{
can_trans = perms.allowOperationBy(PERM_TRANSFER, gAgent.getID());
created_item->setPermissions(perms);
created_item->updateServer(false);
}
}
clearDirtyFlag();
setFocus(TRUE); // Call back the focus...
loadInventoryItem(inventory_id, can_trans);
}
void LLFloaterEditEnvironmentBase::onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
{
LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been updated with asset " << asset_id << " results are:" << results << LL_ENDL;
clearDirtyFlag();
if (inventory_id != mInventoryId)
{
loadInventoryItem(inventory_id);
}
}
void LLFloaterEditEnvironmentBase::onPanelDirtyFlagChanged(bool value)
{
if (value)
setDirtyFlag();
}
//-------------------------------------------------------------------------
bool LLFloaterEditEnvironmentBase::canUseInventory() const
{
return LLEnvironment::instance().isInventoryEnabled();
}
bool LLFloaterEditEnvironmentBase::canApplyRegion() const
{
return gAgent.canManageEstate();
}
bool LLFloaterEditEnvironmentBase::canApplyParcel() const
{
return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
}
//=========================================================================

View File

@ -0,0 +1,148 @@
/**
* @file llfloatereditenvironmentbase.h
* @brief Floaters to create and edit fixed settings for sky and water.
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_FLOATEREDITENVIRONMENTBASE_H
#define LL_FLOATEREDITENVIRONMENTBASE_H
#include "llfloater.h"
#include "llsettingsbase.h"
#include "llflyoutcombobtn.h"
#include "llinventory.h"
#include "boost/signals2.hpp"
class LLTabContainer;
class LLButton;
class LLLineEditor;
class LLFloaterSettingsPicker;
class LLFixedSettingCopiedCallback;
class LLFloaterEditEnvironmentBase : public LLFloater
{
LOG_CLASS(LLFloaterEditEnvironmentBase);
friend class LLFixedSettingCopiedCallback;
public:
static const std::string KEY_INVENTORY_ID;
LLFloaterEditEnvironmentBase(const LLSD &key);
~LLFloaterEditEnvironmentBase();
virtual void onFocusReceived() override;
virtual void onFocusLost() override;
virtual LLSettingsBase::ptr_t getEditSettings() const = 0;
virtual BOOL isDirty() const override { return getIsDirty(); }
protected:
typedef std::function<void()> on_confirm_fn;
virtual void setEditSettingsAndUpdate(const LLSettingsBase::ptr_t &settings) = 0;
virtual void updateEditEnvironment() = 0;
virtual LLFloaterSettingsPicker *getSettingsPicker() = 0;
void loadInventoryItem(const LLUUID &inventoryId, bool can_trans = true);
void checkAndConfirmSettingsLoss(on_confirm_fn cb);
virtual void doImportFromDisk() = 0;
virtual void doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings);
virtual void doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings);
virtual void doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings);
void doCloseInventoryFloater(bool quitting = false);
bool canUseInventory() const;
bool canApplyRegion() const;
bool canApplyParcel() const;
LLUUID mInventoryId;
LLInventoryItem * mInventoryItem;
LLHandle<LLFloater> mInventoryFloater;
bool mCanCopy;
bool mCanMod;
bool mCanTrans;
bool mCanSave;
bool mIsDirty;
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id);
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
void onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
bool getIsDirty() const { return mIsDirty; }
void setDirtyFlag() { mIsDirty = true; }
virtual void clearDirtyFlag() = 0;
void onPanelDirtyFlagChanged(bool);
virtual void onClickCloseBtn(bool app_quitting = false) override;
void onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings);
void onButtonImport();
void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status);
private:
LLUUID mExpectingAssetId; // for asset load confirmation
};
class LLSettingsEditPanel : public LLPanel
{
public:
virtual void setSettings(const LLSettingsBase::ptr_t &) = 0;
typedef boost::signals2::signal<void(LLPanel *, bool)> on_dirty_charged_sg;
typedef boost::signals2::connection connection_t;
inline bool getIsDirty() const { return mIsDirty; }
inline void setIsDirty() { mIsDirty = true; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
inline void clearIsDirty() { mIsDirty = false; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
inline bool getCanChangeSettings() const { return mCanEdit; }
inline void setCanChangeSettings(bool flag) { mCanEdit = flag; }
inline connection_t setOnDirtyFlagChanged(on_dirty_charged_sg::slot_type cb) { return mOnDirtyChanged.connect(cb); }
protected:
LLSettingsEditPanel() :
LLPanel(),
mIsDirty(false),
mOnDirtyChanged()
{}
private:
void onTextureChanged(LLUUID &inventory_item_id);
bool mIsDirty;
bool mCanEdit;
on_dirty_charged_sg mOnDirtyChanged;
};
#endif // LL_FLOATERENVIRONMENTBASE_H

View File

@ -125,7 +125,6 @@ namespace {
}
//=========================================================================
const std::string LLFloaterEditExtDayCycle::KEY_INVENTORY_ID("inventory_id");
const std::string LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT("edit_context");
const std::string LLFloaterEditExtDayCycle::KEY_DAY_LENGTH("day_length");
const std::string LLFloaterEditExtDayCycle::KEY_CANMOD("canmod");
@ -133,7 +132,7 @@ const std::string LLFloaterEditExtDayCycle::KEY_CANMOD("canmod");
const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_INVENTORY("inventory");
const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_PARCEL("parcel");
const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION("region");
/*
//=========================================================================
class LLDaySettingCopiedCallback : public LLInventoryCallback
@ -156,12 +155,12 @@ public:
private:
LLHandle<LLFloater> mHandle;
};
};*/
//=========================================================================
LLFloaterEditExtDayCycle::LLFloaterEditExtDayCycle(const LLSD &key) :
LLFloater(key),
LLFloaterEditEnvironmentBase(key),
mFlyoutControl(nullptr),
mDayLength(0),
mCurrentTrack(1),
@ -170,19 +169,12 @@ LLFloaterEditExtDayCycle::LLFloaterEditExtDayCycle(const LLSD &key) :
mFramesSlider(nullptr),
mCurrentTimeLabel(nullptr),
mImportButton(nullptr),
mInventoryId(),
mInventoryItem(nullptr),
mLoadFrame(nullptr),
mSkyBlender(),
mWaterBlender(),
mScratchSky(),
mScratchWater(),
mIsPlaying(false),
mIsDirty(false),
mCanSave(false),
mCanCopy(false),
mCanMod(false),
mCanTrans(false),
mCloneTrack(nullptr),
mLoadTrack(nullptr),
mClearTrack(nullptr)
@ -425,19 +417,6 @@ void LLFloaterEditExtDayCycle::onClose(bool app_quitting)
}
}
void LLFloaterEditExtDayCycle::onFocusReceived()
{
if (isInVisibleChain())
{
updateEditEnvironment();
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
}
}
void LLFloaterEditExtDayCycle::onFocusLost()
{
}
void LLFloaterEditExtDayCycle::onVisibilityChange(BOOL new_visibility)
{
@ -488,6 +467,10 @@ void LLFloaterEditExtDayCycle::refresh()
LLFloater::refresh();
}
void LLFloaterEditExtDayCycle::setEditSettingsAndUpdate(const LLSettingsBase::ptr_t &settings)
{
setEditDayCycle(std::dynamic_pointer_cast<LLSettingsDay>(settings));
}
void LLFloaterEditExtDayCycle::setEditDayCycle(const LLSettingsDay::ptr_t &pday)
{
@ -700,63 +683,6 @@ void LLFloaterEditExtDayCycle::onButtonApply(LLUICtrl *ctrl, const LLSD &data)
}
}
void LLFloaterEditExtDayCycle::onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsDay::ptr_t &day)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
std::string settings_name = response["message"].asString();
LLInventoryObject::correctInventoryName(settings_name);
if (settings_name.empty())
{
// Ideally notification should disable 'OK' button if name won't fit our requirements,
// for now either display notification, or use some default name
settings_name = "Unnamed";
}
if (mCanMod)
{
doApplyCreateNewInventory(day, settings_name);
}
else if (mInventoryItem)
{
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
LLUUID parent_id = mInventoryItem->getParentUUID();
if (marketplacelistings_id == parent_id)
{
parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
}
LLPointer<LLInventoryCallback> cb = new LLDaySettingCopiedCallback(getHandle());
copy_inventory_item(
gAgent.getID(),
mInventoryItem->getPermissions().getOwner(),
mInventoryItem->getUUID(),
parent_id,
settings_name,
cb);
}
else
{
LL_WARNS() << "Failed to copy day setting" << LL_ENDL;
}
}
}
void LLFloaterEditExtDayCycle::onClickCloseBtn(bool app_quitting /*= false*/)
{
if (!app_quitting)
checkAndConfirmSettingsLoss([this](){ closeFloater(); clearDirtyFlag(); });
else
closeFloater();
}
void LLFloaterEditExtDayCycle::onButtonImport()
{
checkAndConfirmSettingsLoss([this]() { doImportFromDisk(); });
}
void LLFloaterEditExtDayCycle::onButtonLoadFrame()
{
doOpenInventoryFloater((mCurrentTrack == LLSettingsDay::TRACK_WATER) ? LLSettingsType::ST_WATER : LLSettingsType::ST_SKY, LLUUID::null);
@ -1053,35 +979,6 @@ void LLFloaterEditExtDayCycle::onFrameSliderMouseUp(S32 x, S32 y, MASK mask)
selectFrame(sliderpos, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
}
void LLFloaterEditExtDayCycle::onPanelDirtyFlagChanged(bool value)
{
if (value)
setDirtyFlag();
}
void LLFloaterEditExtDayCycle::checkAndConfirmSettingsLoss(on_confirm_fn cb)
{
if (isDirty())
{
LLSD args(LLSDMap("TYPE", mEditDay->getSettingsType())
("NAME", mEditDay->getName()));
// create and show confirmation textbox
LLNotificationsUtil::add("SettingsConfirmLoss", args, LLSD(),
[cb](const LLSD&notif, const LLSD&resp)
{
S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
if (opt == 0)
cb();
});
}
else if (cb)
{
cb();
}
}
void LLFloaterEditExtDayCycle::onTimeSliderCallback()
{
stopPlay();
@ -1435,106 +1332,6 @@ LLFloaterEditExtDayCycle::connection_t LLFloaterEditExtDayCycle::setEditCommitSi
return mCommitSignal.connect(cb);
}
void LLFloaterEditExtDayCycle::loadInventoryItem(const LLUUID &inventoryId, bool can_trans)
{
if (inventoryId.isNull())
{
mInventoryItem = nullptr;
mInventoryId.setNull();
mCanSave = true;
mCanCopy = true;
mCanMod = true;
mCanTrans = true;
return;
}
mInventoryId = inventoryId;
LL_INFOS("ENVDAYEDIT") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
mInventoryItem = gInventory.getItem(mInventoryId);
if (!mInventoryItem)
{
LL_WARNS("ENVDAYEDIT") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
LLNotificationsUtil::add("CantFindInvItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
if (mInventoryItem->getAssetUUID().isNull())
{
LL_WARNS("ENVDAYEDIT") << "Asset ID in inventory item is NULL (" << mInventoryId << ")" << LL_ENDL;
LLNotificationsUtil::add("UnableEditItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
mCanSave = true;
mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
mCanTrans = can_trans && mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
mExpectingAssetId = mInventoryItem->getAssetUUID();
LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
[this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
}
void LLFloaterEditExtDayCycle::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
{
if (asset_id != mExpectingAssetId)
{
LL_WARNS("ENVDAYEDIT") << "Expecting {" << mExpectingAssetId << "} got {" << asset_id << "} - throwing away." << LL_ENDL;
return;
}
mExpectingAssetId.setNull();
clearDirtyFlag();
if (!settings || status)
{
LLSD args;
args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
closeFloater();
return;
}
if (settings->getFlag(LLSettingsBase::FLAG_NOSAVE))
{
mCanSave = false;
mCanCopy = false;
mCanMod = false;
mCanTrans = false;
}
else
{
if (mCanCopy)
settings->clearFlag(LLSettingsBase::FLAG_NOCOPY);
else
settings->setFlag(LLSettingsBase::FLAG_NOCOPY);
if (mCanMod)
settings->clearFlag(LLSettingsBase::FLAG_NOMOD);
else
settings->setFlag(LLSettingsBase::FLAG_NOMOD);
if (mCanTrans)
settings->clearFlag(LLSettingsBase::FLAG_NOTRANS);
else
settings->setFlag(LLSettingsBase::FLAG_NOTRANS);
if (mInventoryItem)
settings->setName(mInventoryItem->getName());
}
setEditDayCycle(std::dynamic_pointer_cast<LLSettingsDay>(settings));
}
void LLFloaterEditExtDayCycle::updateEditEnvironment(void)
{
if (!mEditDay)
@ -1670,93 +1467,6 @@ void LLFloaterEditExtDayCycle::reblendSettings()
mWaterBlender->setPosition(position);
}
void LLFloaterEditExtDayCycle::doApplyCreateNewInventory(const LLSettingsDay::ptr_t &day, std::string settings_name)
{
if (mInventoryItem)
{
LLUUID parent_id = mInventoryItem->getParentUUID();
U32 next_owner_perm = mInventoryItem->getPermissions().getMaskNextOwner();
LLSettingsVOBase::createInventoryItem(day, next_owner_perm, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
else
{
LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
// This method knows what sort of settings object to create.
LLSettingsVOBase::createInventoryItem(day, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
}
void LLFloaterEditExtDayCycle::doApplyUpdateInventory(const LLSettingsDay::ptr_t &day)
{
if (mInventoryId.isNull())
LLSettingsVOBase::createInventoryItem(day, gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS), std::string(),
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
else
LLSettingsVOBase::updateInventoryItem(day, mInventoryId,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
}
void LLFloaterEditExtDayCycle::doApplyEnvironment(const std::string &where, const LLSettingsDay::ptr_t &day)
{
U32 flags(0);
if (mInventoryItem)
{
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOMOD;
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOTRANS;
}
flags |= day->getFlags();
day->setFlag(flags);
if (where == ACTION_APPLY_LOCAL)
{
day->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, day);
}
else if (where == ACTION_APPLY_PARCEL)
{
LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
{
LL_WARNS("ENVDAYEDIT") << "Can not identify parcel. Not applying." << LL_ENDL;
LLNotificationsUtil::add("WLParcelApplyFail");
return;
}
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), day, -1, -1);
}
}
else if (where == ACTION_APPLY_REGION)
{
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateRegion(mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else
{
LLEnvironment::instance().updateRegion(day, -1, -1);
}
}
else
{
LL_WARNS("ENVDAYEDIT") << "Unknown apply '" << where << "'" << LL_ENDL;
return;
}
}
void LLFloaterEditExtDayCycle::doApplyCommit(LLSettingsDay::ptr_t day)
{
if (!mCommitSignal.empty())
@ -1793,51 +1503,6 @@ bool LLFloaterEditExtDayCycle::isAddingFrameAllowed()
return mFramesSlider->canAddSliders();
}
void LLFloaterEditExtDayCycle::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
{
LL_INFOS("ENVDAYEDIT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
if (inventory_id.isNull() || !results["success"].asBoolean())
{
LLNotificationsUtil::add("CantCreateInventory");
return;
}
onInventoryCreated(asset_id, inventory_id);
}
void LLFloaterEditExtDayCycle::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id)
{
bool can_trans = true;
if (mInventoryItem)
{
LLPermissions perms = mInventoryItem->getPermissions();
LLInventoryItem *created_item = gInventory.getItem(mInventoryId);
if (created_item)
{
can_trans = perms.allowOperationBy(PERM_TRANSFER, gAgent.getID());
created_item->setPermissions(perms);
created_item->updateServer(false);
}
}
clearDirtyFlag();
setFocus(TRUE); // Call back the focus...
loadInventoryItem(inventory_id, can_trans);
}
void LLFloaterEditExtDayCycle::onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
{
LL_WARNS("ENVDAYEDIT") << "Inventory item " << inventory_id << " has been updated with asset " << asset_id << " results are:" << results << LL_ENDL;
clearDirtyFlag();
if (inventory_id != mInventoryId)
{
loadInventoryItem(inventory_id);
}
}
void LLFloaterEditExtDayCycle::doImportFromDisk()
{ // Load a a legacy Windlight XML from disk.
(new LLFilePickerReplyThread(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
@ -1864,21 +1529,6 @@ void LLFloaterEditExtDayCycle::loadSettingFromFile(const std::vector<std::string
setEditDayCycle(legacyday);
}
bool LLFloaterEditExtDayCycle::canUseInventory() const
{
return LLEnvironment::instance().isInventoryEnabled();
}
bool LLFloaterEditExtDayCycle::canApplyRegion() const
{
return gAgent.canManageEstate();
}
bool LLFloaterEditExtDayCycle::canApplyParcel() const
{
return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
}
void LLFloaterEditExtDayCycle::startPlay()
{
doCloseInventoryFloater();
@ -1983,14 +1633,8 @@ void LLFloaterEditExtDayCycle::doCloseTrackFloater(bool quitting)
}
}
void LLFloaterEditExtDayCycle::onPickerCommitTrackId(U32 track_id)
LLFloaterSettingsPicker * LLFloaterEditExtDayCycle::getSettingsPicker()
{
cloneTrack(track_id, mCurrentTrack);
}
void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e type, LLUUID curritem)
{
// LLUI::sWindow->setCursor(UI_CURSOR_WAIT);
LLFloaterSettingsPicker *picker = static_cast<LLFloaterSettingsPicker *>(mInventoryFloater.get());
// Show the dialog
@ -2003,7 +1647,17 @@ void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e typ
picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitSetting(data["ItemId"].asUUID(), data["Track"].asInteger()); });
}
return picker;
}
void LLFloaterEditExtDayCycle::onPickerCommitTrackId(U32 track_id)
{
cloneTrack(track_id, mCurrentTrack);
}
void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e type, LLUUID curritem)
{
LLFloaterSettingsPicker *picker = getSettingsPicker();
picker->setSettingsFilter(type);
picker->setSettingsItemId(curritem);
if (type == LLSettingsType::ST_DAYCYCLE)
@ -2018,16 +1672,6 @@ void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e typ
picker->setFocus(TRUE);
}
void LLFloaterEditExtDayCycle::doCloseInventoryFloater(bool quitting)
{
LLFloater* floaterp = mInventoryFloater.get();
if (floaterp)
{
floaterp->closeFloater(quitting);
}
}
void LLFloaterEditExtDayCycle::onPickerCommitSetting(LLUUID item_id, S32 track)
{
LLSettingsBase::TrackPosition frame(mTimeSlider->getCurSliderValue());
@ -2118,7 +1762,9 @@ void LLFloaterEditExtDayCycle::onAssetLoadedForInsertion(LLUUID item_id, LLUUID
LLInventoryItem *inv_item = gInventory.getItem(item_id);
if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
if (inv_item
&& (!inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())
|| !inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())))
{
// Need to check if item is already no-transfer, otherwise make it no-transfer
bool no_transfer = false;

View File

@ -32,6 +32,7 @@
#include <boost/signals2.hpp>
#include "llenvironment.h"
#include "llfloatereditenvironmentbase.h"
class LLCheckBoxCtrl;
class LLComboBox;
@ -50,14 +51,13 @@ typedef std::shared_ptr<LLSettingsBase> LLSettingsBasePtr_t;
/**
* Floater for creating or editing a day cycle.
*/
class LLFloaterEditExtDayCycle : public LLFloater
class LLFloaterEditExtDayCycle : public LLFloaterEditEnvironmentBase
{
LOG_CLASS(LLFloaterEditExtDayCycle);
friend class LLDaySettingCopiedCallback;
public:
static const std::string KEY_INVENTORY_ID;
static const std::string KEY_EDIT_CONTEXT;
static const std::string KEY_DAY_LENGTH;
static const std::string KEY_CANMOD;
@ -82,8 +82,8 @@ public:
virtual BOOL postBuild() override;
virtual void onOpen(const LLSD& key) override;
virtual void onClose(bool app_quitting) override;
virtual void onFocusReceived() override;
virtual void onFocusLost() override;
//virtual void onFocusReceived() override;
//virtual void onFocusLost() override;
virtual void onVisibilityChange(BOOL new_visibility) override;
connection_t setEditCommitSignal(edit_commit_signal_t::slot_type cb);
@ -97,10 +97,13 @@ public:
LLUUID getEditingAssetId() { return mEditDay ? mEditDay->getAssetId() : LLUUID::null; }
LLUUID getEditingInventoryId() { return mInventoryId; }
virtual LLSettingsBase::ptr_t getEditSettings() const override { return mEditDay; }
BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) override;
BOOL isDirty() const override { return getIsDirty(); }
protected:
virtual void setEditSettingsAndUpdate(const LLSettingsBase::ptr_t &settings) override;
private:
typedef std::function<void()> on_confirm_fn;
@ -108,8 +111,8 @@ private:
// flyout response/click
void onButtonApply(LLUICtrl *ctrl, const LLSD &data);
virtual void onClickCloseBtn(bool app_quitting = false) override;
void onButtonImport();
//virtual void onClickCloseBtn(bool app_quitting = false) override;
//void onButtonImport();
void onButtonLoadFrame();
void onAddFrame();
void onRemoveFrame();
@ -119,7 +122,6 @@ private:
void onCommitName(class LLLineEditor* caller, void* user_data);
void onTrackSelectionCallback(const LLSD& user_data);
void onPlayActionCallback(const LLSD& user_data);
void onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsDay::ptr_t &day);
// time slider clicked
void onTimeSliderCallback();
// a frame moved or frame selection changed
@ -128,10 +130,6 @@ private:
void onFrameSliderMouseDown(S32 x, S32 y, MASK mask);
void onFrameSliderMouseUp(S32 x, S32 y, MASK mask);
void onPanelDirtyFlagChanged(bool);
void checkAndConfirmSettingsLoss(on_confirm_fn cb);
void cloneTrack(U32 source_index, U32 dest_index);
void cloneTrack(const LLSettingsDay::ptr_t &source_day, U32 source_index, U32 dest_index);
void selectTrack(U32 track_index, bool force = false);
@ -148,25 +146,21 @@ private:
void removeCurrentSliderFrame();
void removeSliderFrame(F32 frame);
void loadInventoryItem(const LLUUID &inventoryId, bool can_trans = true);
void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status);
void doImportFromDisk();
virtual void doImportFromDisk() override;
void loadSettingFromFile(const std::vector<std::string>& filenames);
void doApplyCreateNewInventory(const LLSettingsDay::ptr_t &day, std::string settings_name);
void doApplyUpdateInventory(const LLSettingsDay::ptr_t &day);
void doApplyEnvironment(const std::string &where, const LLSettingsDay::ptr_t &day);
void doApplyCommit(LLSettingsDay::ptr_t day);
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id);
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
void onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
void doOpenTrackFloater(const LLSD &args);
void doCloseTrackFloater(bool quitting = false);
virtual LLFloaterSettingsPicker* getSettingsPicker() override;
void onPickerCommitTrackId(U32 track_id);
void doOpenInventoryFloater(LLSettingsType::type_e type, LLUUID curritem);
void doCloseInventoryFloater(bool quitting = false);
//void doCloseInventoryFloater(bool quitting = false);
void onPickerCommitSetting(LLUUID item_id, S32 track);
void onAssetLoadedForInsertion(LLUUID item_id,
LLUUID asset_id,
@ -176,11 +170,7 @@ private:
S32 dest_track,
LLSettingsBase::TrackPosition dest_frame);
bool canUseInventory() const;
bool canApplyRegion() const;
bool canApplyParcel() const;
void updateEditEnvironment();
virtual void updateEditEnvironment() override;
void synchronizeTabs();
void reblendSettings();
@ -193,7 +183,7 @@ private:
bool getIsDirty() const { return mIsDirty; }
void setDirtyFlag() { mIsDirty = true; }
virtual void clearDirtyFlag();
virtual void clearDirtyFlag() override;
bool isRemovingFrameAllowed();
bool isAddingFrameAllowed();
@ -218,11 +208,8 @@ private:
LLView* mSkyTabLayoutContainer;
LLView* mWaterTabLayoutContainer;
LLTextBox* mCurrentTimeLabel;
LLUUID mInventoryId;
LLInventoryItem * mInventoryItem;
LLFlyoutComboBtnCtrl * mFlyoutControl;
LLHandle<LLFloater> mInventoryFloater;
LLHandle<LLFloater> mTrackFloater;
LLTrackBlenderLoopingManual::ptr_t mSkyBlender;
@ -236,11 +223,6 @@ private:
LLFrameTimer mPlayTimer;
F32 mPlayStartFrame; // an env frame
bool mIsPlaying;
bool mIsDirty;
bool mCanCopy;
bool mCanMod;
bool mCanTrans;
bool mCanSave;
edit_commit_signal_t mCommitSignal;

View File

@ -81,44 +81,11 @@ namespace
const std::string XML_FLYOUTMENU_FILE("menu_save_settings.xml");
}
//=========================================================================
const std::string LLFloaterFixedEnvironment::KEY_INVENTORY_ID("inventory_id");
//=========================================================================
class LLFixedSettingCopiedCallback : public LLInventoryCallback
{
public:
LLFixedSettingCopiedCallback(LLHandle<LLFloater> handle) : mHandle(handle) {}
virtual void fire(const LLUUID& inv_item_id)
{
if (!mHandle.isDead())
{
LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
if (item)
{
LLFloaterFixedEnvironment* floater = (LLFloaterFixedEnvironment*)mHandle.get();
floater->onInventoryCreated(item->getAssetUUID(), inv_item_id);
}
}
}
private:
LLHandle<LLFloater> mHandle;
};
//=========================================================================
LLFloaterFixedEnvironment::LLFloaterFixedEnvironment(const LLSD &key) :
LLFloater(key),
mFlyoutControl(nullptr),
mInventoryId(),
mInventoryItem(nullptr),
mIsDirty(false),
mCanCopy(false),
mCanMod(false),
mCanTrans(false)
LLFloaterEditEnvironmentBase(key),
mFlyoutControl(nullptr)
{
}
@ -176,19 +143,6 @@ void LLFloaterFixedEnvironment::onClose(bool app_quitting)
syncronizeTabs();
}
void LLFloaterFixedEnvironment::onFocusReceived()
{
if (isInVisibleChain())
{
updateEditEnvironment();
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
}
}
void LLFloaterFixedEnvironment::onFocusLost()
{
}
void LLFloaterFixedEnvironment::refresh()
{
if (!mSettings)
@ -220,6 +174,15 @@ void LLFloaterFixedEnvironment::refresh()
}
}
void LLFloaterFixedEnvironment::setEditSettingsAndUpdate(const LLSettingsBase::ptr_t &settings)
{
mSettings = settings; // shouldn't this do buildDeepCloneAndUncompress() ?
updateEditEnvironment();
syncronizeTabs();
refresh();
LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST);
}
void LLFloaterFixedEnvironment::syncronizeTabs()
{
S32 count = mTab->getTabCount();
@ -250,131 +213,9 @@ LLFloaterSettingsPicker * LLFloaterFixedEnvironment::getSettingsPicker()
return picker;
}
void LLFloaterFixedEnvironment::loadInventoryItem(const LLUUID &inventoryId, bool can_trans)
{
if (inventoryId.isNull())
{
mInventoryItem = nullptr;
mInventoryId.setNull();
mCanMod = true;
mCanCopy = true;
mCanTrans = true;
return;
}
mInventoryId = inventoryId;
LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
mInventoryItem = gInventory.getItem(mInventoryId);
if (!mInventoryItem)
{
LL_WARNS("SETTINGS") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
LLNotificationsUtil::add("CantFindInvItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
if (mInventoryItem->getAssetUUID().isNull())
{
LL_WARNS("ENVIRONMENT") << "Asset ID in inventory item is NULL (" << mInventoryId << ")" << LL_ENDL;
LLNotificationsUtil::add("UnableEditItem");
closeFloater();
mInventoryId.setNull();
mInventoryItem = nullptr;
return;
}
mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
mCanTrans = can_trans && mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
[this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
}
void LLFloaterFixedEnvironment::checkAndConfirmSettingsLoss(LLFloaterFixedEnvironment::on_confirm_fn cb)
{
if (isDirty())
{
LLSD args(LLSDMap("TYPE", mSettings->getSettingsType())
("NAME", mSettings->getName()));
// create and show confirmation textbox
LLNotificationsUtil::add("SettingsConfirmLoss", args, LLSD(),
[cb](const LLSD&notif, const LLSD&resp)
{
S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
if (opt == 0)
cb();
});
}
else if (cb)
{
cb();
}
}
void LLFloaterFixedEnvironment::onPickerCommitSetting(LLUUID item_id)
{
loadInventoryItem(item_id);
// mInventoryId = item_id;
// mInventoryItem = gInventory.getItem(mInventoryId);
//
// mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
// mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
// mCanTrans = mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
//
// LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
// [this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
}
void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
{
if (mInventoryItem && mInventoryItem->getAssetUUID() != asset_id)
{
LL_WARNS("ENVIRONMENT") << "Discarding obsolete asset callback" << LL_ENDL;
return;
}
clearDirtyFlag();
if (!settings || status)
{
LLSD args;
args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
closeFloater();
return;
}
mSettings = settings;
if (mInventoryItem)
mSettings->setName(mInventoryItem->getName());
if (mCanCopy)
settings->clearFlag(LLSettingsBase::FLAG_NOCOPY);
else
settings->setFlag(LLSettingsBase::FLAG_NOCOPY);
if (mCanMod)
settings->clearFlag(LLSettingsBase::FLAG_NOMOD);
else
settings->setFlag(LLSettingsBase::FLAG_NOMOD);
if (mCanTrans)
settings->clearFlag(LLSettingsBase::FLAG_NOTRANS);
else
settings->setFlag(LLSettingsBase::FLAG_NOTRANS);
updateEditEnvironment();
syncronizeTabs();
refresh();
LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST);
}
void LLFloaterFixedEnvironment::onNameChanged(const std::string &name)
@ -473,51 +314,6 @@ void LLFloaterFixedEnvironment::onButtonApply(LLUICtrl *ctrl, const LLSD &data)
}
}
void LLFloaterFixedEnvironment::onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
std::string settings_name = response["message"].asString();
LLInventoryObject::correctInventoryName(settings_name);
if (settings_name.empty())
{
// Ideally notification should disable 'OK' button if name won't fit our requirements,
// for now either display notification, or use some default name
settings_name = "Unnamed";
}
if (mCanMod)
{
doApplyCreateNewInventory(settings_name, settings);
}
else if (mInventoryItem)
{
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
LLUUID parent_id = mInventoryItem->getParentUUID();
if ((marketplacelistings_id == parent_id) || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
{
parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
}
LLPointer<LLInventoryCallback> cb = new LLFixedSettingCopiedCallback(getHandle());
copy_inventory_item(
gAgent.getID(),
mInventoryItem->getPermissions().getOwner(),
mInventoryItem->getUUID(),
parent_id,
settings_name,
cb);
}
else
{
LL_WARNS() << "Failed to copy fixed env setting" << LL_ENDL;
}
}
}
void LLFloaterFixedEnvironment::onClickCloseBtn(bool app_quitting)
{
if (!app_quitting)
@ -531,116 +327,6 @@ void LLFloaterFixedEnvironment::onButtonLoad()
checkAndConfirmSettingsLoss([this](){ doSelectFromInventory(); });
}
void LLFloaterFixedEnvironment::doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings)
{
if (mInventoryItem)
{
LLUUID parent_id = mInventoryItem->getParentUUID();
U32 next_owner_perm = mInventoryItem->getPermissions().getMaskNextOwner();
LLSettingsVOBase::createInventoryItem(settings, next_owner_perm, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
else
{
LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
// This method knows what sort of settings object to create.
LLSettingsVOBase::createInventoryItem(settings, parent_id, settings_name,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
}
void LLFloaterFixedEnvironment::doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings)
{
LL_DEBUGS("ENVEDIT") << "Update inventory for " << mInventoryId << LL_ENDL;
if (mInventoryId.isNull())
{
LLSettingsVOBase::createInventoryItem(settings, gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS), std::string(),
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
}
else
{
LLSettingsVOBase::updateInventoryItem(settings, mInventoryId,
[this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
}
}
void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings)
{
U32 flags(0);
if (mInventoryItem)
{
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOMOD;
if (!mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
flags |= LLSettingsBase::FLAG_NOTRANS;
}
flags |= settings->getFlags();
settings->setFlag(flags);
if (where == ACTION_APPLY_LOCAL)
{
settings->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, settings);
}
else if (where == ACTION_APPLY_PARCEL)
{
LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
{
LL_WARNS("ENVIRONMENT") << "Can not identify parcel. Not applying." << LL_ENDL;
LLNotificationsUtil::add("WLParcelApplyFail");
return;
}
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else if (settings->getSettingsType() == "sky")
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
}
else if (settings->getSettingsType() == "water")
{
LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
}
}
else if (where == ACTION_APPLY_REGION)
{
if (mInventoryItem && !isDirty())
{
LLEnvironment::instance().updateRegion(mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
}
else if (settings->getSettingsType() == "sky")
{
LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
}
else if (settings->getSettingsType() == "water")
{
LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
}
}
else
{
LL_WARNS("ENVIRONMENT") << "Unknown apply '" << where << "'" << LL_ENDL;
return;
}
}
void LLFloaterFixedEnvironment::doCloseInventoryFloater(bool quitting)
{
LLFloater* floaterp = mInventoryFloater.get();
if (floaterp)
{
floaterp->closeFloater(quitting);
}
}
void LLFloaterFixedEnvironment::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
{
LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
@ -710,28 +396,6 @@ void LLFloaterFixedEnvironment::doSelectFromInventory()
picker->setFocus(TRUE);
}
void LLFloaterFixedEnvironment::onPanelDirtyFlagChanged(bool value)
{
if (value)
setDirtyFlag();
}
//-------------------------------------------------------------------------
bool LLFloaterFixedEnvironment::canUseInventory() const
{
return LLEnvironment::instance().isInventoryEnabled();
}
bool LLFloaterFixedEnvironment::canApplyRegion() const
{
return gAgent.canManageEstate();
}
bool LLFloaterFixedEnvironment::canApplyParcel() const
{
return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
}
//=========================================================================
LLFloaterFixedEnvironmentWater::LLFloaterFixedEnvironmentWater(const LLSD &key):
LLFloaterFixedEnvironment(key)

View File

@ -27,7 +27,7 @@
#ifndef LL_FLOATERFIXEDENVIRONMENT_H
#define LL_FLOATERFIXEDENVIRONMENT_H
#include "llfloater.h"
#include "llfloatereditenvironmentbase.h"
#include "llsettingsbase.h"
#include "llflyoutcombobtn.h"
#include "llinventory.h"
@ -43,15 +43,10 @@ class LLFixedSettingCopiedCallback;
/**
* Floater container for creating and editing fixed environment settings.
*/
class LLFloaterFixedEnvironment : public LLFloater
class LLFloaterFixedEnvironment : public LLFloaterEditEnvironmentBase
{
LOG_CLASS(LLFloaterFixedEnvironment);
friend class LLFixedSettingCopiedCallback;
public:
static const std::string KEY_INVENTORY_ID;
LLFloaterFixedEnvironment(const LLSD &key);
~LLFloaterFixedEnvironment();
@ -59,64 +54,35 @@ public:
virtual void onOpen(const LLSD& key) override;
virtual void onClose(bool app_quitting) override;
virtual void onFocusReceived() override;
virtual void onFocusLost() override;
void setEditSettings(const LLSettingsBase::ptr_t &settings) { mSettings = settings; clearDirtyFlag(); syncronizeTabs(); refresh(); }
LLSettingsBase::ptr_t getEditSettings() const { return mSettings; }
virtual BOOL isDirty() const override { return getIsDirty(); }
virtual LLSettingsBase::ptr_t getEditSettings() const override { return mSettings; }
protected:
typedef std::function<void()> on_confirm_fn;
virtual void updateEditEnvironment() = 0;
virtual void refresh() override;
void setEditSettingsAndUpdate(const LLSettingsBase::ptr_t &settings) override;
virtual void syncronizeTabs();
LLFloaterSettingsPicker *getSettingsPicker();
void loadInventoryItem(const LLUUID &inventoryId, bool can_trans = true);
void checkAndConfirmSettingsLoss(on_confirm_fn cb);
virtual LLFloaterSettingsPicker *getSettingsPicker() override;
LLTabContainer * mTab;
LLLineEditor * mTxtName;
LLSettingsBase::ptr_t mSettings;
virtual void doImportFromDisk() = 0;
virtual void doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings);
virtual void doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings);
virtual void doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings);
void doCloseInventoryFloater(bool quitting = false);
bool canUseInventory() const;
bool canApplyRegion() const;
bool canApplyParcel() const;
LLFlyoutComboBtnCtrl * mFlyoutControl;
LLUUID mInventoryId;
LLInventoryItem * mInventoryItem;
LLHandle<LLFloater> mInventoryFloater;
bool mCanCopy;
bool mCanMod;
bool mCanTrans;
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id);
void onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
void onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
bool getIsDirty() const { return mIsDirty; }
void setDirtyFlag() { mIsDirty = true; }
virtual void clearDirtyFlag();
virtual void clearDirtyFlag() override;
void updatePermissionFlags();
void doSelectFromInventory();
void onPanelDirtyFlagChanged(bool);
virtual void onClickCloseBtn(bool app_quitting = false) override;
void onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings);
private:
void onNameChanged(const std::string &name);
@ -126,9 +92,6 @@ private:
void onButtonLoad();
void onPickerCommitSetting(LLUUID item_id);
void onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status);
bool mIsDirty;
};
class LLFloaterFixedEnvironmentWater : public LLFloaterFixedEnvironment
@ -172,36 +135,4 @@ protected:
private:
};
class LLSettingsEditPanel : public LLPanel
{
public:
virtual void setSettings(const LLSettingsBase::ptr_t &) = 0;
typedef boost::signals2::signal<void(LLPanel *, bool)> on_dirty_charged_sg;
typedef boost::signals2::connection connection_t;
inline bool getIsDirty() const { return mIsDirty; }
inline void setIsDirty() { mIsDirty = true; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
inline void clearIsDirty() { mIsDirty = false; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
inline bool getCanChangeSettings() const { return mCanEdit; }
inline void setCanChangeSettings(bool flag) { mCanEdit = flag; }
inline connection_t setOnDirtyFlagChanged(on_dirty_charged_sg::slot_type cb) { return mOnDirtyChanged.connect(cb); }
protected:
LLSettingsEditPanel() :
LLPanel(),
mIsDirty(false),
mOnDirtyChanged()
{}
private:
bool mIsDirty;
bool mCanEdit;
on_dirty_charged_sg mOnDirtyChanged;
};
#endif // LL_FLOATERFIXEDENVIRONMENT_H

View File

@ -315,12 +315,15 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLIconCtrl* icon = 0;
bool is_in_group = gAgent.isInGroup(session_id, TRUE);
LLUUID icon_id;
if(gAgent.isInGroup(session_id, TRUE))
if (is_in_group)
{
LLGroupIconCtrl::Params icon_params;
icon_params.group_id = session_id;
icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
icon_id = session_id;
mSessions[session_id] = floaterp;
floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id));
@ -332,11 +335,18 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLAvatarIconCtrl::Params icon_params;
icon_params.avatar_id = avatar_id;
icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
icon_id = avatar_id;
mSessions[session_id] = floaterp;
floaterp->mCloseSignal.connect(boost::bind(&LLFloaterIMContainer::onCloseFloater, this, session_id));
}
LLFloaterIMSessionTab* floater = LLFloaterIMSessionTab::getConversation(session_id);
if (floater)
{
floater->updateChatIcon(icon_id);
}
// forced resize of the floater
LLRect wrapper_rect = this->mTabContainer->getLocalRect();
floaterp->setRect(wrapper_rect);
@ -1866,6 +1876,8 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
{
new_selection = mConversationsRoot->getPreviousFromChild(widget, FALSE);
}
// Will destroy views and delete models that are not assigned to any views
widget->destroyView();
}

View File

@ -34,6 +34,8 @@
#include "llagent.h"
#include "llagentcamera.h"
#include "llavataractions.h"
#include "llavatariconctrl.h"
#include "llgroupiconctrl.h"
#include "llchatentry.h"
#include "llchathistory.h"
#include "llchiclet.h"
@ -47,6 +49,9 @@
#include "llfloaterimnearbychat.h"
const F32 REFRESH_INTERVAL = 1.0f;
const std::string ICN_GROUP("group_chat_icon");
const std::string ICN_NEARBY("nearby_chat_icon");
const std::string ICN_AVATAR("avatar_icon");
void cb_group_do_nothing()
{
@ -534,8 +539,7 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
if (widget)
{
mConversationsRoot->extractItem(widget);
delete widget;
widget->destroyView();
}
mConversationsWidgets.erase(participant_id);
}
@ -705,6 +709,39 @@ void LLFloaterIMSessionTab::updateSessionName(const std::string& name)
mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name);
}
void LLFloaterIMSessionTab::updateChatIcon(const LLUUID& id)
{
if (mSession)
{
if (mSession->isP2PSessionType())
{
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>(ICN_AVATAR);
icon->setVisible(true);
icon->setValue(id);
}
if (mSession->isAdHocSessionType())
{
LLGroupIconCtrl* icon = getChild<LLGroupIconCtrl>(ICN_GROUP);
icon->setVisible(true);
}
if (mSession->isGroupSessionType())
{
LLGroupIconCtrl* icon = getChild<LLGroupIconCtrl>(ICN_GROUP);
icon->setVisible(true);
icon->setValue(id);
}
}
else
{
if (mIsNearbyChat)
{
LLIconCtrl* icon = getChild<LLIconCtrl>(ICN_NEARBY);
icon->setVisible(true);
}
}
}
void LLFloaterIMSessionTab::hideAllStandardButtons()
{
for (S32 i = 0; i < BUTTON_COUNT; i++)

View File

@ -105,6 +105,8 @@ public:
void restoreFloater();
void saveCollapsedState();
void updateChatIcon(const LLUUID& id);
LLView* getChatHistory();
protected:

View File

@ -104,14 +104,17 @@ void LLPanelMarketplaceListings::buildAllPanels()
panel = buildInventoryPanel("Active Items", "panel_marketplace_listings_listed.xml");
panel->getFilter().setFilterMarketplaceActiveFolders();
panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems");
panel->getFilter().setDefaultEmptyLookupMessage("MarketplaceNoListing");
panel->getFilter().markDefault();
panel = buildInventoryPanel("Inactive Items", "panel_marketplace_listings_unlisted.xml");
panel->getFilter().setFilterMarketplaceInactiveFolders();
panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems");
panel->getFilter().setDefaultEmptyLookupMessage("MarketplaceNoListing");
panel->getFilter().markDefault();
panel = buildInventoryPanel("Unassociated Items", "panel_marketplace_listings_unassociated.xml");
panel->getFilter().setFilterMarketplaceUnassociatedFolders();
panel->getFilter().setEmptyLookupMessage("MarketplaceNoMatchingItems");
panel->getFilter().setDefaultEmptyLookupMessage("MarketplaceNoListing");
panel->getFilter().markDefault();
// Set the tab panel

View File

@ -105,6 +105,11 @@ LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
void LLMeshFilePicker::notify(const std::vector<std::string>& filenames)
{
if(LLAppViewer::instance()->quitRequested())
{
return;
}
if (filenames.size() > 0)
{
mMP->loadModel(filenames[0], mLOD);

View File

@ -39,6 +39,7 @@
#include "llfloaterimcontainer.h"
#include "llimview.h" // for gIMMgr
#include "llnotificationsutil.h"
#include "llstartup.h"
#include "llstatusbar.h" // can_afford_transaction()
#include "groupchatlistener.h"
// [RLVa:KB] - Checked: 2011-03-28 (RLVa-1.3.0)
@ -71,6 +72,11 @@ public:
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{
if (LLStartUp::getStartupState() < STATE_STARTED)
{
return true;
}
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableGroupInfo"))
{
LLNotificationsUtil::add("NoGroupInfo", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));

View File

@ -1131,6 +1131,9 @@ void LLIMModel::LLIMSession::buildHistoryFileName()
}
// </FS:Ansariel> [Legacy IM logfile names]
}
// user's account name can change, but filenames and session names are account name based
LLConversationLog::getInstance()->verifyFilename(mSessionID, mHistoryFileName, av_name.getCompleteName());
}
else if (isGroupChat())
{

View File

@ -80,6 +80,7 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
: mName(p.name),
mFilterModified(FILTER_NONE),
mEmptyLookupMessage("InventoryNoMatchingItems"),
mDefaultEmptyLookupMessage(""),
mFilterOps(p.filter_ops),
mBackupFilterOps(mFilterOps),
mFilterSubString(p.substring),
@ -1604,12 +1605,24 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)
mEmptyLookupMessage = message;
}
void LLInventoryFilter::setDefaultEmptyLookupMessage(const std::string& message)
{
mDefaultEmptyLookupMessage = message;
}
std::string LLInventoryFilter::getEmptyLookupMessage() const
{
LLStringUtil::format_map_t args;
args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig());
if (isDefault() && !mDefaultEmptyLookupMessage.empty())
{
return LLTrans::getString(mDefaultEmptyLookupMessage);
}
else
{
LLStringUtil::format_map_t args;
args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig());
return LLTrans::getString(mEmptyLookupMessage, args);
return LLTrans::getString(mEmptyLookupMessage, args);
}
}

View File

@ -270,6 +270,7 @@ public:
EFilterCreatorType getFilterCreatorType() const;
void setEmptyLookupMessage(const std::string& message);
void setDefaultEmptyLookupMessage(const std::string& message);
std::string getEmptyLookupMessage() const;
// +-------------------------------------------------------------------+
@ -346,6 +347,7 @@ private:
std::string mFilterText;
std::string mEmptyLookupMessage;
std::string mDefaultEmptyLookupMessage;
ESearchType mSearchType;

View File

@ -106,14 +106,14 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
mWaitList.insert(asset_uuid);
return NULL;
}
// <FS:Beq/> fIRE-14457 Fix CopySLURL fails / landmakrs not loading - based on snippet from Chorazin Allen
mRequestedList[asset_uuid] = gFrameTimeSeconds;
mRequestedList[asset_uuid] = gFrameTimeSeconds;
// Note that getAssetData can callback immediately and cleans mRequestedList
gAssetStorage->getAssetData(asset_uuid,
LLAssetType::AT_LANDMARK,
LLLandmarkList::processGetAssetReply,
NULL);
// <FS:Beq/> fIRE-14457 Fix CopySLURL fails / landmakrs not loading - based on snippet from Chorazin Allen
// mRequestedList[asset_uuid] = gFrameTimeSeconds;
}
return NULL;
}
@ -197,11 +197,15 @@ void LLLandmarkList::processGetAssetReply(
landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin();
LLUUID asset_uuid = *iter;
gLandmarkList.mWaitList.erase(iter);
// add to mRequestedList before calling getAssetData()
gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds;
// Note that getAssetData can callback immediately and cleans mRequestedList
gAssetStorage->getAssetData(asset_uuid,
LLAssetType::AT_LANDMARK,
LLLandmarkList::processGetAssetReply,
NULL);
gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds;
}
scheduling = false;
}

View File

@ -352,6 +352,28 @@ std::string LLLogChat::makeLogFileName(std::string filename)
return filename;
}
//static
void LLLogChat::renameLogFile(const std::string& old_filename, const std::string& new_filename)
{
std::string new_name = cleanFileName(new_filename);
std::string old_name = cleanFileName(old_filename);
new_name = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, new_name);
old_name = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, old_name);
if (new_name.empty() || old_name.empty())
{
return;
}
new_name += '.' + LL_TRANSCRIPT_FILE_EXTENSION;
old_name += '.' + LL_TRANSCRIPT_FILE_EXTENSION;
if (!LLFile::isfile(new_name) && LLFile::isfile(old_name))
{
LLFile::rename(old_name, new_name);
}
}
std::string LLLogChat::cleanFileName(std::string filename)
{
std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars

View File

@ -94,6 +94,7 @@ public:
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
static void renameLogFile(const std::string& old_filename, const std::string& new_filename);
/**
*Add functions to get old and non date stamped file names when needed
*/

View File

@ -58,6 +58,7 @@
#include "llevents.h"
#include "llappviewer.h"
#include "llsdserialize.h"
#include "lltrans.h"
#include <boost/scoped_ptr.hpp>
#include <sstream>
@ -347,7 +348,7 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
{
data["certificate"] = response["certificate"];
}
if (gViewerWindow)
gViewerWindow->setShowProgress(FALSE, FALSE);
LLFloaterReg::showInstance("message_critical", data);
@ -363,13 +364,36 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
// login.cgi is insisting on a required update. We were called with an
// event that bundles both the login.cgi 'response' and the
// synchronization event from the 'updater'.
std::string required_version = response["message_args"]["VERSION"];
LL_WARNS("LLLogin") << "Login failed because an update to version " << required_version << " is required." << LL_ENDL;
std::string login_version = response["message_args"]["VERSION"];
std::string vvm_version = updater["VERSION"];
std::string relnotes = updater["URL"];
LL_WARNS("LLLogin") << "Login failed because an update to version " << login_version << " is required." << LL_ENDL;
// vvm_version might be empty because we might not have gotten
// SLVersionChecker's LoginSync handshake. But if it IS populated, it
// should (!) be the same as the version we got from login.cgi.
if ((! vvm_version.empty()) && vvm_version != login_version)
{
LL_WARNS("LLLogin") << "VVM update version " << vvm_version
<< " differs from login version " << login_version
<< "; presenting VVM version to match release notes URL"
<< LL_ENDL;
login_version = vvm_version;
}
if (relnotes.empty() || relnotes.find("://") == std::string::npos)
{
relnotes = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (!LLStringUtil::endsWith(relnotes, "/"))
relnotes += "/";
relnotes += LLURI::escape(login_version) + ".html";
}
if (gViewerWindow)
gViewerWindow->setShowProgress(FALSE, FALSE);
LLSD args(LLSDMap("VERSION", required_version));
LLSD args;
args["VERSION"] = login_version;
args["URL"] = relnotes;
if (updater.isUndefined())
{
// If the updater failed to shake hands, better advise the user to

View File

@ -302,6 +302,7 @@ public:
* Writes notification message to IM p2p session.
*/
static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false);
static void logToIMP2P(const LLUUID& from_id, const std::string& message, bool to_file_only = false);
/**
* Writes group notice notification message to IM group session.

View File

@ -174,15 +174,13 @@ void log_name_callback(const LLAvatarName& av_name, const std::string& from_name
}
// static
void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)
void LLHandlerUtil::logToIMP2P(const LLUUID& from_id, const std::string& message, bool to_file_only)
{
if (!gCacheName)
{
return;
}
LLUUID from_id = notification->getPayload()["from_id"];
if (from_id.isNull())
{
// Normal behavior for system generated messages, don't spam.
@ -192,14 +190,21 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi
if(to_file_only)
{
LLAvatarNameCache::get(from_id, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID()));
LLAvatarNameCache::get(from_id, boost::bind(&log_name_callback, _2, "", message, LLUUID()));
}
else
{
LLAvatarNameCache::get(from_id, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));
LLAvatarNameCache::get(from_id, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, message, from_id));
}
}
// static
void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)
{
LLUUID from_id = notification->getPayload()["from_id"];
logToIMP2P(from_id, notification->getMessage(), to_file_only);
}
// static
void LLHandlerUtil::logGroupNoticeToIMGroup(
const LLNotificationPtr& notification)

View File

@ -40,6 +40,8 @@
#include "rlvactions.h"
// [/RLVa:KB]
#include <boost/regex.hpp>
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
@ -167,7 +169,19 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)
{
// log only to file if notif panel can be embedded to IM and IM is opened
bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification);
LLHandlerUtil::logToIMP2P(notification, file_only);
if ((notification->getName() == "TeleportOffered"
|| notification->getName() == "TeleportOffered_MaturityExceeded"
|| notification->getName() == "TeleportOffered_MaturityBlocked"))
{
boost::regex r("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>( - )?",
boost::regex::perl|boost::regex::icase);
std::string stripped_msg = boost::regex_replace(notification->getMessage(), r, "");
LLHandlerUtil::logToIMP2P(notification->getPayload()["from_id"], stripped_msg,file_only);
}
else
{
LLHandlerUtil::logToIMP2P(notification, file_only);
}
}
}

View File

@ -29,7 +29,7 @@
#include "llpanel.h"
#include "llsettingssky.h"
#include "llfloaterfixedenvironment.h"
#include "llfloatereditenvironmentbase.h"
//=========================================================================
class LLSlider;

View File

@ -30,7 +30,7 @@
#include "llpanel.h"
#include "llsettingswater.h"
#include "llfloaterfixedenvironment.h"
#include "llfloatereditenvironmentbase.h"
//=========================================================================
class LLSlider;

View File

@ -546,6 +546,16 @@ void LLPanelLogin::show(const LLRect &rect,
gFocusMgr.setDefaultKeyboardFocus(sInstance);
}
//static
void LLPanelLogin::reshapePanel()
{
if (sInstance)
{
LLRect rect = sInstance->getRect();
sInstance->reshape(rect.getWidth(), rect.getHeight());
}
}
//static
void LLPanelLogin::populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd)
{

View File

@ -56,6 +56,7 @@ public:
static void show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data);
static void reshapePanel();
static void populateFields(LLPointer<LLCredential> credential, bool remember_user, bool remember_psswrd);
static void resetFields();

View File

@ -37,6 +37,7 @@
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
#include "llnotificationsutil.h"
#include "llstartup.h"
#include "lltexturectrl.h"
#include "lltoggleablemenu.h"
#include "lltrans.h"
@ -86,6 +87,11 @@ public:
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"));
@ -208,6 +214,11 @@ public:
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"));

View File

@ -74,6 +74,8 @@ const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels
const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
const F32 EXCEEDING_ZOOM_DISTANCE = 0.5f;
const S32 ADDR_LEFT_PAD = 3;
//
// LLPanelPrimMediaControls
//
@ -156,7 +158,7 @@ BOOL LLPanelPrimMediaControls::postBuild()
mMediaProgressPanel = getChild<LLPanel>("media_progress_indicator");
mMediaProgressBar = getChild<LLProgressBar>("media_progress_bar");
mMediaAddressCtrl = getChild<LLUICtrl>("media_address");
mMediaAddress = getChild<LLUICtrl>("media_address_url");
mMediaAddress = getChild<LLLineEditor>("media_address_url");
mMediaPlaySliderPanel = getChild<LLUICtrl>("media_play_position");
mMediaPlaySliderCtrl = getChild<LLUICtrl>("media_play_slider");
mSkipFwdCtrl = getChild<LLUICtrl>("skip_forward");
@ -501,8 +503,10 @@ void LLPanelPrimMediaControls::updateShape()
std::string test_prefix = mCurrentURL.substr(0, prefix.length());
LLStringUtil::toLower(test_prefix);
mSecureURL = has_focus && (test_prefix == prefix);
mCurrentURL = (mSecureURL ? " " + mCurrentURL : mCurrentURL);
S32 left_pad = mSecureURL ? mSecureLockIcon->getRect().getWidth() : ADDR_LEFT_PAD;
mMediaAddress->setTextPadding(left_pad, 0);
if(mCurrentURL!=mPreviousURL)
{
setCurrentURL();

View File

@ -39,6 +39,7 @@ class LLProgressBar;
class LLSliderCtrl;
class LLViewerMediaImpl;
class LLWindowShade;
class LLLineEditor;
class LLPanelPrimMediaControls : public LLPanel
{
@ -164,7 +165,7 @@ private:
LLPanel *mMediaProgressPanel;
LLProgressBar *mMediaProgressBar;
LLUICtrl *mMediaAddressCtrl;
LLUICtrl *mMediaAddress;
LLLineEditor *mMediaAddress;
LLUICtrl *mMediaPlaySliderPanel;
LLUICtrl *mMediaPlaySliderCtrl;
LLUICtrl *mVolumeCtrl;

View File

@ -266,11 +266,7 @@ LLParticipantList::~LLParticipantList()
*/
void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id)
{
LLConversationItemParticipant* participant = findParticipant(participant_id);
if (participant)
{
removeParticipant(participant);
}
removeParticipant(participant_id);
// re-add avaline caller with a correct class instance.
addAvatarIDExceptAgent(participant_id);
}
@ -404,6 +400,7 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
// Hack for this: LLAvatarTracker::instance().isBuddyOnline(avatar_id))
// Add the participant model to the session's children list
// This will post "add_participant" event
addParticipant(participant);
adjustParticipant(avatar_id);

View File

@ -1214,7 +1214,10 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
}
if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME))
{
std::string help_string = mEditor->getText().substr(segment->getStart(), segment->getEnd() - segment->getStart());
// Use Wtext since segment's start/end are made for wstring and will
// result in a shift for case of multi-byte symbols inside std::string.
LLWString segment_text = mEditor->getWText().substr(segment->getStart(), segment->getEnd() - segment->getStart());
std::string help_string = wstring_to_utf8str(segment_text);
setHelpPage(help_string);
mLiveHelpTimer.stop();
}

View File

@ -530,157 +530,163 @@ void LLSceneMonitor::dumpToFile(std::string file_name)
if (!hasResults()) return;
LL_INFOS("SceneMonitor") << "Saving scene load stats to " << file_name << LL_ENDL;
llofstream os(file_name.c_str());
os << std::setprecision(10);
LLTrace::PeriodicRecording& scene_load_recording = mSceneLoadRecording.getResults();
const U32 frame_count = scene_load_recording.getNumRecordedPeriods();
F64Seconds frame_time;
os << "Stat";
for (S32 frame = 1; frame <= frame_count; frame++)
try
{
frame_time += scene_load_recording.getPrevRecording(frame_count - frame).getDuration();
os << ", " << frame_time.value();
}
os << '\n';
llofstream os(file_name.c_str());
os << "Sample period(s)";
for (S32 frame = 1; frame <= frame_count; frame++)
{
frame_time = scene_load_recording.getPrevRecording(frame_count - frame).getDuration();
os << ", " << frame_time.value();
}
os << '\n';
os << std::setprecision(10);
LLTrace::PeriodicRecording& scene_load_recording = mSceneLoadRecording.getResults();
const U32 frame_count = scene_load_recording.getNumRecordedPeriods();
typedef LLTrace::StatType<LLTrace::CountAccumulator> trace_count;
for (auto& it : trace_count::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if(unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
F64Seconds frame_time;
os << "Stat";
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
row << ", " << recording.getSum(it);
frame_time += scene_load_recording.getPrevRecording(frame_count - frame).getDuration();
os << ", " << frame_time.value();
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::EventAccumulator> trace_event;
for (auto& it : trace_event::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if(unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
F64 mean = recording.getMean(it);
if (llisnan(mean))
{
row << ", n/a";
}
else
{
row << ", " << mean;
}
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::SampleAccumulator> trace_sample;
for (auto& it : trace_sample::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if(unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
F64 mean = recording.getMean(it);
if (llisnan(mean))
{
row << ", n/a";
}
else
{
row << ", " << mean;
}
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::MemAccumulator> trace_mem;
for (auto& it : trace_mem::instance_snapshot())
{
os << it.getName() << "(KiB)";
for (S32 frame = 1; frame <= frame_count; frame++)
{
os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(it).valueInUnits<LLUnits::Kilobytes>();
}
os << '\n';
}
os.flush();
os.close();
os << "Sample period(s)";
for (S32 frame = 1; frame <= frame_count; frame++)
{
frame_time = scene_load_recording.getPrevRecording(frame_count - frame).getDuration();
os << ", " << frame_time.value();
}
os << '\n';
typedef LLTrace::StatType<LLTrace::CountAccumulator> trace_count;
for (auto& it : trace_count::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if (unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
row << ", " << recording.getSum(it);
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::EventAccumulator> trace_event;
for (auto& it : trace_event::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if (unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
F64 mean = recording.getMean(it);
if (llisnan(mean))
{
row << ", n/a";
}
else
{
row << ", " << mean;
}
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::SampleAccumulator> trace_sample;
for (auto& it : trace_sample::instance_snapshot())
{
std::ostringstream row;
row << std::setprecision(10);
row << it.getName();
const char* unit_label = it.getUnitLabel();
if (unit_label[0])
{
row << "(" << unit_label << ")";
}
S32 samples = 0;
for (S32 frame = 1; frame <= frame_count; frame++)
{
LLTrace::Recording& recording = scene_load_recording.getPrevRecording(frame_count - frame);
samples += recording.getSampleCount(it);
F64 mean = recording.getMean(it);
if (llisnan(mean))
{
row << ", n/a";
}
else
{
row << ", " << mean;
}
}
row << '\n';
if (samples > 0)
{
os << row.str();
}
}
typedef LLTrace::StatType<LLTrace::MemAccumulator> trace_mem;
for (auto& it : trace_mem::instance_snapshot())
{
os << it.getName() << "(KiB)";
for (S32 frame = 1; frame <= frame_count; frame++)
{
os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(it).valueInUnits<LLUnits::Kilobytes>();
}
os << '\n';
}
os.flush();
os.close();
}
catch (const std::ios_base::failure &e)
{
LL_WARNS() << "Unable to dump scene monitor results: " << e.what() << LL_ENDL;
}
}
//-------------------------------------------------------------------------------------------------------------

View File

@ -132,47 +132,52 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin
//<FS:Beq> Per frame SkinningMatrix Caching
//void LLSkinningUtil::initSkinningMatrixPalette(
// LLMatrix4* mat,
// S32 count,
// const LLMeshSkinInfo* skin,
// LLVOAvatar *avatar)
// LLMatrix4* mat,
// S32 count,
// const LLMeshSkinInfo* skin,
// LLVOAvatar *avatar)
//{
// initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
// for (U32 j = 0; j < count; ++j)
// {
// LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
// llassert(joint);
// if (joint)
// {
// initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
// for (U32 j = 0; j < count; ++j)
// {
// S32 joint_num = skin->mJointNums[j];
// LLJoint * joint = NULL;
// if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)
// {
// joint = avatar->getJoint(joint_num);
// }
// llassert(joint);
// if (joint)
// {
//#ifdef MAT_USE_SSE
// LLMatrix4a bind, world, res;
// bind.loadu(skin->mInvBindMatrix[j]);
// world.loadu(joint->getWorldMatrix());
// matMul(bind, world, res);
// memcpy(mat[j].mMatrix, res.mMatrix, 16 * sizeof(float));
// LLMatrix4a bind, world, res;
// bind.loadu(skin->mInvBindMatrix[j]);
// world.loadu(joint->getWorldMatrix());
// matMul(bind, world, res);
// memcpy(mat[j].mMatrix, res.mMatrix, 16 * sizeof(float));
//#else
// mat[j] = skin->mInvBindMatrix[j];
// mat[j] *= joint->getWorldMatrix();
// mat[j] = skin->mInvBindMatrix[j];
// mat[j] *= joint->getWorldMatrix();
//#endif
// }
// else
// {
// mat[j] = skin->mInvBindMatrix[j];
// }
// else
// {
// mat[j] = skin->mInvBindMatrix[j];
//#if DEBUG_SKINNING
// // This shouldn't happen - in mesh upload, skinned
// // rendering should be disabled unless all joints are
// // valid. In other cases of skinned rendering, invalid
// // joints should already have been removed during scrubInvalidJoints().
// LL_WARNS_ONCE("Avatar") << avatar->getFullname()
// << " rigged to invalid joint name " << skin->mJointNames[j]
// << " num " << skin->mJointNums[j] << LL_ENDL;
// LL_WARNS_ONCE("Avatar") << avatar->getFullname()
// << " avatar build state: isBuilt() " << avatar->isBuilt()
// << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
// // This shouldn't happen - in mesh upload, skinned
// // rendering should be disabled unless all joints are
// // valid. In other cases of skinned rendering, invalid
// // joints should already have been removed during scrubInvalidJoints().
// LL_WARNS_ONCE("Avatar") << avatar->getFullname()
// << " rigged to invalid joint name " << skin->mJointNames[j]
// << " num " << skin->mJointNums[j] << LL_ENDL;
// LL_WARNS_ONCE("Avatar") << avatar->getFullname()
// << " avatar build state: isBuilt() " << avatar->isBuilt()
// << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
//#endif
// dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin);
// }
// }
// dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin);
// }
// }
//}
#ifndef LL_RELEASE_FOR_DOWNLOAD
@ -186,44 +191,49 @@ void LLSkinningUtil::initSkinningMatrixPalette(
LLVOAvatar *avatar)
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
// This timer is too hot for normal use (though better now with caching)
LL_RECORD_BLOCK_TIME(FTM_SKINNING_INIT);
// This timer is too hot for normal use (though better now with caching)
LL_RECORD_BLOCK_TIME(FTM_SKINNING_INIT);
#endif
LLMatrix4a bind[LL_MAX_JOINTS_PER_MESH_OBJECT];
LLMatrix4a world[LL_MAX_JOINTS_PER_MESH_OBJECT];
LLMatrix4a bind[LL_MAX_JOINTS_PER_MESH_OBJECT];
LLMatrix4a world[LL_MAX_JOINTS_PER_MESH_OBJECT];
initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
// TODO: Refactored to encourage the compiler to optimise better but it's too old and stubborn. Need to hand tool the SIMD.
// TODO: There are two overheads in this function casued by the unaligned loads. use Matrix4a
// TODO: getWorldMatrix forces a reverse recursion up through the skelly. Check if this is happening efficiently.
for (U32 j = 0; j < count; ++j)
for (U32 j = 0; j < count; ++j)
{
LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
if (joint)
{
bind[j].loadu(skin->mInvBindMatrix[j]);
world[j].loadu(joint->getWorldMatrix());
matMul(bind[j], world[j], mat[j]);
}
else
{
mat[j].loadu(skin->mInvBindMatrix[j]);
S32 joint_num = skin->mJointNums[j];
LLJoint * joint = NULL;
if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)
{
joint = avatar->getJoint(joint_num);
}
if (joint)
{
bind[j].loadu(skin->mInvBindMatrix[j]);
world[j].loadu(joint->getWorldMatrix());
matMul(bind[j], world[j], mat[j]);
}
else
{
mat[j].loadu(skin->mInvBindMatrix[j]);
#if DEBUG_SKINNING
// This shouldn't happen - in mesh upload, skinned
// rendering should be disabled unless all joints are
// valid. In other cases of skinned rendering, invalid
// joints should already have been removed during scrubInvalidJoints().
// Beq note - Oct 2018 Animesh - Many rigged meshes still fail here. ('mElbowLeeft' typo in the rigging data)
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " rigged to invalid joint name " << skin->mJointNames[j]
<< " num " << skin->mJointNums[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " avatar build state: isBuilt() " << avatar->isBuilt()
<< " mInitFlags " << avatar->mInitFlags << LL_ENDL;
// This shouldn't happen - in mesh upload, skinned
// rendering should be disabled unless all joints are
// valid. In other cases of skinned rendering, invalid
// joints should already have been removed during scrubInvalidJoints().
// Beq note - Oct 2018 Animesh - Many rigged meshes still fail here. ('mElbowLeeft' typo in the rigging data)
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " rigged to invalid joint name " << skin->mJointNames[j]
<< " num " << skin->mJointNums[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " avatar build state: isBuilt() " << avatar->isBuilt()
<< " mInitFlags " << avatar->mInitFlags << LL_ENDL;
#endif
}
}
//LL_DEBUGS("Skinning") << "[" << avatar->getFullname() << "] joint(" << skin->mJointNames[j] << ") matices bind(" << bind << ") world(" << world << ")" << LL_ENDL;
}
}
@ -232,7 +242,7 @@ void LLSkinningUtil::initSkinningMatrixPalette(
void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
{
#if DEBUG_SKINNING
const S32 max_joints = skin->mJointNames.size();
const S32 max_joints = skin->mJointNames.size();
for (U32 j=0; j<num_vertices; j++)
{
F32 *w = weights[j].getF32ptr();
@ -406,7 +416,7 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
}
for (U32 k=0; k<4; ++k)
{
S32 joint_index = idx[k];
S32 joint_index = idx[k];
if (wght[k] > 0.0f && num_joints > joint_index)
{
S32 joint_num = skin->mJointNums[joint_index];

View File

@ -4552,11 +4552,6 @@ bool process_login_success_response(U32 &first_sim_size_x, U32 &first_sim_size_y
}
// Request the map server url
// Non-agni grids have a different default location.
if (LLGridManager::getInstance()->isInSLBeta())
{
gSavedSettings.setString("MapServerURL", "http://test.map.secondlife.com.s3.amazonaws.com/");
}
std::string map_server_url = response["map-server-url"];
if(!map_server_url.empty())
{

View File

@ -50,8 +50,8 @@
/// LLViewerAssetRequest
///----------------------------------------------------------------------------
// There is also PoolSizeVAssetStorage value in setting that should mirror this name
static const std::string VIEWER_ASSET_STORAGE_CORO_POOL = "VAssetStorage";
// There is also PoolSizeAssetStorage value in setting that should mirror this name
static const std::string VIEWER_ASSET_STORAGE_CORO_POOL = "AssetStorage";
/**
* @brief Local class to encapsulate asset fetch requests with a timestamp.
@ -134,6 +134,14 @@ LLViewerAssetStorage::~LLViewerAssetStorage()
// This class has dedicated coroutine pool, clean it up, otherwise coroutines will crash later.
LLCoprocedureManager::instance().close(VIEWER_ASSET_STORAGE_CORO_POOL);
}
while (mCoroWaitList.size() > 0)
{
CoroWaitList &request = mCoroWaitList.front();
// Clean up pending downloads, delete request and trigger callbacks
removeAndCallbackPendingDownloads(request.mId, request.mType, request.mId, request.mType, LL_ERR_NOERR, LLExtStat::NONE);
mCoroWaitList.pop_front();
}
}
// virtual
@ -342,6 +350,29 @@ void LLViewerAssetStorage::storeAssetData(
}
}
void LLViewerAssetStorage::checkForTimeouts()
{
LLAssetStorage::checkForTimeouts();
// Restore requests
LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
while (mCoroWaitList.size() > 0
&& manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
{
CoroWaitList &request = mCoroWaitList.front();
// <FS:Ansariel> [UDP Assets]
//bool with_http = true;
//bool is_temp = false;
//LLViewerAssetStatsFF::record_enqueue(request.mType, with_http, is_temp);
// </FS:Ansariel> [UDP Assets]
manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, request.mRequest, request.mId, request.mType, request.mCallback, request.mUserData));
mCoroWaitList.pop_front();
}
}
/**
* @brief Allocate and queue an asset fetch request for the viewer
@ -399,14 +430,22 @@ void LLViewerAssetStorage::queueRequestHttp(
// This is the same as the current UDP logic - don't re-request a duplicate.
if (!duplicate)
{
// <FS:Ansariel> [UDP Assets]
//bool with_http = true;
//bool is_temp = false;
//LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
// <FS:Ansariel> [UDP Assets]
// Coroutine buffer has fixed size (synchronization buffer, so we have no alternatives), so buffer any request above limit
if (LLCoprocedureManager::instance().count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
{
// <FS:Ansariel> [UDP Assets]
//bool with_http = true;
//bool is_temp = false;
//LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
// </FS:Ansariel> [UDP Assets]
LLCoprocedureManager::instance().enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL,"LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
LLCoprocedureManager::instance().enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
}
else
{
mCoroWaitList.emplace_back(req, uuid, atype, callback, user_data);
}
}
}

View File

@ -43,7 +43,7 @@ public:
~LLViewerAssetStorage();
virtual void storeAssetData(
void storeAssetData(
const LLTransactionID& tid,
LLAssetType::EType atype,
LLStoreAssetCallback callback,
@ -52,9 +52,9 @@ public:
bool is_priority = false,
bool store_local = false,
bool user_waiting=FALSE,
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
virtual void storeAssetData(
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) override;
void storeAssetData(
const std::string& filename,
const LLTransactionID& tid,
LLAssetType::EType type,
@ -63,16 +63,17 @@ public:
bool temp_file = false,
bool is_priority = false,
bool user_waiting=FALSE,
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) override;
void checkForTimeouts() override;
protected:
// virtual
void _queueDataRequest(const LLUUID& uuid,
LLAssetType::EType type,
LLGetAssetCallback callback,
void *user_data,
BOOL duplicate,
BOOL is_priority);
BOOL is_priority) override;
void queueRequestHttp(const LLUUID& uuid,
LLAssetType::EType type,
@ -91,8 +92,35 @@ protected:
std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype);
void logAssetStorageInfo();
void logAssetStorageInfo() override;
// Asset storage works through coroutines and coroutines have limited queue capacity
// This class is meant to temporary store requests when fiber's queue is full
class CoroWaitList
{
public:
CoroWaitList(LLViewerAssetRequest *req,
const LLUUID& uuid,
LLAssetType::EType atype,
LLGetAssetCallback &callback,
void *user_data)
: mRequest(req),
mId(uuid),
mType(atype),
mCallback(callback),
mUserData(user_data)
{
}
LLViewerAssetRequest* mRequest;
LLUUID mId;
LLAssetType::EType mType;
LLGetAssetCallback mCallback;
void *mUserData;
};
typedef std::list<CoroWaitList> wait_list_t;
wait_list_t mCoroWaitList;
std::string mViewerAssetUrl;
S32 mAssetCoroCount;
S32 mCountRequests;

View File

@ -6625,7 +6625,7 @@ class LLToolsSelectNextPartFace : public view_listener_t
new_te = to_select->getNumTEs() - 1;
}
}
LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, FALSE);
LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te);
}
else
{

View File

@ -136,7 +136,7 @@ void LLGridManager::initialize(const std::string& grid_file)
"https://secondlife.aditi.lindenlab.com/helpers/",
DEFAULT_LOGIN_PAGE,
SL_UPDATE_QUERY_URL,
"https://my.aditi.lindenlab.com/",
"https://my.secondlife-beta.com/",
"Aditi");
// dump example grid file...

View File

@ -5034,22 +5034,78 @@ void LLViewerObject::refreshBakeTexture()
}
}
void LLViewerObject::updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture)
{
// Objects getting non-alpha texture and alpha mask can result in graphical bugs, like white or red alphas.
// To resolve the issue this function provides image format to material and based on format material's
// getDiffuseAlphaModeRender() function will decide what value to provide to render
//
// Unfortunately LLMaterial has no access to diffuse image, so we have to set this data in LLViewerObject
// regardles of object being used/seen or frequency of image-updates.
mat->setDiffuseBaked(baked_texture);
if (!baked_texture)
{
if (imagep->isMissingAsset())
{
mat->setDiffuseFormatPrimary(0);
}
else if (0 == imagep->getPrimaryFormat())
{
// We don't have information about this texture, wait for it
mWaitingTextureInfo.insert(uuid_material_mmap_t::value_type(imagep->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
// Temporary assume RGBA image
mat->setDiffuseFormatPrimary(GL_RGBA);
}
else
{
mat->setDiffuseFormatPrimary(imagep->getPrimaryFormat());
}
}
}
S32 LLViewerObject::setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep)
{
LLUUID new_id = imagep->getID();
S32 retval = LLPrimitive::setTETexture(te, new_id);
LLTextureEntry* tep = getTE(te);
LLUUID old_image_id = tep->getID();
LLViewerTexture* baked_texture = getBakedTextureForMagicId(new_id);
mTEImages[te] = baked_texture ? baked_texture : imagep;
updateAvatarMeshVisibility(new_id, old_image_id);
LLMaterial* mat = tep->getMaterialParams();
if (mat)
{
// Don't update format from texture (and don't shedule one) if material has no alpha mode set,
// just assume RGBA format, format will get updated with setTEMaterialParams call if mode changes
if (mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
{
bool baked = baked_texture != NULL;
updateDiffuseMatParams(te, mat, imagep, baked);
}
else
{
mat->setDiffuseFormatPrimary(GL_RGBA);
}
}
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
return retval;
}
void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
{
if (mTEImages[te] != imagep)
{
LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null;
LLPrimitive::setTETexture(te, imagep->getID());
LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID());
mTEImages[te] = baked_texture ? baked_texture : imagep;
updateAvatarMeshVisibility(imagep->getID(), old_image_id);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
setDiffuseImageAndParams(te, imagep);
}
}
@ -5061,15 +5117,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image)
if (uuid != getTEref(te).getID() ||
uuid == LLUUID::null)
{
retval = LLPrimitive::setTETexture(te, uuid);
LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid);
mTEImages[te] = baked_texture ? baked_texture : image;
updateAvatarMeshVisibility(uuid,old_image_id);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
gPipeline.markTextured(mDrawable);
}
retval = setDiffuseImageAndParams(te, image);
}
return retval;
}
@ -5364,6 +5412,29 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return 0;
}
if (pMaterialParams.notNull()
&& pMaterialParams->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
{
// Don't update if no alpha is set. If alpha changes, this function will run again,
// no point in sheduling additional texture callbacks (in updateDiffuseMatParams)
LLTextureEntry* tex_entry = getTE(te);
bool is_baked = tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID());
LLViewerTexture *img_diffuse = getTEImage(te);
llassert(NULL != img_diffuse);
if (NULL != img_diffuse)
{
// Will modify alpha mask provided to renderer to fit image
updateDiffuseMatParams(te, pMaterialParams.get(), img_diffuse, is_baked);
}
else
{
LLMaterial *mat = pMaterialParams.get(); // to avoid const
mat->setDiffuseFormatPrimary(0);
}
}
retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
LL_DEBUGS("Material") << "Changing material params for te " << (S32)te
<< ", object " << mID
@ -5376,6 +5447,84 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return retval;
}
bool LLViewerObject::notifyAboutCreatingTexture(LLViewerTexture *texture)
{
// Confirmation about texture creation, check wait-list
// and make changes, or return false
std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
bool refresh_materials = false;
// RGB textures without alpha channels won't work right with alpha,
// we provide format to material for material to decide when to drop alpha
for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.notNull()
&& LLRender::DIFFUSE_MAP == range_it->second.map)
{
U32 format = texture->getPrimaryFormat();
if (format != cur_material->getDiffuseFormatPrimary())
{
cur_material->setDiffuseFormatPrimary(format);
refresh_materials = true;
}
}
} //for
if (refresh_materials)
{
LLViewerObject::refreshMaterials();
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return refresh_materials;
}
bool LLViewerObject::notifyAboutMissingAsset(LLViewerTexture *texture)
{
// When waiting information about texture it turned out to be missing.
// Confirm the state, update values accordingly
std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
if (range.first == range.second) return false;
bool refresh_materials = false;
for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.isNull())
continue;
if (range_it->second.map == LLRender::DIFFUSE_MAP)
{
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
if (cur_material.notNull()
&& LLRender::DIFFUSE_MAP == range_it->second.map)
{
if (0 != cur_material->getDiffuseFormatPrimary())
{
cur_material->setDiffuseFormatPrimary(0);
refresh_materials = true;
}
}
}
} //for
if (refresh_materials)
{
LLViewerObject::refreshMaterials();
}
//clear wait-list
mWaitingTextureInfo.erase(range.first, range.second);
return refresh_materials;
}
void LLViewerObject::refreshMaterials()
{
setChanged(TEXTURE);

Some files were not shown because too many files have changed in this diff Show More