diff options
151 files changed, 2793 insertions, 3598 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 5667b69c28..a74cf32afa 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -25,6 +25,7 @@ Aimee Trescothick VWR-3903 VWR-4083 VWR-4106 + VWR-5308 VWR-6348 VWR-6358 VWR-6360 @@ -252,6 +253,7 @@ Gigs Taggart VWR-2491 VWR-2502 VWR-2331 + VWR-5308 VWR-8781 VWR-8783 Ginko Bayliss diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index b92ccd1d77..9f4c108dff 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -548,12 +548,11 @@ void LLAudioEngine::enableWind(bool enable) { if (enable && (!mEnableWind)) { - initWind(); - mEnableWind = enable; + mEnableWind = initWind(); } else if (mEnableWind && (!enable)) { - mEnableWind = enable; + mEnableWind = false; cleanupWind(); } } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index d287104204..5876cef4ea 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -195,7 +195,7 @@ protected: virtual LLAudioBuffer *createBuffer() = 0; virtual LLAudioChannel *createChannel() = 0; - virtual void initWind() = 0; + virtual bool initWind() = 0; virtual void cleanupWind() = 0; virtual void setInternalGain(F32 gain) = 0; diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp index d7f58defca..7a8a04afa1 100644 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ b/indra/llaudio/llaudioengine_fmod.cpp @@ -54,13 +54,12 @@ extern "C" { void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); } -FSOUND_DSPUNIT *gWindDSP = NULL; - LLAudioEngine_FMOD::LLAudioEngine_FMOD() { mInited = false; mWindGen = NULL; + mWindDSP = NULL; } @@ -258,10 +257,10 @@ void LLAudioEngine_FMOD::allocateListener(void) void LLAudioEngine_FMOD::shutdown() { - if (gWindDSP) + if (mWindDSP) { - FSOUND_DSP_SetActive(gWindDSP,false); - FSOUND_DSP_Free(gWindDSP); + FSOUND_DSP_SetActive(mWindDSP,false); + FSOUND_DSP_Free(mWindDSP); } stopInternetStream(); @@ -289,29 +288,66 @@ LLAudioChannel * LLAudioEngine_FMOD::createChannel() } -void LLAudioEngine_FMOD::initWind() +bool LLAudioEngine_FMOD::initWind() { - mWindGen = new LLWindGen<MIXBUFFERFORMAT>; + if (!mWindGen) + { + bool enable; + + switch (FSOUND_GetMixer()) + { + case FSOUND_MIXER_MMXP5: + case FSOUND_MIXER_MMXP6: + case FSOUND_MIXER_QUALITY_MMXP5: + case FSOUND_MIXER_QUALITY_MMXP6: + enable = (typeid(MIXBUFFERFORMAT) == typeid(S16)); + break; + case FSOUND_MIXER_BLENDMODE: + enable = (typeid(MIXBUFFERFORMAT) == typeid(S32)); + break; + case FSOUND_MIXER_QUALITY_FPU: + enable = (typeid(MIXBUFFERFORMAT) == typeid(F32)); + break; + default: + // FSOUND_GetMixer() does not return a valid mixer type on Darwin + LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL; + enable = true; + break; + } + + if (enable) + { + mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate()); + } + else + { + LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL; + } + } + + mNextWindUpdate = 0.0; - if (!gWindDSP) + if (mWindGen && !mWindDSP) { - gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); + mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); } - if (gWindDSP) + if (mWindDSP) { - FSOUND_DSP_SetActive(gWindDSP, true); + FSOUND_DSP_SetActive(mWindDSP, true); + return true; } - mNextWindUpdate = 0.0; + + return false; } void LLAudioEngine_FMOD::cleanupWind() { - if (gWindDSP) + if (mWindDSP) { - FSOUND_DSP_SetActive(gWindDSP, false); - FSOUND_DSP_Free(gWindDSP); - gWindDSP = NULL; + FSOUND_DSP_SetActive(mWindDSP, false); + FSOUND_DSP_Free(mWindDSP); + mWindDSP = NULL; } delete mWindGen; @@ -740,30 +776,12 @@ void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int len // originalbuffer = fmod's original mixbuffer. // newbuffer = the buffer passed from the previous DSP unit. // length = length in samples at this mix time. - // param = user parameter passed through in FSOUND_DSP_Create. - // - // modify the buffer in some fashion + // userdata = user parameter passed through in FSOUND_DSP_Create. LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen = (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata; - U8 stride; - -#if LL_DARWIN - stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT); -#else - int mixertype = FSOUND_GetMixer(); - if (mixertype == FSOUND_MIXER_BLENDMODE || - mixertype == FSOUND_MIXER_QUALITY_FPU) - { - stride = 4; - } - else - { - stride = 2; - } -#endif - - newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride); + + newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length); return newbuffer; } diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmod.h index 3968657cba..0e386a3884 100644 --- a/indra/llaudio/llaudioengine_fmod.h +++ b/indra/llaudio/llaudioengine_fmod.h @@ -55,15 +55,15 @@ public: virtual void shutdown(); - /*virtual*/ void initWind(); + /*virtual*/ bool initWind(); /*virtual*/ void cleanupWind(); /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); #if LL_DARWIN - typedef S32 MIXBUFFERFORMAT; + typedef S32 MIXBUFFERFORMAT; #else - typedef S16 MIXBUFFERFORMAT; + typedef S16 MIXBUFFERFORMAT; #endif protected: @@ -83,6 +83,7 @@ protected: void* mUserData; LLWindGen<MIXBUFFERFORMAT> *mWindGen; + FSOUND_DSPUNIT *mWindDSP; }; diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index a5982ccbd6..887c791790 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -370,7 +370,7 @@ U32 LLAudioBufferOpenAL::getLength() // ------------ -void LLAudioEngine_OpenAL::initWind() +bool LLAudioEngine_OpenAL::initWind() { ALenum error; llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; @@ -397,10 +397,12 @@ void LLAudioEngine_OpenAL::initWind() if(mWindBuf==NULL) { llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; - mEnableWind=false; + return false; } llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; + + return true; } void LLAudioEngine_OpenAL::cleanupWind() @@ -508,14 +510,14 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) alGenBuffers(1,&buffer); if((error=alGetError()) != AL_NO_ERROR) { - llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; + llwarns << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << error << llendl; break; } alBufferData(buffer, AL_FORMAT_STEREO16, mWindGen->windGenerate(mWindBuf, - mWindBufSamples, 2), + mWindBufSamples), mWindBufBytes, mWindBufFreq); error = alGetError(); diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h index 5aca03e195..16125b2476 100644 --- a/indra/llaudio/llaudioengine_openal.h +++ b/indra/llaudio/llaudioengine_openal.h @@ -57,23 +57,23 @@ class LLAudioEngine_OpenAL : public LLAudioEngine LLAudioBuffer* createBuffer(); LLAudioChannel* createChannel(); - /*virtual*/ void initWind(); + /*virtual*/ bool initWind(); /*virtual*/ void cleanupWind(); /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); private: void * windDSP(void *newbuffer, int length); - typedef S16 WIND_SAMPLE_T; - LLWindGen<WIND_SAMPLE_T> *mWindGen; - S16 *mWindBuf; - U32 mWindBufFreq; - U32 mWindBufSamples; - U32 mWindBufBytes; - ALuint mWindSource; - int mNumEmptyWindALBuffers; - - static const int MAX_NUM_WIND_BUFFERS = 80; - static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec + typedef S16 WIND_SAMPLE_T; + LLWindGen<WIND_SAMPLE_T> *mWindGen; + S16 *mWindBuf; + U32 mWindBufFreq; + U32 mWindBufSamples; + U32 mWindBufBytes; + ALuint mWindSource; + int mNumEmptyWindALBuffers; + + static const int MAX_NUM_WIND_BUFFERS = 80; + static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec }; class LLAudioChannelOpenAL : public LLAudioChannel diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h index 847bfa6e9d..1908b2545f 100644 --- a/indra/llaudio/llwindgen.h +++ b/indra/llaudio/llwindgen.h @@ -33,104 +33,149 @@ #define WINDGEN_H #include "llcommon.h" -#include "llrand.h" template <class MIXBUFFERFORMAT_T> class LLWindGen { public: - LLWindGen() : + LLWindGen(const U32 sample_rate = 44100) : mTargetGain(0.f), mTargetFreq(100.f), mTargetPanGainR(0.5f), - mbuf0(0.0), - mbuf1(0.0), - mbuf2(0.0), - mbuf3(0.0), - mbuf4(0.0), - mbuf5(0.0), - mY0(0.0), - mY1(0.0), + mInputSamplingRate(sample_rate), + mSubSamples(2), + mFilterBandWidth(50.f), + mBuf0(0.0f), + mBuf1(0.0f), + mBuf2(0.0f), + mY0(0.0f), + mY1(0.0f), mCurrentGain(0.f), mCurrentFreq(100.f), - mCurrentPanGainR(0.5f) {}; - - static const U32 getInputSamplingRate() {return mInputSamplingRate;} + mCurrentPanGainR(0.5f) + { + mSamplePeriod = (F32)mSubSamples / (F32)mInputSamplingRate; + mB2 = expf(-F_TWO_PI * mFilterBandWidth * mSamplePeriod); + } + const U32 getInputSamplingRate() { return mInputSamplingRate; } + // newbuffer = the buffer passed from the previous DSP unit. // numsamples = length in samples-per-channel at this mix time. - // stride = number of bytes between start of each sample. // NOTE: generates L/R interleaved stereo - MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride) + MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples) { - U8 *cursamplep = (U8*)newbuffer; + MIXBUFFERFORMAT_T *cursamplep = newbuffer; + + // Filter coefficients + F32 a0 = 0.0f, b1 = 0.0f; - double bandwidth = 50.0F; - double a0,b1,b2; + // No need to clip at normal volumes + bool clip = mCurrentGain > 2.0f; - // calculate resonant filter coeffs - b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate)); + bool interp_freq = false; - while (numsamples--) + //if the frequency isn't changing much, we don't need to interpolate in the inner loop + if (llabs(mTargetFreq - mCurrentFreq) < (mCurrentFreq * 0.112)) { - mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq)); - mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain)); - mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR)); - b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate)); - a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); - double nextSample; + // calculate resonant filter coefficients + mCurrentFreq = mTargetFreq; + b1 = (-4.0f * mB2) / (1.0f + mB2) * cosf(F_TWO_PI * (mCurrentFreq * mSamplePeriod)); + a0 = (1.0f - mB2) * sqrtf(1.0f - (b1 * b1) / (4.0f * mB2)); + } + else + { + interp_freq = true; + } + + while (numsamples) + { + F32 next_sample; + + // Start with white noise + // This expression is fragile, rearrange it and it will break! + next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); - // start with white noise - nextSample = ll_frand(2.0f) - 1.0f; + // Apply a pinking filter + // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ + mBuf0 = mBuf0 * 0.99765f + next_sample * 0.0990460f; + mBuf1 = mBuf1 * 0.96300f + next_sample * 0.2965164f; + mBuf2 = mBuf2 * 0.57000f + next_sample * 1.0526913f; - // apply pinking filter - mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample; - mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample; - mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample; - mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample; - mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample; - mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample; + next_sample = mBuf0 + mBuf1 + mBuf2 + next_sample * 0.1848f; - nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5; + if (interp_freq) + { + // calculate and interpolate resonant filter coefficients + mCurrentFreq = (0.999f * mCurrentFreq) + (0.001f * mTargetFreq); + b1 = (-4.0f * mB2) / (1.0f + mB2) * cosf(F_TWO_PI * (mCurrentFreq * mSamplePeriod)); + a0 = (1.0f - mB2) * sqrtf(1.0f - (b1 * b1) / (4.0f * mB2)); + } - // do a resonant filter on the noise - nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 ); + // Apply a resonant low-pass filter on the pink noise + next_sample = a0 * next_sample - b1 * mY0 - mB2 * mY1; mY1 = mY0; - mY0 = nextSample; + mY0 = next_sample; - nextSample *= mCurrentGain; + mCurrentGain = (0.999f * mCurrentGain) + (0.001f * mTargetGain); + mCurrentPanGainR = (0.999f * mCurrentPanGainR) + (0.001f * mTargetPanGainR); - MIXBUFFERFORMAT_T sample; + // For a 3dB pan law use: + // next_sample *= mCurrentGain * ((mCurrentPanGainR*(mCurrentPanGainR-1)*1.652+1.413); + next_sample *= mCurrentGain; - sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f); - *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); - cursamplep += stride; - - sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f); - *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); - cursamplep += stride; + // delta is used to interpolate between synthesized samples + F32 delta = (next_sample - mLastSample) / (F32)mSubSamples; + + // Fill the audio buffer, clipping if necessary + for (U8 i=mSubSamples; i && numsamples; --i, --numsamples) + { + mLastSample = mLastSample + delta; + S32 sample_right = (S32)(mLastSample * mCurrentPanGainR); + S32 sample_left = (S32)mLastSample - sample_right; + + if (!clip) + { + *cursamplep = (MIXBUFFERFORMAT_T)sample_left; + ++cursamplep; + *cursamplep = (MIXBUFFERFORMAT_T)sample_right; + ++cursamplep; + } + else + { + *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX); + ++cursamplep; + *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX); + ++cursamplep; + } + } } return newbuffer; } - + +public: F32 mTargetGain; F32 mTargetFreq; F32 mTargetPanGainR; - + private: - static const U32 mInputSamplingRate = 44100; - F64 mbuf0; - F64 mbuf1; - F64 mbuf2; - F64 mbuf3; - F64 mbuf4; - F64 mbuf5; - F64 mY0; - F64 mY1; + U32 mInputSamplingRate; + U8 mSubSamples; + F32 mSamplePeriod; + F32 mFilterBandWidth; + F32 mB2; + + F32 mBuf0; + F32 mBuf1; + F32 mBuf2; + F32 mY0; + F32 mY1; + F32 mCurrentGain; F32 mCurrentFreq; F32 mCurrentPanGainR; + F32 mLastSample; }; #endif diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3c689930b8..527ab42fc9 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -232,7 +232,6 @@ set(llcommon_HEADER_FILES metaclasst.h metaproperty.h metapropertyt.h - processor.h reflective.h reflectivet.h roles_constants.h @@ -290,6 +289,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index f39a4e6619..20727dd76e 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -238,7 +238,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer #else // windows or x86-mac or x86-linux or x86-solaris U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { - static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50)); + static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()); // we drop the low-order byte in our timers, so report a lower frequency return sCPUClockFrequency >> 8; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index f6ab55a6b5..98c9eabcd6 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -30,139 +30,385 @@ * $/LicenseInfo$ */ -// Filename: Processor.cpp -// ======================= -// Author: Benjamin Jurke -// File history: 27.02.2002 - File created. Support for Intel and AMD processors -// 05.03.2002 - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID -// command is not available -// - The CProcessor::WriteInfoTextFile function do not -// longer use Win32 file functions (-> os independend) -// - Optional include of the windows.h header which is -// still need for CProcessor::GetCPUFrequency. -// 06.03.2002 - My birthday (18th :-)) -// - Replaced the '\r\n' line endings in function -// CProcessor::CPUInfoToText by '\n' -// - Replaced unsigned __int64 by signed __int64 for -// solving some compiler conversion problems -// - Fixed a bug at family=6, model=6 (Celeron -> P2) -////////////////////////////////////////////////////////////////////////////////// - #include "linden_common.h" +#include "llprocessor.h" -#include "processor.h" +#include "llerror.h" -#include <memory> +//#include <memory> #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include <winsock2.h> # include <windows.h> +# include <intrin.h> #endif -#if LL_LINUX -#include "llsys.h" -#endif // LL_LINUX +#include "llsd.h" + +#if LL_MSVC && _M_X64 +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_MSVC && _M_IX86 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__i386__) ) +# define LL_X86 1 +#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) +# define LL_PPC 1 +#endif + +class LLProcessorInfoImpl; // foward declaration for the mImpl; + +namespace +{ + enum cpu_info + { + eBrandName = 0, + eFrequency, + eVendor, + eStepping, + eFamily, + eExtendedFamily, + eModel, + eExtendedModel, + eType, + eBrandID, + eFamilyName + }; + + + const char* cpu_info_names[] = + { + "Processor Name", + "Frequency", + "Vendor", + "Stepping", + "Family", + "Extended Family", + "Model", + "Extended Model", + "Type", + "Brand ID", + "Family Name" + }; + + enum cpu_config + { + eMaxID, + eMaxExtID, + eCLFLUSHCacheLineSize, + eAPICPhysicalID, + eCacheLineSize, + eL2Associativity, + eCacheSizeK, + eFeatureBits, + eExtFeatureBits + }; + + const char* cpu_config_names[] = + { + "Max Supported CPUID level", + "Max Supported Ext. CPUID level", + "CLFLUSH cache line size", + "APIC Physical ID", + "Cache Line Size", + "L2 Associativity", + "Cache Size", + "Feature Bits", + "Ext. Feature Bits" + }; -#if !LL_DARWIN && !LL_SOLARIS -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -// We need the QueryPerformanceCounter and Sleep functions -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE -#endif + // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32. + // The rest of the names are referenced by bit maks returned from cpuid. + enum cpu_features + { + eSSE_Ext=25, + eSSE2_Ext=26, + + eSSE3_Features=32, + eMONTIOR_MWAIT=33, + eCPLDebugStore=34, + eThermalMonitor2=35, + eAltivec=36 + }; -// Some macros we often need -//////////////////////////// -#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false) + const char* cpu_feature_names[] = + { + "x87 FPU On Chip", + "Virtual-8086 Mode Enhancement", + "Debugging Extensions", + "Page Size Extensions", + "Time Stamp Counter", + "RDMSR and WRMSR Support", + "Physical Address Extensions", + "Machine Check Exception", + "CMPXCHG8B Instruction", + "APIC On Chip", + "Unknown1", + "SYSENTER and SYSEXIT", + "Memory Type Range Registers", + "PTE Global Bit", + "Machine Check Architecture", + "Conditional Move/Compare Instruction", + "Page Attribute Table", + "Page Size Extension", + "Processor Serial Number", + "CFLUSH Extension", + "Unknown2", + "Debug Store", + "Thermal Monitor and Clock Ctrl", + "MMX Technology", + "FXSAVE/FXRSTOR", + "SSE Extensions", + "SSE2 Extensions", + "Self Snoop", + "Hyper-threading Technology", + "Thermal Monitor", + "Unknown4", + "Pend. Brk. EN.", // 31 End of FeatureInfo bits + + "SSE3 New Instructions", // 32 + "MONITOR/MWAIT", + "CPL Qualified Debug Store", + "Thermal Monitor 2", + + "Altivec" + }; + + std::string intel_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 3: return "Intel i386"; + case 4: return "Intel i486"; + case 5: return "Intel Pentium"; + case 6: return "Intel Pentium Pro/2/3, Core"; + case 7: return "Intel Itanium (IA-64)"; + case 0xF: return "Intel Pentium 4"; + case 0x10: return "Intel Itanium 2 (IA-64)"; + } + return "Unknown"; + } + + std::string amd_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 4: return "AMD 80486/5x86"; + case 5: return "AMD K5/K6"; + case 6: return "AMD K7"; + case 0xF: return "AMD K8"; + case 0x10: return "AMD K8L"; + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + U32 composed_family = family + ext_family; + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + U32 composed_family = (family == 0xF) + ? family + ext_family + : family; + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + +} // end unnamed namespace + +// The base class for implementations. +// Each platform should override this class. +class LLProcessorInfoImpl +{ +public: + LLProcessorInfoImpl() + { + mProcessorInfo["info"] = LLSD::emptyMap(); + mProcessorInfo["config"] = LLSD::emptyMap(); + mProcessorInfo["extension"] = LLSD::emptyMap(); + } + virtual ~LLProcessorInfoImpl() {} + + F64 getCPUFrequency() const + { + return getInfo(eFrequency, 0).asReal(); + } + + bool hasSSE() const + { + return hasExtension(cpu_feature_names[eSSE_Ext]); + } + + bool hasSSE2() const + { + return hasExtension(cpu_feature_names[eSSE2_Ext]); + } + + bool hasAltivec() const + { + return hasExtension("Altivec"); + } + + std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } + std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } + + // This is virtual to support a different linux format. + // *NOTE:Mani - I didn't want to screw up server use of this data... + virtual std::string getCPUFeatureDescription() const + { + std::ostringstream out; + out << std::endl << std::endl; + out << "// CPU General Information" << std::endl; + out << "//////////////////////////" << std::endl; + out << "Processor Name: " << getCPUBrandName() << std::endl; + out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl; + out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl; + out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl; + out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl; + out << "Model: " << getInfo(eModel, 0) << std::endl; + out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl; + out << "Type: " << getInfo(eType, 0) << std::endl; + out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl; + out << std::endl; + out << "// CPU Configuration" << std::endl; + out << "//////////////////////////" << std::endl; + + // Iterate through the dictionary of configuration options. + LLSD configs = mProcessorInfo["config"]; + for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr) + { + out << cfgItr->first << " = " << cfgItr->second << std::endl; + } + out << std::endl; + + out << "// CPU Extensions" << std::endl; + out << "//////////////////////////" << std::endl; + + for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr) + { + out << " " << itr->first << std::endl; + } + return out.str(); + } + +protected: + void setInfo(cpu_info info_type, const LLSD& value) + { + setInfo(cpu_info_names[info_type], value); + } + LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const + { + return getInfo(cpu_info_names[info_type], defaultVal); + } + + void setConfig(cpu_config config_type, const LLSD& value) + { + setConfig(cpu_config_names[config_type], value); + } + LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const + { + return getConfig(cpu_config_names[config_type], defaultVal); + } + + void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } + bool hasExtension(const std::string& name) const + { + return mProcessorInfo["extension"].has(name); + } + +private: + void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } + LLSD getInfo(const std::string& name, const LLSD& defaultVal) const + { + if(mProcessorInfo["info"].has(name)) + { + return mProcessorInfo["info"][name]; + } + return defaultVal; + } + void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } + LLSD getConfig(const std::string& name, const LLSD& defaultVal) const + { + LLSD r = mProcessorInfo["config"].get(name); + return r.isDefined() ? r : defaultVal; + } + +private: + + LLSD mProcessorInfo; +}; + + +#ifdef LL_MSVC +// LL_MSVC and not LLWINDOWS because some of the following code +// uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE // Delays for the specified amount of milliseconds -static void _Delay(unsigned int ms) +static void _Delay(unsigned int ms) { - LARGE_INTEGER freq, c1, c2; - __int64 x; + LARGE_INTEGER freq, c1, c2; + __int64 x; - // Get High-Res Timer frequency + // Get High-Res Timer frequency if (!QueryPerformanceFrequency(&freq)) return; - + // Convert ms to High-Res Timer value x = freq.QuadPart/1000*ms; - // Get first snapshot of High-Res Timer value + // Get first snapshot of High-Res Timer value QueryPerformanceCounter(&c1); do { - // Get second snapshot - QueryPerformanceCounter(&c2); + // Get second snapshot + QueryPerformanceCounter(&c2); }while(c2.QuadPart-c1.QuadPart < x); // Loop while (second-first < x) } -#endif - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to measure the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) +static F64 calculate_cpu_frequency(U32 measure_msecs) { -#if LL_LINUX - // use the shinier LLCPUInfo interface - return 1000000.0F * gSysCPU.getMHz(); -#endif - -#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE - return 0; -#else - // If there are invalid measure time parameters, zero msecs for example, - // we've to exit the function - if (uiMeasureMSecs < 1) + if(measure_msecs == 0) { - // If theres already a measured frequency available, we return it - if (uqwFrequency > 0) - return uqwFrequency; - else - return 0; - } - - // Now we check if the CPUID command is available - if (!CheckCPUIDPresence()) return 0; - - // First we get the CPUID standard level 0x00000001 - unsigned long reg; - __asm - { - mov eax, 1 - cpuid - mov reg, edx } - // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available. - // This function is necessary for our measure process. - if (!(reg & (1 << 4))) - return 0; - // After that we declare some vars and check the frequency of the high // resolution timer for the measure process. - // If there's no high-res timer, we exit. - __int64 starttime, endtime, timedif, freq, start, end, dif; + // If there"s no high-res timer, we exit. + unsigned __int64 starttime, endtime, timedif, freq, start, end, dif; if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) + { return 0; + } // Now we can init the measure process. We set the process and thread priority // to the highest available level (Realtime priority). Also we focus the @@ -178,35 +424,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); SetProcessAffinityMask(hProcess, dwNewMask); - // Now we call a CPUID to ensure, that all other prior called functions are - // completed now (serialization) - __asm cpuid + //// Now we call a CPUID to ensure, that all other prior called functions are + //// completed now (serialization) + //__asm cpuid + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); // We ask the high-res timer for the start time QueryPerformanceCounter((LARGE_INTEGER *) &starttime); // Then we get the current cpu clock and store it - __asm - { - rdtsc - mov dword ptr [start+4], edx - mov dword ptr [start], eax - } + start = __rdtsc(); // Now we wart for some msecs - _Delay(uiMeasureMSecs); -// Sleep(uiMeasureMSecs); + _Delay(measure_msecs); + // Sleep(uiMeasureMSecs); // We ask for the end time QueryPerformanceCounter((LARGE_INTEGER *) &endtime); // And also for the end cpu clock - __asm - { - rdtsc - mov dword ptr [end+4], edx - mov dword ptr [end], eax - } + end = __rdtsc(); // Now we can restore the default process and thread priorities SetProcessAffinityMask(hProcess, dwProcessMask); @@ -219,2075 +457,433 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) // And finally the frequency is the clock difference divided by the time // difference. - uqwFrequency = (F64)dif / (((F64)timedif) / freq); + F64 frequency = (F64)dif / (((F64)timedif) / freq); // At last we just return the frequency that is also stored in the call - // member var uqwFrequency - return uqwFrequency; -#endif + // member var uqwFrequency - converted to MHz + return frequency / (F64)1000000; } -// bool CProcessor::AnalyzeIntelProcessor() -// ======================================== -// Private class function for analyzing an Intel processor -////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeIntelProcessor() +// Windows implementation +class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl { -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, edxreg; - - // First we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // Now we get the CPUID standard level 0x00000001 - __asm +public: + LLProcessorInfoWindowsImpl() { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx + getCPUIDInfo(); + setInfo(eFrequency, calculate_cpu_frequency(50)); } - - // Then get the cpu model, family, type, stepping and brand id by masking - // the eax and ebx register - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - CPUInfo.uiBrandID = ebxreg & 0xF; - - static const char* INTEL_BRAND[] = - { - /* 0x00 */ "", - /* 0x01 */ "0.18 micron Intel Celeron", - /* 0x02 */ "0.18 micron Intel Pentium III", - /* 0x03 */ "0.13 micron Intel Celeron", - /* 0x04 */ "0.13 micron Intel Pentium III", - /* 0x05 */ "", - /* 0x06 */ "0.13 micron Intel Pentium III Mobile", - /* 0x07 */ "0.13 micron Intel Celeron Mobile", - /* 0x08 */ "0.18 micron Intel Pentium 4", - /* 0x09 */ "0.13 micron Intel Pentium 4", - /* 0x0A */ "0.13 micron Intel Celeron", - /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon", - /* 0x0C */ "Intel Xeon MP", - /* 0x0D */ "", - /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon", - /* 0x0F */ "Mobile Intel Celeron", - /* 0x10 */ "", - /* 0x11 */ "Mobile Genuine Intel", - /* 0x12 */ "Intel Celeron M", - /* 0x13 */ "Mobile Intel Celeron", - /* 0x14 */ "Intel Celeron", - /* 0x15 */ "Mobile Genuine Intel", - /* 0x16 */ "Intel Pentium M", - /* 0x17 */ "Mobile Intel Celeron", - }; - // Only override the brand if we have it in the lookup table. We should - // already have a string here from GetCPUInfo(). JC - if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) ) +private: + void getCPUIDInfo() { - strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; + // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx + + // __cpuid with an InfoType argument of 0 returns the number of + // valid Ids in cpu_info[0] and the CPU identification string in + // the other three array elements. The CPU identification string is + // not in linear order. The code below arranges the information + // in a human readable form. + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); + unsigned int ids = (unsigned int)cpu_info[0]; + setConfig(eMaxID, (S32)ids); + + char cpu_vendor[0x20]; + memset(cpu_vendor, 0, sizeof(cpu_vendor)); + *((int*)cpu_vendor) = cpu_info[1]; + *((int*)(cpu_vendor+4)) = cpu_info[3]; + *((int*)(cpu_vendor+8)) = cpu_info[2]; + setInfo(eVendor, cpu_vendor); - if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) + // Get the information associated with each valid Id + for(unsigned int i=0; i<=ids; ++i) { - strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon"); - } - } + __cpuid(cpu_info, i); - // Then we translate the cpu family - switch (CPUInfo.uiFamily) - { - case 3: // Family = 3: i386 (80386) processor family - strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */ - break; - case 4: // Family = 4: i486 (80486) processor family - strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */ - break; - case 5: // Family = 5: Pentium (80586) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */ - break; - case 6: // Family = 6: Pentium Pro (80686) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */ - break; - case 15: // Family = 15: Extended family specific - // Masking the extended family - CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF; - switch (CPUInfo.uiExtendedFamily) - { - case 0: // Family = 15, Ext. Family = 0: Pentium 4 (80786 ??) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */ - break; - case 1: // Family = 15, Ext. Family = 1: McKinley (64-bit) processor family - strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */ - break; - default: // Sure is sure - strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */ - break; - } - break; - default: // Failsave - strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */ - break; - } - - // Now we come to the big deal, the exact model name - switch (CPUInfo.uiFamily) - { - case 3: // i386 (80386) processor family - strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // i486 (80486) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: i486 DX-25/33 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: i486 DX-50 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: i486 SX processor model - strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: i486 DX2 (with i487 numeric coprocessor) processor model - strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // Model = 4: i486 SL processor model (never heard ?!?) - strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 5: // Model = 5: i486 SX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: i486 write-back enhanced DX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: i486 DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: i486 write-back enhanced DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Pentium (80586) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium (P5 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; // Famous for the DIV bug, as far as I know - case 1: // Model = 1: Pentium 60/66 processor model - strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: Pentium 75-200 (P54C) processor model - strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: Pentium overdrive for 486 systems processor model - strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 4: Pentium MMX processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium processor model (don't know difference to Model=2) - strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium MMX (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 6: // Pentium Pro (80686) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium Pro (P6 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 1: // Model = 1: Pentium Pro - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 3: Pentium II (66 MHz FSB, I think) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 5: // Model = 5: Pentium II/Xeon/Celeron (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 6: // Model = 6: Pentium II with internal L2 cache - strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium III/Xeon (extern L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // We want to know it exactly: - switch (CPUInfo.uiBrandID) - { - case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-)) - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9 - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // Exact detection: - switch (CPUInfo.uiBrandID) - { - case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // Getting bored of this............ - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron"); /*Flawfinder: ignore*/ - // Omniscient: ;-) - switch (CPUInfo.uiBrandID) - { - case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model - strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *bored* - strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E - strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F - strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *more bored* - strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 15: // Extended processor family - // Masking the extended model - CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF; - switch (CPUInfo.uiModel) + // Interpret CPU feature information. + if (i == 1) { - case 0: // Model = 0: Pentium 4 Willamette (A-Step) core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 1: // Model = 1: Pentium 4 Willamette core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette + setInfo(eStepping, cpu_info[0] & 0xf); + setInfo(eModel, (cpu_info[0] >> 4) & 0xf); + int family = (cpu_info[0] >> 8) & 0xf; + setInfo(eFamily, family); + setInfo(eType, (cpu_info[0] >> 12) & 0x3); + setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf); + int ext_family = (cpu_info[0] >> 20) & 0xff; + setInfo(eExtendedFamily, ext_family); + setInfo(eBrandID, cpu_info[1] & 0xff); + + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + + setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + + if(cpu_info[2] & 0x1) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if(cpu_info[2] & 0x8) + { + setExtension(cpu_feature_names[eMONTIOR_MWAIT]); + } + + if(cpu_info[2] & 0x10) + { + setExtension(cpu_feature_names[eCPLDebugStore]); + } + + if(cpu_info[2] & 0x100) + { + setExtension(cpu_feature_names[eThermalMonitor2]); + } + + unsigned int feature_info = (unsigned int) cpu_info[3]; + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ + setExtension(cpu_feature_names[index]); } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 2: // Model = 2: Pentium 4 Northwood core - if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - else // Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - default: // Silly stupid never used failsave option - strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; + } } - break; - default: // *grmpf* - strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; - } - - // After the long processor model block we now come to the processors serial - // number. - // First of all we check if the processor supports the serial number - if (CPUInfo.MaxSupportedLevel >= 3) - { - // If it supports the serial number CPUID level 0x00000003 we read the data - unsigned long sig1, sig2, sig3; - __asm - { - mov eax, 1 - cpuid - mov sig1, eax - mov eax, 3 - cpuid - mov sig2, ecx - mov sig3, edx } - // Then we convert the data to a readable string - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", - sig1 >> 16, - sig1 & 0xFFFF, - sig3 >> 16, - sig3 & 0xFFFF, - sig2 >> 16, sig2 & 0xFFFF); - } - else - { - // If there's no serial number support we just put "No serial number" - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "No Processor Serial Number"); - } - - // Now we get the standard processor extensions - GetStandardProcessorExtensions(); - // And finally the processor configuration (caches, TLBs, ...) and translate - // the data to readable strings - GetStandardProcessorConfiguration(); - TranslateProcessorConfiguration(); + // Calling __cpuid with 0x80000000 as the InfoType argument + // gets the number of valid extended IDs. + __cpuid(cpu_info, 0x80000000); + unsigned int ext_ids = cpu_info[0]; + setConfig(eMaxExtID, 0); - // At last... - return true; -#else - return FALSE; -#endif -} + char cpu_brand_string[0x40]; + memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); -// bool CProcessor::AnalyzeAMDProcessor() -// ====================================== -// Private class function for analyzing an AMD processor -//////////////////////////////////////////////////////// -bool CProcessor::AnalyzeAMDProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return 0; - - // Now we get the CPUID standard level 0x00000001 - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask the model, family, stepping and type (AMD does not support brand id) - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // Now we check if the processor supports the brand id string extended CPUID level - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004) - { - // If it supports the extended CPUID level 0x80000004 we read the data - char tmp[52]; /* Flawfinder: ignore */ - memset(tmp, 0, sizeof(tmp)); - __asm + // Get the information associated with each extended ID. + for(unsigned int i=0x80000000; i<=ext_ids; ++i) { - mov eax, 0x80000002 - cpuid - mov dword ptr [tmp], eax - mov dword ptr [tmp+4], ebx - mov dword ptr [tmp+8], ecx - mov dword ptr [tmp+12], edx - mov eax, 0x80000003 - cpuid - mov dword ptr [tmp+16], eax - mov dword ptr [tmp+20], ebx - mov dword ptr [tmp+24], ecx - mov dword ptr [tmp+28], edx - mov eax, 0x80000004 - cpuid - mov dword ptr [tmp+32], eax - mov dword ptr [tmp+36], ebx - mov dword ptr [tmp+40], ecx - mov dword ptr [tmp+44], edx - } - // And copy it to the brand id string - strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - } - else - { - // Or just tell there is no brand id string support - strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */ - } - - // After that we translate the processor family - switch(CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x86 (80486) processor family - switch (CPUInfo.uiModel) + __cpuid(cpu_info, i); + + // Interpret CPU brand string and cache information. + if (i == 0x80000002) + memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000003) + memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000004) { - case 3: // Thanks to AMD for this nice form of family - case 7: // detection.... *grmpf* - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */ - break; - case 0xE: - case 0xF: - strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); + setInfo(eBrandName, cpu_brand_string); } - break; - case 5: // Family = 5: K5 or K6 processor family - switch (CPUInfo.uiModel) + else if (i == 0x80000006) { - case 0: - case 1: - case 2: - case 3: - strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */ - break; - case 6: - case 7: - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + setConfig(eCacheLineSize, cpu_info[2] & 0xff); + setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); + setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff); } - break; - case 6: // Family = 6: K7 (Athlon, ...) processor family - strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */ - break; - default: // For security - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; + } } +}; - // After the family detection we come to the specific processor model - // detection - switch (CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x85 (80486) processor family - switch (CPUInfo.uiModel) - { - case 3: // Model = 3: 80486 DX2 - strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: 80486 write-back enhanced DX2 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: 80486 DX4 - strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: 80486 write-back enhanced DX4 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xE: // Model = 0xE: 5x86 - strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xF: // Model = 0xF: 5x86 write-back enhanced (oh my god.....) - strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Family = 5: K5 / K6 processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 MHz) - strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: K5 5k86 (PR 120 and 133 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: K5 5k86 (PR 166 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: K5 5k86 (PR 200 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Model = 6: K6 - strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: K6 (0.25 micron) - strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: K6-2 - strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: K6-III - strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xD: // Model = 0xD: K6-2+ / K6-III+ - strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 6: // Family = 6: K7 processor family (AMDs first good processors) - switch (CPUInfo.uiModel) +#elif LL_DARWIN + +#include <mach/machine.h> +#include <sys/sysctl.h> + +class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl +{ +public: + LLProcessorInfoDarwinImpl() + { + getCPUIDInfo(); + uint64_t frequency = getSysctlInt64("hw.cpufrequency"); + setInfo(eFrequency, (F64)frequency / (F64)1000000); + } + + virtual ~LLProcessorInfoDarwinImpl() {} + +private: + int getSysctlInt(const char* name) + { + int result = 0; + size_t len = sizeof(int); + int error = sysctlbyname(name, (void*)&result, &len, NULL, 0); + return error == -1 ? 0 : result; + } + + uint64_t getSysctlInt64(const char* name) + { + uint64_t value = 0; + size_t size = sizeof(value); + int result = sysctlbyname(name, (void*)&value, &size, NULL, 0); + if ( result == 0 ) + { + if ( size == sizeof( uint64_t ) ) + ; + else if ( size == sizeof( uint32_t ) ) + value = (uint64_t)(( uint32_t *)&value); + else if ( size == sizeof( uint16_t ) ) + value = (uint64_t)(( uint16_t *)&value); + else if ( size == sizeof( uint8_t ) ) + value = (uint64_t)(( uint8_t *)&value); + else { - case 1: // Athlon - strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Athlon (0.18 micron) - strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Duron (Spitfire core) - strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 4: // Athlon (Thunderbird core) - strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Athlon MP / Mobile Athlon (Palomino core) - strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Mobile Duron (Morgan core) - strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; + LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL; } - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - - // Now we read the standard processor extension that are stored in the same - // way the Intel standard extensions are - GetStandardProcessorExtensions(); - - // Then we check if theres an extended CPUID level support - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001) - { - // If we can access the extended CPUID level 0x80000001 we get the - // edx register - __asm - { - mov eax, 0x80000001 - cpuid - mov edxreg, edx } - - // Now we can mask some AMD specific cpu extensions - CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22); - CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29); - CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30); - CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31); - } - - // After that we check if the processor supports the ext. CPUID level - // 0x80000006 - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006) + + return result == -1 ? 0 : value; + } + + void getCPUIDInfo() { - // If it's present, we read it out - __asm - { - mov eax, 0x80000005 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } + size_t len = 0; - // Then we mask the L1 Data TLB information - if ((ebxreg >> 16) && (eaxreg >> 16)) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (eaxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (ebxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF; - } - if (CPUInfo._Data.uiAssociativeWays == 0xFF) - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - - // Now the L1 Instruction/Code TLB information - if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF)) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (eaxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (ebxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = ebxreg & 0xFF; - } - if (CPUInfo._Instruction.uiAssociativeWays == 0xFF) - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; + char cpu_brand_string[0x40]; + len = sizeof(cpu_brand_string); + memset(cpu_brand_string, 0, len); + sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); + cpu_brand_string[0x3f] = 0; + setInfo(eBrandName, cpu_brand_string); - // Then we read the L1 data cache information - if ((ecxreg >> 24) > 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF; - CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF; - } - // After that we read the L2 instruction/code cache information - if ((edxreg >> 24) > 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF; - CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF; - } - - // Note: I'm not absolutely sure that the L1 page size code (the - // 'if/else if/else if' structs above) really detects the real page - // size for the TLB. Somebody should check it.... - - // Now we read the ext. CPUID level 0x80000006 - __asm - { - mov eax, 0x80000006 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - } + char cpu_vendor[0x20]; + len = sizeof(cpu_vendor); + memset(cpu_vendor, 0, len); + sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); + cpu_vendor[0x1f] = 0; + setInfo(eVendor, cpu_vendor); + + setInfo(eStepping, getSysctlInt("machdep.cpu.stepping")); + setInfo(eModel, getSysctlInt("machdep.cpu.model")); + int family = getSysctlInt("machdep.cpu.family"); + int ext_family = getSysctlInt("machdep.cpu.extfamily"); + setInfo(eFamily, family); + setInfo(eExtendedFamily, ext_family); + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + setInfo(eType, 0); // ? where to find this? + + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits"); + S32 *feature_infos = (S32*)(&feature_info); + + setConfig(eFeatureBits, feature_infos[0]); - // We only mask the unified L2 cache masks (never heard of an - // L2 cache that is divided in data and code parts) - if (((ecxreg >> 12) & 0xF) > 0) + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */ - switch ((ecxreg >> 12) & 0xF) + if(feature_info & bit) { - case 1: - CPUInfo._L2.uiAssociativeWays = 1; - break; - case 2: - CPUInfo._L2.uiAssociativeWays = 2; - break; - case 4: - CPUInfo._L2.uiAssociativeWays = 4; - break; - case 6: - CPUInfo._L2.uiAssociativeWays = 8; - break; - case 8: - CPUInfo._L2.uiAssociativeWays = 16; - break; - case 0xF: - CPUInfo._L2.uiAssociativeWays = (unsigned int) -1; - break; - default: - CPUInfo._L2.uiAssociativeWays = 0; - break; + setExtension(cpu_feature_names[index]); } - CPUInfo._L2.uiLineSize = ecxreg & 0xFF; } - } - else - { - // If we could not detect the ext. CPUID level 0x80000006 we - // try to read the standard processor configuration. - GetStandardProcessorConfiguration(); - } - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // And finally exit - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::AnalyzeUnknownProcessor() -// ========================================== -// Private class function to analyze an unknown (No Intel or AMD) processor -/////////////////////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeUnknownProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg; - - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // First of all we read the standard CPUID level 0x00000001 - // This level should be available on every x86-processor clone - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - } - // Then we mask the processor model, family, type and stepping - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // To have complete information we also mask the brand id - CPUInfo.uiBrandID = ebxreg & 0xF; - - // Then we get the standard processor extensions - GetStandardProcessorExtensions(); - - // Now we mark everything we do not know as unknown - strcpy(strCPUName, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Data.strTLB, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._Instruction.strTLB, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Trace.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Data.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Instruction.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L2.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L3.strCache, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/ - - // For the family, model and brand id we can only print the numeric value - snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID); /* Flawfinder: ignore */ - snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily); /* Flawfinder: ignore */ - snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel); /* Flawfinder: ignore */ - - // And thats it - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::CheckCPUIDPresence() -// ===================================== -// This function checks if the CPUID command is available on the current -// processor -//////////////////////////////////////////////////////////////////////// -bool CProcessor::CheckCPUIDPresence() -{ -#if LL_WINDOWS - unsigned long BitChanged; - - // We've to check if we can toggle the flag register bit 21 - // If we can't the processor does not support the CPUID command - __asm - { - pushfd - pop eax - mov ebx, eax - xor eax, 0x00200000 - push eax - popfd - pushfd - pop eax - xor eax,ebx - mov BitChanged, eax - } - return ((BitChanged) ? true : false); -#else - return FALSE; -#endif -} + // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be + // The feature bits I think it is. Here's a test: +#ifndef LL_RELEASE_FOR_DOWNLOAD + #if defined(__i386__) && defined(__PIC__) + /* %ebx may be the PIC register. */ + #define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #else + #define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #endif + + unsigned int eax, ebx, ecx, edx; + __cpuid(0x1, eax, ebx, ecx, edx); + if(feature_infos[0] != (S32)edx) + { + llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl; + } +#endif // LL_RELEASE_FOR_DOWNLOAD -// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -// =============================================================== -// This function (or switch ?!) just translates a one-byte processor configuration -// byte to understandable values -////////////////////////////////////////////////////////////////////////////////// -void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -{ - // First we ensure that there's only one single byte - cfg &= 0xFF; - // Then we do a big switch - switch(cfg) - { - case 0: // cfg = 0: Unused - break; - case 0x1: // cfg = 0x1: code TLB present, 4 KB pages, 4 ways, 32 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 32; - break; - case 0x2: // cfg = 0x2: code TLB present, 4 MB pages, fully associative, 2 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 2; - break; - case 0x3: // cfg = 0x3: data TLB present, 4 KB pages, 4 ways, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 64; - break; - case 0x4: // cfg = 0x4: data TLB present, 4 MB pages, 4 ways, 8 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 8; - break; - case 0x6: // cfg = 0x6: code L1 cache present, 8 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0x8: // cfg = 0x8: code L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0xA: // cfg = 0xA: data L1 cache present, 8 KB, 2 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 2; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0xC: // cfg = 0xC: data L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0x22: // cfg = 0x22: code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "512 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 4; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x23: // cfg = 0x23: code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x25: // cfg = 0x25: code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x29: // cfg = 0x29: code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x40: // cfg = 0x40: no integrated L2 cache (P6 core) or L3 cache (P4 core) - break; - case 0x41: // cfg = 0x41: code and data L2 cache present, 128 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x42: // cfg = 0x42: code and data L2 cache present, 256 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x43: // cfg = 0x43: code and data L2 cache present, 512 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x44: // cfg = 0x44: code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x45: // cfg = 0x45: code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x50: // cfg = 0x50: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 64; - break; - case 0x51: // cfg = 0x51: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 128; - break; - case 0x52: // cfg = 0x52: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 256; - break; - case 0x5B: // cfg = 0x5B: data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 64; - break; - case 0x5C: // cfg = 0x5C: data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 128; - break; - case 0x5d: // cfg = 0x5D: data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 256; - break; - case 0x66: // cfg = 0x66: data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x67: // cfg = 0x67: data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x68: // cfg = 0x68: data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "32 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x70: // cfg = 0x70: trace L1 cache present, 12 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x71: // cfg = 0x71: trace L1 cache present, 16 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x72: // cfg = 0x72: trace L1 cache present, 32 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x79: // cfg = 0x79: code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7A: // cfg = 0x7A: code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7B: // cfg = 0x7B: code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7C: // cfg = 0x7C: code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x81: // cfg = 0x81: code and data L2 cache present, 128 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x82: // cfg = 0x82: code and data L2 cache present, 256 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x83: // cfg = 0x83: code and data L2 cache present, 512 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x84: // cfg = 0x84: code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x85: // cfg = 0x85: code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; + uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); + S32 *ext_feature_infos = (S32*)(&ext_feature_info); + setConfig(eExtFeatureBits, ext_feature_infos[0]); } -} +}; -FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else - { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ - } - // To ease the function use we return the buffer - return buf; -} -FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ +#elif LL_LINUX +const char CPUINFO_FILE[] = "/proc/cpuinfo"; - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -FORCEINLINE static void TranslateCache(ProcessorCache *cache) +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl { - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the cache is present - if (cache->bPresent) - { - // If present we construct the string - snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ - } - else +public: + LLProcessorInfoLinuxImpl() { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ + get_proc_cpuinfo(); } -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - TranslateCache(&CPUInfo._Trace); + virtual ~LLProcessorInfoLinuxImpl() {} +private: - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// void CProcessor::GetStandardProcessorConfiguration() -// ==================================================== -// Private class function to read the standard processor configuration -////////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorConfiguration() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // We check if the CPUID function is available - if (!CheckCPUIDPresence()) - return; - - // First we check if the processor supports the standard - // CPUID level 0x00000002 - if (CPUInfo.MaxSupportedLevel >= 2) + void get_proc_cpuinfo() { - // Now we go read the std. CPUID level 0x00000002 the first time - unsigned long count, num = 255; - for (count = 0; count < num; count++) + std::map< std::string, std::string > cpuinfo; + LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo_fp) { - __asm - { - mov eax, 2 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } - // We have to repeat this reading for 'num' times - num = eaxreg & 0xFF; - - // Then we call the big decode switch function - DecodeProcessorConfiguration(eaxreg >> 8); - DecodeProcessorConfiguration(eaxreg >> 16); - DecodeProcessorConfiguration(eaxreg >> 24); - - // If ebx contains additional data we also decode it - if ((ebxreg & 0x80000000) == 0) + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo_fp)) { - DecodeProcessorConfiguration(ebxreg); - DecodeProcessorConfiguration(ebxreg >> 8); - DecodeProcessorConfiguration(ebxreg >> 16); - DecodeProcessorConfiguration(ebxreg >> 24); - } - // And also the ecx register - if ((ecxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(ecxreg); - DecodeProcessorConfiguration(ecxreg >> 8); - DecodeProcessorConfiguration(ecxreg >> 16); - DecodeProcessorConfiguration(ecxreg >> 24); - } - // At last the edx processor register - if ((edxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(edxreg); - DecodeProcessorConfiguration(edxreg >> 8); - DecodeProcessorConfiguration(edxreg >> 16); - DecodeProcessorConfiguration(edxreg >> 24); + // /proc/cpuinfo on Linux looks like: + // name\t*: value\n + char* tabspot = strchr( line, '\t' ); + if (tabspot == NULL) + continue; + char* colspot = strchr( tabspot, ':' ); + if (colspot == NULL) + continue; + char* spacespot = strchr( colspot, ' ' ); + if (spacespot == NULL) + continue; + char* nlspot = strchr( line, '\n' ); + if (nlspot == NULL) + nlspot = line + strlen( line ); // Fallback to terminating NUL + std::string linename( line, tabspot ); + std::string llinename(linename); + LLStringUtil::toLower(llinename); + std::string lineval( spacespot + 1, nlspot ); + cpuinfo[ llinename ] = lineval; } + fclose(cpuinfo_fp); + } +# if LL_X86 + +// *NOTE:Mani - eww, macros! srry. +#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ + if (!cpuinfo[cpuinfo_id].empty()) \ + { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} + +#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ + {\ + S32 result; \ + if (!cpuinfo[cpuinfo_id].empty() \ + && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ + { setInfo(llpi_id, result);} \ + } + + F64 mhz; + if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) + && 200.0 < mhz && mhz < 10000.0) + { + setInfo(eFrequency,(F64)(mhz)); } - } -#endif -} -// void CProcessor::GetStandardProcessorExtensions() -// ================================================= -// Private class function to read the standard processor extensions -/////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorExtensions() -{ -#if LL_WINDOWS - unsigned long ebxreg, edxreg; + LLPI_SET_INFO_STRING(eBrandName, "model name"); + LLPI_SET_INFO_STRING(eVendor, "vendor_id"); - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return; - // We just get the standard CPUID level 0x00000001 which should be - // available on every x86 processor - __asm - { - mov eax, 1 - cpuid - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask some bits - CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0); - CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1); - CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2); - CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3); - CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4); - CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5); - CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6); - CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7); - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8); - CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9); - CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF; - CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11); - CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12); - CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13); - CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14); - CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15); - CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16); - CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17); - CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18); - CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19); - CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF; - CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21); - CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22); - CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23); - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27); - CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28); - CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF; - CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29); - CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30); -#endif -} + LLPI_SET_INFO_INT(eStepping, "stepping"); + LLPI_SET_INFO_INT(eModel, "model"); -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; + + S32 family; + if (!cpuinfo["cpu family"].empty() + && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) + { + setInfo(eFamily, family); + } - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return NULL; + setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family)); - // We read the standard CPUID level 0x00000000 which should - // be available on every x86 processor - __asm - { - mov eax, 0 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - mov ecxreg, ecx - } - // Then we connect the single register values to the vendor string - *((unsigned long *) CPUInfo.strVendor) = ebxreg; - *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg; - *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg; - // Null terminate for string comparisons below. - CPUInfo.strVendor[12] = 0; - - // We can also read the max. supported standard CPUID level - CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF; - - // Then we read the ext. CPUID level 0x80000000 - __asm - { - mov eax, 0x80000000 - cpuid - mov eaxreg, eax - } - // ...to check the max. supportted extended CPUID level - CPUInfo.MaxSupportedExtendedLevel = eaxreg; - - // Then we switch to the specific processor vendors - // See http://www.sandpile.org/ia32/cpuid.htm - if (!strcmp(CPUInfo.strVendor, "GenuineIntel")) - { - AnalyzeIntelProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD")) - { - AnalyzeAMDProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CyrixInstead")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "NexGenDriven")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CentaurHauls")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86")) - { - // Transmeta - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "Geode by NSC")) - { - AnalyzeUnknownProcessor(); - } - else - { - AnalyzeUnknownProcessor(); - } -#endif - // After all we return the class CPUInfo member var - return (&CPUInfo); -} + // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + // setInfo(eType, 0); // ? where to find this? -#elif LL_SOLARIS -#include <kstat.h> - -#if defined(__i386) -#include <sys/auxv.h> -#endif - -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - if(uqwFrequency == 0){ - GetCPUInfo(); - } - - return uqwFrequency; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - // In Solaris the CPU info is in the kstats - // try "psrinfo" or "kstat cpu_info" to see all - // that's available - int ncpus=0, i; - kstat_ctl_t *kc; - kstat_t *ks; - kstat_named_t *ksinfo, *ksi; - kstat_t *CPU_stats_list; - - kc = kstat_open(); - - if((int)kc == -1){ - llwarns << "kstat_open(0 failed!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 && - strncmp(ks->ks_name, "cpu_info", 8) == 0) - ncpus++; - } - - if(ncpus < 1){ - llwarns << "No cpus found in kstats!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 - && strncmp(ks->ks_name, "cpu_info", 8) == 0 - && kstat_read(kc, ks, NULL) != -1){ - CPU_stats_list = ks; // only looking at the first CPU - - break; - } - } - - if(ncpus > 1) - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus); - - kstat_read(kc, CPU_stats_list, NULL); - ksinfo = (kstat_named_t *)CPU_stats_list->ks_data; - for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need - ksi = ksinfo++; - if(!strcmp(ksi->name, "brand")){ - strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(strCPUName)-strlen(strCPUName)-1); - strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - // DEBUG llinfos << "CPU brand: " << strCPUName << llendl; - continue; - } + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + // Read extensions + std::string flags = " " + cpuinfo["flags"] + " "; + LLStringUtil::toLower(flags); - if(!strcmp(ksi->name, "clock_MHz")){ -#if defined(__sparc) - llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl; - uqwFrequency = (F64)(ksi->value.l * 1000000); -#else - uqwFrequency = (F64)(ksi->value.i64 * 1000000); -#endif - //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl; - continue; + if( flags.find( " sse " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE_Ext]); } -#if defined(__i386) - if(!strcmp(ksi->name, "vendor_id")){ - strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1); - // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl; - continue; + if( flags.find( " sse2 " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE2_Ext]); } -#endif - } - - kstat_close(kc); - -#if defined(__sparc) // SPARC does not define a vendor string in kstat - strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1); -#endif - - // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl; - -#if defined (__i386) // we really don't care about the CPU extensions on SPARC but on x86... - - // Now get cpu extensions - - uint_t ui; - - (void) getisax(&ui, 1); - if(ui & AV_386_FPU) - CPUInfo._Ext.FPU_FloatingPointUnit = true; - if(ui & AV_386_CX8) - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true; - if(ui & AV_386_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_AMD_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_FXSR) - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true; - if(ui & AV_386_SSE) - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true; - if(ui & AV_386_SSE2) - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true; -/* Left these here since they may get used later - if(ui & AV_386_SSE3) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNow) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNowx) - CPUInfo._Ext.... = true; -*/ -#endif - return (&CPUInfo); -} - -#else -// LL_DARWIN - -#include <mach/machine.h> -#include <sys/sysctl.h> - -static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else - { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ +# endif // LL_X86 } - // To ease the function use we return the buffer - return buf; -} -static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -static void TranslateCache(ProcessorCache *cache) -{ - char buf[64]; /* Flawfinder: ignore */ - // We just check if the cache is present - if (cache->bPresent) + std::string getCPUFeatureDescription() const { - // If present we construct the string - snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ - } - else - { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ - } -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - - TranslateCache(&CPUInfo._Trace); + std::ostringstream s; - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - U64 frequency = 0; - size_t len = sizeof(frequency); - - if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0) - { - uqwFrequency = (F64)frequency; - } - - return uqwFrequency; -} - -static bool hasFeature(const char *name) -{ - bool result = false; - int val = 0; - size_t len = sizeof(val); - - if(sysctlbyname(name, &val, &len, NULL, 0) == 0) - { - if(val != 0) - result = true; - } - - return result; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - int pagesize = 0; - int cachelinesize = 0; - int l1icachesize = 0; - int l1dcachesize = 0; - int l2settings = 0; - int l2cachesize = 0; - int l3settings = 0; - int l3cachesize = 0; - int ncpu = 0; - int cpusubtype = 0; - - // sysctl knows all. - int mib[2]; - size_t len; - mib[0] = CTL_HW; - - mib[1] = HW_PAGESIZE; - len = sizeof(pagesize); - sysctl(mib, 2, &pagesize, &len, NULL, 0); - - mib[1] = HW_CACHELINE; - len = sizeof(cachelinesize); - sysctl(mib, 2, &cachelinesize, &len, NULL, 0); - - mib[1] = HW_L1ICACHESIZE; - len = sizeof(l1icachesize); - sysctl(mib, 2, &l1icachesize, &len, NULL, 0); - - mib[1] = HW_L1DCACHESIZE; - len = sizeof(l1dcachesize); - sysctl(mib, 2, &l1dcachesize, &len, NULL, 0); - - mib[1] = HW_L2SETTINGS; - len = sizeof(l2settings); - sysctl(mib, 2, &l2settings, &len, NULL, 0); - - mib[1] = HW_L2CACHESIZE; - len = sizeof(l2cachesize); - sysctl(mib, 2, &l2cachesize, &len, NULL, 0); - - mib[1] = HW_L3SETTINGS; - len = sizeof(l3settings); - sysctl(mib, 2, &l3settings, &len, NULL, 0); - - mib[1] = HW_L3CACHESIZE; - len = sizeof(l3cachesize); - sysctl(mib, 2, &l3cachesize, &len, NULL, 0); - - mib[1] = HW_NCPU; - len = sizeof(ncpu); - sysctl(mib, 2, &ncpu, &len, NULL, 0); - - sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0); - - strCPUName[0] = 0; - - if((ncpu == 0) || (ncpu == 1)) - { - // Uhhh... - } - else if(ncpu == 2) - { - strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - } - else - { - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu); /* Flawfinder: ignore */ - } - -#if __ppc__ - switch(cpusubtype) - { - case CPU_SUBTYPE_POWERPC_601:// ((cpu_subtype_t) 1) - strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - - break; - case CPU_SUBTYPE_POWERPC_602:// ((cpu_subtype_t) 2) - strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603:// ((cpu_subtype_t) 3) - strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603e:// ((cpu_subtype_t) 4) - strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603ev:// ((cpu_subtype_t) 5) - strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604:// ((cpu_subtype_t) 6) - strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604e:// ((cpu_subtype_t) 7) - strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_620:// ((cpu_subtype_t) 8) - strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_750:// ((cpu_subtype_t) 9) - strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7400:// ((cpu_subtype_t) 10) - strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7450:// ((cpu_subtype_t) 11) - strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_970:// ((cpu_subtype_t) 100) - strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - - default: - strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = - CPUInfo._Ext.MMX_MultimediaExtensions = - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false; - - CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec"); - -#endif - -#if __i386__ - // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()? - switch(cpusubtype) - { - default: - strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); // MBW -- XXX -- this may be wrong... - CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse"); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2"); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64"); - -#endif - - // Terse CPU info uses this string... - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); /* Flawfinder: ignore */ - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - - // Fun cache config stuff... - - if(l1dcachesize != 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Data.uiAssociativeWays = ???; - CPUInfo._L1.Data.uiLineSize = cachelinesize; + // *NOTE:Mani - This is for linux only. + LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo) + { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo)) + { + line[strlen(line)-1] = ' '; + s << line; + s << std::endl; + } + fclose(cpuinfo); + s << std::endl; + } + else + { + s << "Unable to collect processor information" << std::endl; + } + return s.str(); } + +}; - if(l1icachesize != 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Instruction.uiAssociativeWays = ???; - CPUInfo._L1.Instruction.uiLineSize = cachelinesize; - } - if(l2cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; - } +#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX - if(l3cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; +////////////////////////////////////////////////////// +// Interface definition +LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) +{ + // *NOTE:Mani - not thread safe. + if(!mImpl) + { +#ifdef LL_MSVC + static LLProcessorInfoWindowsImpl the_impl; + mImpl = &the_impl; +#elif LL_DARWIN + static LLProcessorInfoDarwinImpl the_impl; + mImpl = &the_impl; +#else + static LLProcessorInfoLinuxImpl the_impl; + mImpl = &the_impl; +#endif // LL_MSVC } - - CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint"); - -// printf("pagesize = 0x%x\n", pagesize); -// printf("cachelinesize = 0x%x\n", cachelinesize); -// printf("l1icachesize = 0x%x\n", l1icachesize); -// printf("l1dcachesize = 0x%x\n", l1dcachesize); -// printf("l2settings = 0x%x\n", l2settings); -// printf("l2cachesize = 0x%x\n", l2cachesize); -// printf("l3settings = 0x%x\n", l3settings); -// printf("l3cachesize = 0x%x\n", l3cachesize); - - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // After all we return the class CPUInfo member var - return (&CPUInfo); } -#endif // LL_DARWIN -// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -// ====================================================================== -// Gets the frequency and processor information and writes it to a string -///////////////////////////////////////////////////////////////////////// -bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -{ -#define LENCHECK len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len; /*Flawfinder: ignore*/ -#define COPYADD(str) strcpy(buf, str); LENCHECK; /* Flawfinder: ignore */ -#define FORMATADD(format, var) sprintf(buf, format, var); LENCHECK; /* Flawfinder: ignore */ -#define BOOLADD(str, boolvar) COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); } - - char buf[1024]; /* Flawfinder: ignore */ - unsigned int len; - - // First we have to get the frequency - GetCPUFrequency(50); - - // Then we get the processor information - GetCPUInfo(); - - // Now we construct the string (see the macros at function beginning) - strBuffer[0] = 0; - - COPYADD("// CPU General Information\n//////////////////////////\n"); - FORMATADD("Processor name: %s\n", strCPUName); - FORMATADD("Frequency: %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f); - FORMATADD("Vendor: %s\n", CPUInfo.strVendor); - FORMATADD("Family: %s\n", CPUInfo.strFamily); - FORMATADD("Extended family: %d\n", CPUInfo.uiExtendedFamily); - FORMATADD("Model: %s\n", CPUInfo.strModel); - FORMATADD("Extended model: %d\n", CPUInfo.uiExtendedModel); - FORMATADD("Type: %s\n", CPUInfo.strType); - FORMATADD("Brand ID: %s\n", CPUInfo.strBrandID); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("Processor Serial: Disabled\n"); - } -#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent - - COPYADD("\n\n// CPU Configuration\n////////////////////\n"); - FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache); - FORMATADD("L1 data cache: %s\n", CPUInfo._L1.Data.strCache); - FORMATADD("L2 cache: %s\n", CPUInfo._L2.strCache); - FORMATADD("L3 cache: %s\n", CPUInfo._L3.strCache); - FORMATADD("Trace cache: %s\n", CPUInfo._Trace.strCache); - FORMATADD("Instruction TLB: %s\n", CPUInfo._Instruction.strTLB); - FORMATADD("Data TLB: %s\n", CPUInfo._Data.strTLB); - FORMATADD("Max Supported CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedLevel); - FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel); - - COPYADD("\n\n// CPU Extensions\n/////////////////\n"); - BOOLADD("AA64 AMD 64-bit Architecture: ", CPUInfo._Ext.AA64_AMD64BitArchitecture); - BOOLADD("ACPI Thermal Monitor And Clock Control: ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl); - BOOLADD("APIC Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController); - FORMATADD(" APIC-ID: %d\n", CPUInfo._Ext.APIC_ID); - BOOLADD("CLFSH CLFLUSH Instruction Presence: ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction); - FORMATADD(" CLFLUSH Instruction Cache Line Size: %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize); - BOOLADD("CMOV Conditional Move And Compare Instructions: ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions); - BOOLADD("CX8 COMPXCHG8B Instruction: ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction); - BOOLADD("DE Debugging Extensions: ", CPUInfo._Ext.DE_DebuggingExtensions); - BOOLADD("DS Debug Store: ", CPUInfo._Ext.DS_DebugStore); - BOOLADD("FGPAT Page Attribute Table: ", CPUInfo._Ext.FGPAT_PageAttributeTable); - BOOLADD("FPU Floating Point Unit: ", CPUInfo._Ext.FPU_FloatingPointUnit); - BOOLADD("FXSR Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore); - BOOLADD("HT Hyper Threading: ", CPUInfo._Ext.HT_HyperThreading); - BOOLADD("IA64 Intel 64-Bit Architecture: ", CPUInfo._Ext.IA64_Intel64BitArchitecture); - BOOLADD("MCA Machine Check Architecture: ", CPUInfo._Ext.MCA_MachineCheckArchitecture); - BOOLADD("MCE Machine Check Exception: ", CPUInfo._Ext.MCE_MachineCheckException); - BOOLADD("MMX Multimedia Extensions: ", CPUInfo._Ext.MMX_MultimediaExtensions); - BOOLADD("MMX+ Multimedia Extensions: ", CPUInfo._Ext.EMMX_MultimediaExtensions); - BOOLADD("MSR Model Specific Registers: ", CPUInfo._Ext.MSR_ModelSpecificRegisters); - BOOLADD("MTRR Memory Type Range Registers: ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters); - BOOLADD("PAE Physical Address Extension: ", CPUInfo._Ext.PAE_PhysicalAddressExtension); - BOOLADD("PGE PTE Global Flag: ", CPUInfo._Ext.PGE_PTE_GlobalFlag); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("PN Processor Serial Number: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("PN Processor Serial Number: Disabled\n"); - } - BOOLADD("PSE Page Size Extensions: ", CPUInfo._Ext.PSE_PageSizeExtensions); - BOOLADD("PSE36 36-bit Page Size Extension: ", CPUInfo._Ext.PSE36_36bitPageSizeExtension); - BOOLADD("SEP Fast System Call: ", CPUInfo._Ext.SEP_FastSystemCall); - BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop); - BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions); - BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions); - BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions); - BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor); - BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter); - BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements); - BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions); - BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions); -#endif - // Yippie!!! - return true; -} +LLProcessorInfo::~LLProcessorInfo() {} +F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } +bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } +std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } +std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } +std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); } -// bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -// =========================================================== -// Takes use of CProcessor::CPUInfoToText and saves the string to a -// file -/////////////////////////////////////////////////////////////////// -bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -{ - char buf[16384]; /* Flawfinder: ignore */ - - // First we get the string - if (!CPUInfoToText(buf, 16383)) - return false; - - // Then we create a new file (CREATE_ALWAYS) - LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */ - if (!file) - return false; - - // After that we write the string to the file - unsigned long dwBytesToWrite, dwBytesWritten; - dwBytesToWrite = (unsigned long) strlen(buf); /*Flawfinder: ignore*/ - dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file); - fclose(file); - if (dwBytesToWrite != dwBytesWritten) - return false; - - // Done - return true; -} diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 746d007a7f..fc2c8dacfb 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -30,167 +30,26 @@ * $/LicenseInfo$ */ -// Author: Benjamin Jurke -// File history: 27.02.2002 File created. -/////////////////////////////////////////// - #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +class LLProcessorInfoImpl; -// Options: -/////////// -#if LL_WINDOWS -#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -#endif - -#if LL_MSVC && _M_X64 -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_MSVC && _M_IX86 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -# define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -# define LL_PPC 1 -#endif - - -struct ProcessorExtensions -{ - bool FPU_FloatingPointUnit; - bool VME_Virtual8086ModeEnhancements; - bool DE_DebuggingExtensions; - bool PSE_PageSizeExtensions; - bool TSC_TimeStampCounter; - bool MSR_ModelSpecificRegisters; - bool PAE_PhysicalAddressExtension; - bool MCE_MachineCheckException; - bool CX8_COMPXCHG8B_Instruction; - bool APIC_AdvancedProgrammableInterruptController; - unsigned int APIC_ID; - bool SEP_FastSystemCall; - bool MTRR_MemoryTypeRangeRegisters; - bool PGE_PTE_GlobalFlag; - bool MCA_MachineCheckArchitecture; - bool CMOV_ConditionalMoveAndCompareInstructions; - bool FGPAT_PageAttributeTable; - bool PSE36_36bitPageSizeExtension; - bool PN_ProcessorSerialNumber; - bool CLFSH_CFLUSH_Instruction; - unsigned int CLFLUSH_InstructionCacheLineSize; - bool DS_DebugStore; - bool ACPI_ThermalMonitorAndClockControl; - bool EMMX_MultimediaExtensions; - bool MMX_MultimediaExtensions; - bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore; - bool SSE_StreamingSIMD_Extensions; - bool SSE2_StreamingSIMD2_Extensions; - bool Altivec_Extensions; - bool SS_SelfSnoop; - bool HT_HyperThreading; - unsigned int HT_HyterThreadingSiblings; - bool TM_ThermalMonitor; - bool IA64_Intel64BitArchitecture; - bool _3DNOW_InstructionExtensions; - bool _E3DNOW_InstructionExtensions; - bool AA64_AMD64BitArchitecture; -}; - -struct ProcessorCache -{ - bool bPresent; - char strSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiLineSize; - bool bSectored; - char strCache[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorL1Cache -{ - ProcessorCache Instruction; - ProcessorCache Data; -}; - -struct ProcessorTLB +class LL_COMMON_API LLProcessorInfo { - bool bPresent; - char strPageSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiEntries; - char strTLB[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorInfo -{ - char strVendor[16]; /* Flawfinder: ignore */ - unsigned int uiFamily; - unsigned int uiExtendedFamily; - char strFamily[64]; /* Flawfinder: ignore */ - unsigned int uiModel; - unsigned int uiExtendedModel; - char strModel[128]; /* Flawfinder: ignore */ - unsigned int uiStepping; - unsigned int uiType; - char strType[64]; /* Flawfinder: ignore */ - unsigned int uiBrandID; - char strBrandID[64]; /* Flawfinder: ignore */ - char strProcessorSerial[64]; /* Flawfinder: ignore */ - unsigned long MaxSupportedLevel; - unsigned long MaxSupportedExtendedLevel; - ProcessorExtensions _Ext; - ProcessorL1Cache _L1; - ProcessorCache _L2; - ProcessorCache _L3; - ProcessorCache _Trace; - ProcessorTLB _Instruction; - ProcessorTLB _Data; -}; - - -// CProcessor -// ========== -// Class for detecting the processor name, type and available -// extensions as long as it's speed. -///////////////////////////////////////////////////////////// -class CProcessor -{ -// Constructor / Destructor: -//////////////////////////// public: - CProcessor(); - -// Private vars: -//////////////// -public: - F64 uqwFrequency; - char strCPUName[128]; /* Flawfinder: ignore */ - ProcessorInfo CPUInfo; - -// Private functions: -///////////////////// + LLProcessorInfo(); + ~LLProcessorInfo(); + + F64 getCPUFrequency() const; + bool hasSSE() const; + bool hasSSE2() const; + bool hasAltivec() const; + std::string getCPUFamilyName() const; + std::string getCPUBrandName() const; + std::string getCPUFeatureDescription() const; private: - bool AnalyzeIntelProcessor(); - bool AnalyzeAMDProcessor(); - bool AnalyzeUnknownProcessor(); - bool CheckCPUIDPresence(); - void DecodeProcessorConfiguration(unsigned int cfg); - void TranslateProcessorConfiguration(); - void GetStandardProcessorConfiguration(); - void GetStandardProcessorExtensions(); - -// Public functions: -//////////////////// -public: - F64 GetCPUFrequency(unsigned int uiMeasureMSecs); - const ProcessorInfo *GetCPUInfo(); - bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen); - bool WriteInfoTextFile(const std::string& strFilename); + LLProcessorInfoImpl* mImpl; }; - -#endif +#endif // LLPROCESSOR_H diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 52b1b63209..d41d0c8a3f 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -58,7 +58,6 @@ # include <unistd.h> # include <sys/sysinfo.h> const char MEMINFO_FILE[] = "/proc/meminfo"; -const char CPUINFO_FILE[] = "/proc/cpuinfo"; #elif LL_SOLARIS # include <stdio.h> # include <unistd.h> @@ -513,71 +512,21 @@ U32 LLOSInfo::getProcessResidentSizeKB() LLCPUInfo::LLCPUInfo() { std::ostringstream out; - CProcessor proc; - const ProcessorInfo* info = proc.GetCPUInfo(); + LLProcessorInfo proc; // proc.WriteInfoTextFile("procInfo.txt"); - mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; - mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; - mHasAltivec = info->_Ext.Altivec_Extensions; - mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0F); - mFamily.assign( info->strFamily ); + mHasSSE = proc.hasSSE(); + mHasSSE2 = proc.hasSSE2(); + mHasAltivec = proc.hasAltivec(); + mCPUMHz = (F64)proc.getCPUFrequency(); + mFamily = proc.getCPUFamilyName(); mCPUString = "Unknown"; -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS - out << proc.strCPUName; + out << proc.getCPUBrandName(); if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check { out << " (" << mCPUMHz << " MHz)"; } mCPUString = out.str(); - -#elif LL_LINUX - std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo_fp) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo_fp)) - { - // /proc/cpuinfo on Linux looks like: - // name\t*: value\n - char* tabspot = strchr( line, '\t' ); - if (tabspot == NULL) - continue; - char* colspot = strchr( tabspot, ':' ); - if (colspot == NULL) - continue; - char* spacespot = strchr( colspot, ' ' ); - if (spacespot == NULL) - continue; - char* nlspot = strchr( line, '\n' ); - if (nlspot == NULL) - nlspot = line + strlen( line ); // Fallback to terminating NUL - std::string linename( line, tabspot ); - std::string llinename(linename); - LLStringUtil::toLower(llinename); - std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; - } - fclose(cpuinfo_fp); - } -# if LL_X86 - std::string flags = " " + cpuinfo["flags"] + " "; - LLStringUtil::toLower(flags); - mHasSSE = ( flags.find( " sse " ) != std::string::npos ); - mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos ); - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) - { - mCPUMHz = (F64)(mhz); - } - if (!cpuinfo["model name"].empty()) - mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX } bool LLCPUInfo::hasAltivec() const @@ -607,38 +556,9 @@ std::string LLCPUInfo::getCPUString() const void LLCPUInfo::stream(std::ostream& s) const { -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS // gather machine information. - char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */ - CProcessor proc; - if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) - { - s << proc_buf; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#else - // *NOTE: This works on linux. What will it do on other systems? - LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo)) - { - line[strlen(line)-1] = ' '; - s << line; - } - fclose(cpuinfo); - s << std::endl; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#endif + s << LLProcessorInfo().getCPUFeatureDescription(); + // These are interesting as they reflect our internal view of the // CPU's attributes regardless of platform s << "->mHasSSE: " << (U32)mHasSSE << std::endl; diff --git a/indra/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp new file mode 100644 index 0000000000..a9e312b70b --- /dev/null +++ b/indra/llcommon/tests/llprocessor_test.cpp @@ -0,0 +1,67 @@ +/** + * @file llprocessor_test.cpp + * @date 2010-06-01 + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../test/lltut.h" + +#include "../llprocessor.h" + + +namespace tut +{ + struct processor + { + }; + + typedef test_group<processor> processor_t; + typedef processor_t::object processor_object_t; + tut::processor_t tut_processor("processor"); + + template<> template<> + void processor_object_t::test<1>() + { + set_test_name("LLProcessorInfo regression test"); + + LLProcessorInfo pi; + F64 freq = pi.getCPUFrequency(); + //bool sse = pi.hasSSE(); + //bool sse2 = pi.hasSSE2(); + //bool alitvec = pi.hasAltivec(); + std::string family = pi.getCPUFamilyName(); + std::string brand = pi.getCPUBrandName(); + //std::string steam = pi.getCPUFeatureDescription(); + + ensure_not_equals("Unknown Brand name", brand, "Unknown"); + ensure_not_equals("Unknown Family name", family, "Unknown"); + ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000); + } +} diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2c767a4857..53830b1a14 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -85,10 +85,7 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid, mType(type), mName(name) { - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - LLStringUtil::trim(mName); - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); + correctInventoryName(mName); } LLInventoryObject::LLInventoryObject() : @@ -155,12 +152,8 @@ void LLInventoryObject::setUUID(const LLUUID& new_uuid) void LLInventoryObject::rename(const std::string& n) { std::string new_name(n); - LLStringUtil::replaceNonstandardASCII(new_name, ' '); - LLStringUtil::replaceChar(new_name, '|', ' '); - LLStringUtil::trim(new_name); - LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); - - if( new_name != mName ) + correctInventoryName(new_name); + if( !new_name.empty() && new_name != mName ) { mName = new_name; } @@ -221,10 +214,7 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream) " %254s %254[^|]", keyword, valuestr); mName.assign(valuestr); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - LLStringUtil::trim(mName); - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); + correctInventoryName(mName); } else { @@ -284,6 +274,15 @@ void LLInventoryObject::updateServer(BOOL) const llwarns << "LLInventoryObject::updateServer() called. Doesn't do anything." << llendl; } +inline +void LLInventoryObject::correctInventoryName(std::string& name) +{ + LLStringUtil::replaceNonstandardASCII(name, ' '); + LLStringUtil::replaceChar(name, '|', ' '); + LLStringUtil::trim(name); + LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN); +} + ///---------------------------------------------------------------------------- /// Class LLInventoryItem diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index b083e305b1..4c6ac83ab8 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -92,9 +92,13 @@ public: void setParent(const LLUUID& new_parent); void setType(LLAssetType::EType type); +private: + // in place correction for inventory name string + void correctInventoryName(std::string& name); + //-------------------------------------------------------------------- // File Support - // Implemented here so that a minimal information set can be transmitted + // Implemented here so that a minimal information set can be transmitted // between simulator and viewer. //-------------------------------------------------------------------- public: diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 209b506c30..c3c15e1374 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -61,11 +61,11 @@ #endif // Single Precision Floating Point Routines -#ifndef fsqrtf -#define fsqrtf(x) ((F32)sqrt((F64)(x))) -#endif #ifndef sqrtf -#define sqrtf(x) ((F32)sqrt((F64)(x))) +#define sqrtf(x) ((F32)sqrt((F64)(x))) +#endif +#ifndef fsqrtf +#define fsqrtf(x) sqrtf(x) #endif #ifndef cosf @@ -78,11 +78,14 @@ #define tanf(x) ((F32)tan((F64)(x))) #endif #ifndef acosf -#define acosf(x) ((F32)acos((F64)(x))) +#define acosf(x) ((F32)acos((F64)(x))) #endif #ifndef powf -#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) +#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) +#endif +#ifndef expf +#define expf(x) ((F32)exp((F64)(x))) #endif const F32 GRAVITY = -9.8f; diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 8e0245c451..6bf1347514 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -66,8 +66,12 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mAutoScrolling( false ) , mAutoScrollRate( 0.f ) , mSelectedTab( NULL ) + , mTabComparator( NULL ) + , mNoVisibleTabsHelpText(NULL) { - mSingleExpansion = params.single_expansion; + initNoTabsWidget(params.empty_accordion_text); + + mSingleExpansion = params.single_expansion; if(mFitParent && !mSingleExpansion) { llinfos << "fit_parent works best when combined with single_expansion" << llendl; @@ -78,7 +82,10 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel() , mAutoScrolling( false ) , mAutoScrollRate( 0.f ) , mSelectedTab( NULL ) + , mNoVisibleTabsHelpText(NULL) { + initNoTabsWidget(LLTextBox::Params()); + mSingleExpansion = false; mFitParent = false; LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml"); @@ -168,6 +175,8 @@ BOOL LLAccordionCtrl::postBuild() } } + updateNoTabsHelpTextVisibility(); + return TRUE; } @@ -187,8 +196,15 @@ void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) rcLocal.mRight = rcLocal.mLeft + width; rcLocal.mTop = rcLocal.mBottom + height; + // get textbox a chance to reshape its content + mNoVisibleTabsHelpText->reshape(width, height, called_from_parent); + setRect(rcLocal); + // assume that help text is always fit accordion. + // necessary text paddings can be set via h_pad and v_pad + mNoVisibleTabsHelpText->setRect(getLocalRect()); + arrange(); } @@ -359,6 +375,31 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) } } +void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) +{ + LLTextBox::Params tp = tb_params; + tp.rect(getLocalRect()); + mNoVisibleTabsOrigString = tp.initial_value().asString(); + mNoVisibleTabsHelpText = LLUICtrlFactory::create<LLTextBox>(tp, this); +} + +void LLAccordionCtrl::updateNoTabsHelpTextVisibility() +{ + bool visible_exists = false; + std::vector<LLAccordionCtrlTab*>::const_iterator it = mAccordionTabs.begin(); + const std::vector<LLAccordionCtrlTab*>::const_iterator it_end = mAccordionTabs.end(); + for (; it != it_end; ++it) + { + if ((*it)->getVisible()) + { + visible_exists = true; + break; + } + } + + mNoVisibleTabsHelpText->setVisible(!visible_exists); +} + void LLAccordionCtrl::arrangeSinge() { S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter @@ -737,6 +778,20 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return 1; } + else if (info.has("child_visibility_change")) + { + BOOL new_visibility = info["child_visibility_change"]; + if (new_visibility) + { + // there is at least one visible tab + mNoVisibleTabsHelpText->setVisible(FALSE); + } + else + { + // it could be the latest visible tab, check all of them + updateNoTabsHelpTextVisibility(); + } + } return LLPanel::notifyParent(info); } void LLAccordionCtrl::reset () @@ -745,6 +800,28 @@ void LLAccordionCtrl::reset () mScrollbar->setDocPos(0); } +void LLAccordionCtrl::sort() +{ + if (!mTabComparator) + { + llwarns << "No comparator specified for sorting accordion tabs." << llendl; + return; + } + + std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator)); + arrange(); +} + +void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) +{ + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = mNoVisibleTabsOrigString; + LLStringUtil::format(text, args); + + mNoVisibleTabsHelpText->setValue(text); +} + S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */) { if(tab_index < 0) diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index a029201c90..fc6f2d896c 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -34,6 +34,7 @@ #define LL_ACCORDIONCTRL_H #include "llpanel.h" +#include "lltextbox.h" #include "llscrollbar.h" #include <vector> @@ -56,6 +57,19 @@ private: public: + /** + * Abstract comparator for accordion tabs. + */ + class LLTabComparator + { + public: + LLTabComparator() {}; + virtual ~LLTabComparator() {}; + + /** Returns true if tab1 < tab2, false otherwise */ + virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0; + }; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> { @@ -64,10 +78,12 @@ public: accordion tabs are responsible for scrolling their content. *NOTE fit_parent works best when combined with single_expansion. Accordion view should implement getRequiredRect() and provide valid height*/ + Optional<LLTextBox::Params> empty_accordion_text; Params() : single_expansion("single_expansion",false) , fit_parent("fit_parent", false) + , empty_accordion_text("empty_accordion_text") {}; }; @@ -105,7 +121,18 @@ public: void reset (); + void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } + void sort(); + + /** + * Sets filter substring as a search_term for help text when there are no any visible tabs. + */ + void setFilterSubString(const std::string& filter_string); + private: + void initNoTabsWidget(const LLTextBox::Params& tb_params); + void updateNoTabsHelpTextVisibility(); + void arrangeSinge(); void arrangeMultiple(); @@ -123,6 +150,21 @@ private: BOOL autoScroll (S32 x, S32 y); + /** + * An adaptor for LLTabComparator + */ + struct LLComparatorAdaptor + { + LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {}; + + bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) + { + return mComparator.compare(tab1, tab2); + } + + const LLTabComparator& mComparator; + }; + private: LLRect mInnerRect; LLScrollbar* mScrollbar; @@ -130,7 +172,11 @@ private: bool mFitParent; bool mAutoScrolling; F32 mAutoScrollRate; - LLAccordionCtrlTab* mSelectedTab; + LLTextBox* mNoVisibleTabsHelpText; + std::string mNoVisibleTabsOrigString; + + LLAccordionCtrlTab* mSelectedTab; + const LLTabComparator* mTabComparator; }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 83e67980a3..1bc8086a27 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -409,6 +409,13 @@ void LLAccordionCtrlTab::changeOpenClose(bool is_open) } } +void LLAccordionCtrlTab::handleVisibilityChange(BOOL new_visibility) +{ + LLUICtrl::handleVisibilityChange(new_visibility); + + notifyParent(LLSD().with("child_visibility_change", new_visibility)); +} + BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) { if(mCollapsible && mHeaderVisible && mCanOpenClose) @@ -466,7 +473,7 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel) addChild(panel,0); } -std::string LLAccordionCtrlTab::getTitle() +std::string LLAccordionCtrlTab::getTitle() const { LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); if (header) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 83a9024a74..82e0234bfc 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -115,7 +115,7 @@ public: void setAccordionView(LLView* panel); LLView* getAccordionView() { return mContainerPanel; }; - std::string getTitle(); + std::string getTitle() const; // Set text and highlight substring in LLAccordionCtrlTabHeader void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); @@ -154,6 +154,11 @@ public: // Call reshape after changing size virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /** + * Raises notifyParent event with "child_visibility_change" = new_visibility + */ + void handleVisibilityChange(BOOL new_visibility); + // Changes expand/collapse state and triggers expand/collapse callbacks virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index fad98e553f..341debc9a8 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -810,6 +810,11 @@ void LLFloater::applyTitle() { mDragHandle->setTitle ( mTitle ); } + + if (getHost()) + { + getHost()->updateFloaterTitle(this); + } } std::string LLFloater::getCurrentTitle() const diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 75342afbe2..e9614ea660 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -339,6 +339,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW { if( *cur == '\n' ) { + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base); + text_segment->setToken( 0 ); + insertSegment( *seg_list, text_segment, text_len, defaultColor, editor); cur++; if( !*cur || *cur == '\n' ) { @@ -378,9 +381,8 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } S32 seg_end = cur - base; - LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); - text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + //create segments from seg_start to seg_end + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); line_done = TRUE; // to break out of second loop. break; } @@ -486,11 +488,12 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW seg_end = seg_start + between_delimiters + cur_delimiter->getLength(); } - + insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor); + /* LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); text_segment->setToken( cur_delimiter ); insertSegment( seg_list, text_segment, text_len, defaultColor, editor); - + */ // Note: we don't increment cur, since the end of one delimited seg may be immediately // followed by the start of another one. continue; @@ -519,10 +522,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW // llinfos << "Seg: [" << word.c_str() << "]" << llendl; - - LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); - text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); } cur += seg_len; continue; @@ -537,24 +537,50 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } } -void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>* seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) +void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor ) +{ + std::string::size_type pos = wtext.find('\n',seg_start); + + while (pos!=-1 && pos < (std::string::size_type)seg_end) + { + if (pos!=seg_start) + { + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, pos, editor ); + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + } + + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(pos); + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + + seg_start = pos+1; + pos = wtext.find('\n',seg_start); + } + + LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); + text_segment->setToken( cur_token ); + insertSegment( seg_list, text_segment, text_len, defaultColor, editor); +} + +void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) { - LLTextSegmentPtr last = seg_list->back(); + LLTextSegmentPtr last = seg_list.back(); S32 new_seg_end = new_segment->getEnd(); if( new_segment->getStart() == last->getStart() ) { - seg_list->pop_back(); + seg_list.pop_back(); } else { last->setEnd( new_segment->getStart() ); } - seg_list->push_back( new_segment ); + seg_list.push_back( new_segment ); if( new_seg_end < text_len ) { - seg_list->push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); + seg_list.push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); } } diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index e5b66dfa56..09378e408b 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -129,7 +129,8 @@ public: private: LLColor3 readColor(const std::string& s); - void insertSegment(std::vector<LLTextSegmentPtr> *seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor); + void insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor); + void insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor); BOOL mLoaded; word_token_map_t mWordTokenMap; diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 3aea648562..b1dbce0000 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -238,6 +238,16 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, moveResizeHandlesToFront(); } +void LLMultiFloater::updateFloaterTitle(LLFloater* floaterp) +{ + S32 index = mTabContainer->getIndexForPanel(floaterp); + if (index != -1) + { + mTabContainer->setPanelTitle(index, floaterp->getShortTitle()); + } +} + + /** BOOL selectFloater(LLFloater* floaterp) diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index bbf2c56fe7..24a841f64e 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -80,6 +80,7 @@ public: void onTabSelected(); virtual void updateResizeLimits(); + virtual void updateFloaterTitle(LLFloater* floaterp); protected: struct LLFloaterData diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index d86709c448..72f3a14822 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2743,6 +2743,12 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor) editor->addDocumentChild(mView); } +LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1) +{ + LLStyleSP s( new LLStyle(LLStyle::Params().visible(true))); + + mFontHeight = llceil(s->getFont()->getLineHeight()); +} LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1) { mFontHeight = llceil(style->getFont()->getLineHeight()); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 176308c61a..89ce5cdc8e 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -519,6 +519,7 @@ class LLLineBreakTextSegment : public LLTextSegment public: LLLineBreakTextSegment(LLStyleConstSP style,S32 pos); + LLLineBreakTextSegment(S32 pos); ~LLLineBreakTextSegment(); bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 035e9ddd9c..3c98cd5b85 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -307,6 +307,7 @@ set(viewer_SOURCE_FILES llnotificationstorage.cpp llnotificationtiphandler.cpp lloutfitslist.cpp + lloutfitobserver.cpp lloutputmonitorctrl.cpp llpanelavatar.cpp llpanelavatartag.cpp @@ -825,6 +826,7 @@ set(viewer_HEADER_FILES llnotificationmanager.h llnotificationstorage.h lloutfitslist.h + lloutfitobserver.h lloutputmonitorctrl.h llpanelavatar.h llpanelavatartag.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 864a79c38a..b0211dd85b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -583,7 +583,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>180</integer> + <integer>120</integer> </map> <key>AvatarSex</key> <map> @@ -11417,5 +11417,16 @@ <key>Value</key> <integer>1</integer> </map> + <key>OutfitOperationsTimeout</key> + <map> + <key>Comment</key> + <string>Timeout for outfit related operations.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>180</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index d4000e9253..dc76a4e518 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -1,26 +1,26 @@ <llsd> <map> - <key>BusyModeResponse</key> + <key>BusyResponseChanged</key> <map> <key>Comment</key> - <string>Auto response to instant messages while in busy mode.</string> + <string>Does user's busy mode message differ from default?</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>String</string> + <string>Boolean</string> <key>Value</key> - <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> + <integer>0</integer> </map> - <key>BusyModeResponse2</key> + <key>BusyModeResponse</key> <map> <key>Comment</key> - <string>Auto response to instant messages while in busy mode, clean (unencoded) version of BusyModeResponse</string> + <string>Auto response to instant messages while in busy mode.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>|TOKEN COPY BusyModeResponse|</string> + <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string> </map> <key>InstantMessageLogPath</key> <map> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 644363826a..c3f075fd49 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2360,6 +2360,7 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came mAnimationDuration = gSavedSettings.getF32("ZoomTime"); } } + gAgentAvatarp->updateMeshTextures(); } else { diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index d823a3cbbb..acf43dda1e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -64,6 +64,25 @@ BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; using namespace LLVOAvatarDefines; +/////////////////////////////////////////////////////////////////////////////// + +// Callback to wear and start editing an item that has just been created. +class LLWearAndEditCallback : public LLInventoryCallback +{ + void fire(const LLUUID& inv_item) + { + if (inv_item.isNull()) return; + + // Request editing the item after it gets worn. + gAgentWearables.requestEditingWearable(inv_item); + + // Wear it. + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); + } +}; + +/////////////////////////////////////////////////////////////////////////////// + // HACK: For EXT-3923: Pants item shows in inventory with skin icon and messes with "current look" // Some db items are corrupted, have inventory flags = 0, implying wearable type = shape, even though // wearable type stored in asset is some other value. @@ -732,7 +751,7 @@ U32 LLAgentWearables::pushWearable(const LLWearableType::EType type, LLWearable void LLAgentWearables::wearableUpdated(LLWearable *wearable) { - gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); + gAgentAvatarp->wearableUpdated(wearable->getType(), FALSE); wearable->refreshName(); wearable->setLabelUpdated(); @@ -776,7 +795,7 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index) if (wearable) { mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); + gAgentAvatarp->wearableUpdated(wearable->getType(), FALSE); wearable->setLabelUpdated(); } } @@ -1990,7 +2009,7 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con LLWearable* wearable = LLWearableList::instance().createNewWearable(type); LLAssetType::EType asset_type = wearable->getAssetType(); LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; - LLPointer<LLInventoryCallback> cb = wear ? new WearOnAvatarCallback : NULL; + LLPointer<LLInventoryCallback> cb = wear ? new LLWearAndEditCallback : NULL; LLUUID folder_id; if (parent_id.notNull()) @@ -2013,17 +2032,44 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con // static void LLAgentWearables::editWearable(const LLUUID& item_id) { - LLViewerInventoryItem* item; - LLWearable* wearable; + LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); + if (!item) + { + llwarns << "Failed to get linked item" << llendl; + return; + } + + LLWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); + if (!wearable) + { + llwarns << "Cannot get wearable" << llendl; + return; + } + + if (!gAgentWearables.isWearableModifiable(item->getUUID())) + { + llwarns << "Cannot modify wearable" << llendl; + return; + } + + LLPanel* panel = LLSideTray::getInstance()->getPanel("sidepanel_appearance"); + LLSidepanelAppearance::editWearable(wearable, panel); +} + +// Request editing the item after it gets worn. +void LLAgentWearables::requestEditingWearable(const LLUUID& item_id) +{ + mItemToEdit = gInventory.getLinkedItemID(item_id); +} - if ((item = gInventory.getLinkedItem(item_id)) && - (wearable = gAgentWearables.getWearableFromAssetID(item->getAssetUUID())) && - gAgentWearables.isWearableModifiable(item->getUUID()) && - item->isFinished()) +// Start editing the item if previously requested. +void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id) +{ + if (mItemToEdit.notNull() && + mItemToEdit == gInventory.getLinkedItemID(item_id)) { - LLPanel* panel = LLSideTray::getInstance()->showPanel("panel_outfit_edit", LLSD()); - // copied from LLPanelOutfitEdit::onEditWearableClicked() - LLSidepanelAppearance::editWearable(wearable, panel->getParent()); + LLAgentWearables::editWearable(item_id); + mItemToEdit.setNull(); } } diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 679ecefa6f..a41b949be6 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -148,6 +148,12 @@ public: static void editWearable(const LLUUID& item_id); bool moveWearable(const LLViewerInventoryItem* item, bool closer_to_body); + void requestEditingWearable(const LLUUID& item_id); + void editWearableIfRequested(const LLUUID& item_id); + +private: + LLUUID mItemToEdit; + //-------------------------------------------------------------------- // Removing wearables //-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a899926938..12d2752180 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -38,11 +38,13 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llcommandhandler.h" +#include "lleventtimer.h" #include "llgesturemgr.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llnotificationsutil.h" +#include "lloutfitobserver.h" #include "llpaneloutfitsinventory.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" @@ -55,6 +57,34 @@ char ORDER_NUMBER_SEPARATOR('@'); +class LLOutfitUnLockTimer: public LLEventTimer +{ +public: + LLOutfitUnLockTimer(F32 period) : LLEventTimer(period) + { + // restart timer on BOF changed event + LLOutfitObserver::instance().addBOFChangedCallback(boost::bind( + &LLOutfitUnLockTimer::reset, this)); + stop(); + } + + /*virtual*/ + BOOL tick() + { + if(mEventTimer.hasExpired()) + { + LLAppearanceMgr::instance().setOutfitLocked(false); + } + return FALSE; + } + void stop() { mEventTimer.stop(); } + void start() { mEventTimer.start(); } + void reset() { mEventTimer.reset(); } + BOOL getStarted() { return mEventTimer.getStarted(); } + + LLTimer& getEventTimer() { return mEventTimer;} +}; + // support for secondlife:///app/appearance SLapps class LLAppearanceHandler : public LLCommandHandler { @@ -762,6 +792,27 @@ void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& respo } } +void LLAppearanceMgr::setOutfitLocked(bool locked) +{ + if (mOutfitLocked == locked) + { + return; + } + + mOutfitLocked = locked; + if (locked) + { + mUnlockOutfitTimer->reset(); + mUnlockOutfitTimer->start(); + } + else + { + mUnlockOutfitTimer->stop(); + } + + LLOutfitObserver::instance().notifyOutfitLockChanged(); +} + void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id) { LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); @@ -1810,6 +1861,14 @@ void LLAppearanceMgr::onFirstFullyVisible() bool LLAppearanceMgr::updateBaseOutfit() { + if (isOutfitLocked()) + { + // don't allow modify locked outfit + llassert(!isOutfitLocked()); + return false; + } + setOutfitLocked(true); + const LLUUID base_outfit_id = getBaseOutfitUUID(); if (base_outfit_id.isNull()) return false; @@ -2080,7 +2139,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b bool result = false; if (result = gAgentWearables.moveWearable(item, closer_to_body)) { - gAgentAvatarp->wearableUpdated(item->getWearableType(), TRUE); + gAgentAvatarp->wearableUpdated(item->getWearableType(), FALSE); } setOutfitDirty(true); @@ -2138,6 +2197,14 @@ LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), mOutfitIsDirty(false) { + LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + + // unlock outfit on save operation completed + outfit_observer.addCOFSavedCallback(boost::bind( + &LLAppearanceMgr::setOutfitLocked, this, false)); + + mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32( + "OutfitOperationsTimeout"))); } LLAppearanceMgr::~LLAppearanceMgr() diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f1beef5857..2227a43cd8 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -42,10 +42,12 @@ class LLWearable; class LLWearableHoldingPattern; class LLInventoryCallback; +class LLOutfitUnLockTimer; class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr> { friend class LLSingleton<LLAppearanceMgr>; + friend class LLOutfitUnLockTimer; public: typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t; @@ -162,6 +164,8 @@ public: // COF is processed if cat_id is not specified void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null); + bool isOutfitLocked() { return mOutfitLocked; } + protected: LLAppearanceMgr(); ~LLAppearanceMgr(); @@ -186,10 +190,20 @@ private: static void onOutfitRename(const LLSD& notification, const LLSD& response); + void setOutfitLocked(bool locked); + std::set<LLUUID> mRegisteredAttachments; bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; + /** + * Lock for blocking operations on outfit until server reply or timeout exceed + * to avoid unsynchronized outfit state or performing duplicate operations. + */ + bool mOutfitLocked; + + std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; + ////////////////////////////////////////////////////////////////////////////////// // Item-specific convenience functions public: diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 95084666bb..82bd59d25c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -331,10 +331,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; -std::string gLoginPage; -std::vector<std::string> gLoginURIs; -static std::string gHelperURI; - LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 7a3eddf7a6..41f5fe64a1 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -203,7 +203,9 @@ LLBottomTray::~LLBottomTray() // override effect of save_visibility=true. // this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly: // i.g when floater changes its visibility - button changes its toggle state. + getChild<LLUICtrl>("build_btn")->setControlValue(false); getChild<LLUICtrl>("search_btn")->setControlValue(false); + getChild<LLUICtrl>("world_map_btn")->setControlValue(false); } // *TODO Vadim: why void* ? diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 7ac3d14c72..916d53da3c 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -387,13 +387,7 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory item_panel->childSetAction("btn_edit", mCOFCallbacks.mEditWearable); //turning on gray separator line for the last item in the items group of the same wearable type - if (last) - { - LLRect rect = item_panel->getRect(); - item_panel->reshape(rect.getWidth(), rect.getHeight() + - item_panel->getChild<LLView>("wearable_type_separator_icon")->getRect().getHeight()); - item_panel->childSetVisible("wearable_type_separator_icon", true); - } + item_panel->childSetVisible("wearable_type_separator_icon", last); return item_panel; } @@ -427,7 +421,7 @@ LLPanelDeletableWearableListItem* LLCOFWearables::buildAttachemntListItem(LLView llassert(item); if (!item) return NULL; - LLPanelDeletableWearableListItem* item_panel = LLPanelDeletableWearableListItem::create(item); + LLPanelAttachmentListItem* item_panel = LLPanelAttachmentListItem::create(item); if (!item_panel) return NULL; //setting callbacks diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index ca346138fb..d6effb2b21 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -49,6 +49,9 @@ static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item"); +const F32 NUDGE_TIME = 0.25f; // in seconds +const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed + // Constants const F32 CAMERA_BUTTON_DELAY = 0.0f; @@ -75,6 +78,7 @@ protected: void onZoomPlusHeldDown(); void onZoomMinusHeldDown(); void onSliderValueChanged(); + F32 getOrbitRate(F32 time); private: LLButton* mPlusBtn; @@ -155,8 +159,8 @@ LLPanelCameraZoom::LLPanelCameraZoom() mMinusBtn( NULL ), mSlider( NULL ) { - mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this)); - mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this)); + mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this)); + mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this)); mCommitCallbackRegistrar.add("Slider.value_changed", boost::bind(&LLPanelCameraZoom::onSliderValueChanged, this)); } @@ -179,9 +183,9 @@ void LLPanelCameraZoom::onZoomPlusHeldDown() F32 val = mSlider->getValueF32(); F32 inc = mSlider->getIncrement(); mSlider->setValue(val - inc); - // commit only if value changed - if (val != mSlider->getValueF32()) - mSlider->onCommit(); + F32 time = mPlusBtn->getHeldDownTime(); + gAgentCamera.unlockView(); + gAgentCamera.setOrbitInKey(getOrbitRate(time)); } void LLPanelCameraZoom::onZoomMinusHeldDown() @@ -189,9 +193,22 @@ void LLPanelCameraZoom::onZoomMinusHeldDown() F32 val = mSlider->getValueF32(); F32 inc = mSlider->getIncrement(); mSlider->setValue(val + inc); - // commit only if value changed - if (val != mSlider->getValueF32()) - mSlider->onCommit(); + F32 time = mMinusBtn->getHeldDownTime(); + gAgentCamera.unlockView(); + gAgentCamera.setOrbitOutKey(getOrbitRate(time)); +} + +F32 LLPanelCameraZoom::getOrbitRate(F32 time) +{ + if( time < NUDGE_TIME ) + { + F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; + return rate; + } + else + { + return 1; + } } void LLPanelCameraZoom::onSliderValueChanged() diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 8fa7a53996..564e38d02d 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -39,7 +39,6 @@ #include "llflatlistview.h" class LLJoystickCameraRotate; -class LLJoystickCameraZoom; class LLJoystickCameraTrack; class LLFloaterReg; class LLPanelCameraZoom; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5fbbb2c1a8..2299cd719c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -330,9 +330,28 @@ BOOL LLFloaterPreference::postBuild() std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); childSetText("cache_location", cache_location); + // if floater is opened before login set default localized busy message + if (LLStartUp::getStartupState() < STATE_STARTED) + { + gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + } + return TRUE; } +void LLFloaterPreference::onBusyResponseChanged() +{ + // set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise + if(LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) + { + gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); + } + else + { + gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); + } +} + LLFloaterPreference::~LLFloaterPreference() { // clean up user data @@ -487,6 +506,22 @@ void LLFloaterPreference::cancel() void LLFloaterPreference::onOpen(const LLSD& key) { + // this variable and if that follows it are used to properly handle busy mode response message + static bool initialized = FALSE; + // if user is logged in and we haven't initialized busy_response yet, do it + if (!initialized && LLStartUp::getStartupState() == STATE_STARTED) + { + // Special approach is used for busy response localization, because "BusyModeResponse" is + // in non-localizable xml, and also because it may be changed by user and in this case it shouldn't be localized. + // To keep track of whether busy response is default or changed by user additional setting BusyResponseChanged + // was added into per account settings. + + // initialization should happen once,so setting variable to TRUE + initialized = TRUE; + // this connection is needed to properly set "BusyResponseChanged" setting when user makes changes in + // busy response message. + gSavedPerAccountSettings.getControl("BusyModeResponse")->getSignal()->connect(boost::bind(&LLFloaterPreference::onBusyResponseChanged, this)); + } gAgent.sendAgentUserInfoRequest(); /////////////////////////// From LLPanelGeneral ////////////////////////// @@ -540,6 +575,16 @@ void LLFloaterPreference::onVertexShaderEnable() refreshEnabledGraphics(); } +//static +void LLFloaterPreference::initBusyResponse() + { + if (!gSavedPerAccountSettings.getBOOL("BusyResponseChanged")) + { + //LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885) + gSavedPerAccountSettings.setString("BusyModeResponse", LLTrans::getString("BusyModeResponseDefault")); + } + } + void LLFloaterPreference::setHardwareDefaults() { LLFeatureManager::getInstance()->applyRecommendedSettings(); @@ -960,18 +1005,6 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data) refresh(); } -// static -// DEV-24146 - needs to be removed at a later date. jan-2009 -void LLFloaterPreference::cleanupBadSetting() -{ - if (gSavedPerAccountSettings.getString("BusyModeResponse2") == "|TOKEN COPY BusyModeResponse|") - { - llinfos << "cleaning old BusyModeResponse" << llendl; - //LLTrans::getString("BusyModeResponseDefault") is used here for localization (EXT-5885) - gSavedPerAccountSettings.setString("BusyModeResponse2", LLTrans::getString("BusyModeResponseDefault")); - } -} - void LLFloaterPreference::onClickSetKey() { LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance<LLVoiceSetKeyDialog>("voice_set_key", LLSD(), TRUE); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 71aa5d3189..b45e09db7d 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -80,6 +80,9 @@ public: // refresh all the graphics preferences menus static void refreshEnabledGraphics(); + // translate user's busy response message according to current locale if message is default, otherwise do nothing + static void initBusyResponse(); + protected: void onBtnOK(); void onBtnCancel(); @@ -87,6 +90,9 @@ protected: void onClickBrowserClearCache(); + // set value of "BusyResponseChanged" in account settings depending on whether busy response + // string differs from default after user changes. + void onBusyResponseChanged(); // if the custom settings box is clicked void onChangeCustom(); void updateMeterText(LLUICtrl* ctrl); @@ -140,7 +146,6 @@ public: void buildPopupLists(); static void refreshSkin(void* data); - static void cleanupBadSetting(); private: static std::string sSkin; bool mGotPersonalInfo; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 5bea3325a8..00981d3c25 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -91,10 +91,6 @@ ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -S32 LLFloaterSnapshot::sUIWinHeightLong = 526 ; -S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 230 ; -S32 LLFloaterSnapshot::sUIWinWidth = 215 ; - LLSnapshotFloaterView* gSnapshotFloaterView = NULL; const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -1172,9 +1168,6 @@ public: } static void onClickNewSnapshot(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); - //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); - static void onClickLess(void* data) ; - static void onClickMore(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); static void onClickHUDCheck(LLUICtrl *ctrl, void* data); static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); @@ -1188,7 +1181,7 @@ public: static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); static void onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type); static void onCommitProfilePic(LLFloaterSnapshot* view); - static void onToggleAdvanced(LLUICtrl *ctrl, void* data); + static void showAdvanced(LLFloaterSnapshot* view, const BOOL visible); static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); @@ -1399,41 +1392,6 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) } } -void LLFloaterSnapshot::Impl::onClickMore(void* data) -{ - gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() ); - view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); - updateControls(view) ; - updateLayout(view) ; - if(getPreviewView(view)) - { - getPreviewView(view)->setThumbnailImageSize() ; - } - } -} -void LLFloaterSnapshot::Impl::onClickLess(void* data) -{ - gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() ); - view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); - updateControls(view) ; - updateLayout(view) ; - if(getPreviewView(view)) - { - getPreviewView(view)->setThumbnailImageSize() ; - } - } -} - // static void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) { @@ -1691,30 +1649,28 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data) } //static -void LLFloaterSnapshot::Impl::onToggleAdvanced(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::showAdvanced(LLFloaterSnapshot* view, const BOOL visible) { - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLPanel* advanced_panel = view->getChild<LLPanel>("snapshot_advanced"); - if (advanced_panel->getVisible()) + if (advanced_panel->getVisible() != visible) { - advanced_panel->setVisible(false); + gSavedSettings.setBOOL("AdvanceSnapshot", visible); - // shrink floater back to original size - view->reshape(view->getRect().getWidth() - advanced_panel->getRect().getWidth(), view->getRect().getHeight()); + advanced_panel->setVisible(visible); + view->getChild<LLButton>("hide_advanced")->setVisible(visible); + view->getChild<LLButton>("show_advanced")->setVisible(!visible); - view->getChild<LLButton>("hide_advanced")->setVisible(false); - view->getChild<LLButton>("show_advanced")->setVisible(true); - } - else - { - advanced_panel->setVisible(true); - // stretch the floater so it can accommodate the advanced panel - view->reshape(view->getRect().getWidth() + advanced_panel->getRect().getWidth(), view->getRect().getHeight()); - - view->getChild<LLButton>("hide_advanced")->setVisible(true); - view->getChild<LLButton>("show_advanced")->setVisible(false); + if (visible) + { + // stretch the floater so it can accommodate the advanced panel + view->reshape(view->getRect().getWidth() + advanced_panel->getRect().getWidth(), view->getRect().getHeight()); + } + else + { + // shrink floater back to original size + view->reshape(view->getRect().getWidth() - advanced_panel->getRect().getWidth(), view->getRect().getHeight()); + } } } @@ -2002,6 +1958,11 @@ LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) impl (*(new Impl)) { //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_snapshot.xml", FALSE); + + mCommitCallbackRegistrar.add("Snapshot.ShowButtons", boost::bind(&LLFloaterSnapshot::updateButtons, this, _2)); + mCommitCallbackRegistrar.add("Snapshot.ShowAdvanced", boost::bind(&Impl::showAdvanced, this, true)); + mCommitCallbackRegistrar.add("Snapshot.HideAdvanced", boost::bind(&Impl::showAdvanced, this, false)); + mCommitCallbackRegistrar.add("Snapshot.Refresh", boost::bind(&Impl::onClickNewSnapshot, this)); } // Destroys the object @@ -2023,27 +1984,14 @@ LLFloaterSnapshot::~LLFloaterSnapshot() BOOL LLFloaterSnapshot::postBuild() { - - getChild<LLButton>("share")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_SHARE)); - getChild<LLButton>("save")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_SAVE)); - getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_MAIN)); - getChild<LLButton>("share_to_web")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_WEB)); getChild<LLButton>("share_to_email")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_POSTCARD)); getChild<LLButton>("save_to_inventory")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_TEXTURE)); getChild<LLButton>("save_to_computer")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_LOCAL)); getChild<LLButton>("set_profile_pic")->setCommitCallback(boost::bind(&Impl::onCommitProfilePic, this)); - childSetCommitCallback("show_advanced", Impl::onToggleAdvanced, this); - childSetCommitCallback("hide_advanced", Impl::onToggleAdvanced, this); - childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); - childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); - - childSetAction("more_btn", Impl::onClickMore, this); - childSetAction("less_btn", Impl::onClickLess, this); - childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality")); @@ -2095,12 +2043,13 @@ BOOL LLFloaterSnapshot::postBuild() impl.mPreviewHandle = previewp->getHandle(); impl.updateControls(this); impl.updateLayout(this); + impl.showAdvanced(this, gSavedSettings.getBOOL("AdvanceSnapshot")); //save off the refresh button's rectangle so we can apply offsets with thumbnail resize mRefreshBtnRect = getChild<LLButton>("new_snapshot_btn")->getRect(); // make sure we share/hide the general buttons - updateButtons(SNAPSHOT_MAIN); + updateButtons(LLSD("main")); return LLDockableFloater::postBuild(); } @@ -2190,19 +2139,20 @@ void LLFloaterSnapshot::update() } } -bool LLFloaterSnapshot::updateButtons(ESnapshotMode mode) +bool LLFloaterSnapshot::updateButtons(const LLSD& mode) { - childSetVisible("share", mode == SNAPSHOT_MAIN); - childSetVisible("save", mode == SNAPSHOT_MAIN); - childSetVisible("set_profile_pic", mode == SNAPSHOT_MAIN); + std::string button_mode = mode.asString(); -// childSetVisible("share_to_web", mode == SNAPSHOT_SHARE); - childSetVisible("share_to_email", mode == SNAPSHOT_SHARE); + bool mode_main("main" == button_mode); + bool mode_share("share" == button_mode); + bool mode_save("save" == button_mode); - childSetVisible("save_to_inventory", mode == SNAPSHOT_SAVE); - childSetVisible("save_to_computer", mode == SNAPSHOT_SAVE); + // Default to a known state if mode is invalid. + if (!mode_main && !mode_share && !mode_save) mode_main = true; - childSetVisible("cancel", mode != SNAPSHOT_MAIN); + childSetVisible("panel_snapshot_main", mode_main); + childSetVisible("panel_snapshot_share", mode_share); + childSetVisible("panel_snapshot_save", mode_save); return true; } diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 931d355748..8c4373c35c 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -47,13 +47,6 @@ public: SNAPSHOT_FORMAT_BMP } ESnapshotFormat; - enum ESnapshotMode - { - SNAPSHOT_SHARE, - SNAPSHOT_SAVE, - SNAPSHOT_MAIN - }; - LLFloaterSnapshot(const LLSD& key); virtual ~LLFloaterSnapshot(); @@ -66,7 +59,7 @@ public: void setAsProfilePic(const LLUUID& image_id); - bool updateButtons(ESnapshotMode mode); + bool updateButtons(const LLSD& mode); static S32 getUIWinHeightLong() {return sUIWinHeightLong ;} static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3aa9d75bc0..967f38bfd2 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -60,8 +60,14 @@ #include "llinventorymodel.h" #include "llrootview.h" #include "llspeakers.h" +#include "llsidetray.h" +static const S32 RECT_PADDING_NOT_INIT = -1; +static const S32 RECT_PADDING_NEED_RECALC = -2; + +S32 LLIMFloater::sAllowedRectRightPadding = RECT_PADDING_NOT_INIT; + LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id), mControlPanel(NULL), @@ -444,19 +450,44 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) return floater; } +//static +bool LLIMFloater::resetAllowedRectPadding(const LLSD& newvalue) +{ + //reset allowed rect right padding if "SidebarCameraMovement" option + //or sidebar state changed + sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC ; + return true; +} + void LLIMFloater::getAllowedRect(LLRect& rect) { + if (sAllowedRectRightPadding == RECT_PADDING_NOT_INIT) //wasn't initialized + { + gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2)); + + LLSideTray* side_bar = LLSideTray::getInstance(); + side_bar->getCollapseSignal().connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2)); + sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC; + } + rect = gViewerWindow->getWorldViewRectScaled(); - static S32 right_padding = 0; - if (right_padding == 0) + if (sAllowedRectRightPadding == RECT_PADDING_NEED_RECALC) //recalc allowed rect right padding { LLPanel* side_bar_tabs = gViewerWindow->getRootView()->getChild<LLPanel> ( "side_bar_tabs"); - right_padding = side_bar_tabs->getRect().getWidth(); + sAllowedRectRightPadding = side_bar_tabs->getRect().getWidth(); LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs); + + if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE) + { + LLSideTray* side_bar = LLSideTray::getInstance(); + + if (side_bar->getVisible() && !side_bar->getCollapsed()) + sAllowedRectRightPadding += side_bar->getRect().getWidth(); + } } - rect.mRight -= right_padding; + rect.mRight -= sAllowedRectRightPadding; } void LLIMFloater::setDocked(bool docked, bool pop_on_undock) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index fef178e3a2..f1e68a2b3d 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -155,6 +155,10 @@ private: static void closeHiddenIMToasts(); + static bool resetAllowedRectPadding(const LLSD& newvalue); + //need to keep this static for performance issues + static S32 sAllowedRectRightPadding; + static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); LLPanelChatControlPanel* mControlPanel; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 33b52cfd5e..c82ebd1439 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -324,6 +324,19 @@ private: LLWearableType::EType mWearableType; }; +/** Filter out wearables-links */ +class LLFindActualWearablesOfType : public LLFindWearablesOfType +{ +public: + LLFindActualWearablesOfType(LLWearableType::EType type) : LLFindWearablesOfType(type) {} + virtual ~LLFindActualWearablesOfType() {} + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if (item && item->getIsLinkType()) return false; + return LLFindWearablesOfType::operator()(cat, item); + } +}; + // Find worn items. class LLFindWorn : public LLInventoryCollectFunctor { diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 0dd6f53be7..2c60d38cb5 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -177,7 +177,10 @@ protected: void setIconImage(const LLUIImagePtr& image); /** Set item title - inventory item name usually */ - void setTitle(const std::string& title, const std::string& highlit_text); + virtual void setTitle(const std::string& title, const std::string& highlit_text); + + + LLViewerInventoryItem* mItem; // force not showing link icon on item's icon bool mForceNoLinksOnIcons; @@ -196,7 +199,6 @@ private: /** reshape remaining widgets */ void reshapeMiddleWidgets(); - LLViewerInventoryItem* mItem; LLIconCtrl* mIconCtrl; LLTextBox* mTitleCtrl; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6fc5804a48..15760bf155 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -721,8 +721,20 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) // Valid UUID; set the item UUID and rename it new_item->setCreator(id); std::string avatar_name; - // Fetch the currect name - gCacheName->get(id, FALSE, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2, _3)); + + if (gCacheName->getFullName(id, avatar_name)) + { + new_item->rename(avatar_name); + mask |= LLInventoryObserver::LABEL; + } + else + { + // Fetch the current name + gCacheName->get(id, FALSE, + boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), + _1, _2, _3)); + } + } } else if (new_item->getType() == LLAssetType::AT_GESTURE) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index b4f0947b2c..ce44e37017 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -33,15 +33,14 @@ #include "llviewerprecompiledheaders.h" #include "llinventorymodelbackgroundfetch.h" -// Seraph clean this up #include "llagent.h" +#include "llappviewer.h" +#include "llcallbacklist.h" #include "llinventorypanel.h" #include "llviewercontrol.h" #include "llviewermessage.h" -#include "llviewerwindow.h" -#include "llappviewer.h" #include "llviewerregion.h" -#include "llcallbacklist.h" +#include "llviewerwindow.h" const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; const S32 MAX_FETCH_RETRIES = 10; @@ -63,47 +62,47 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch() { } -bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() +bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const { return mFetchQueue.empty() && mBulkFetchCount<=0; } -bool LLInventoryModelBackgroundFetch::libraryFetchStarted() +bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const { return mRecursiveLibraryFetchStarted; } -bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() +bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() const { return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID()); } -bool LLInventoryModelBackgroundFetch::libraryFetchInProgress() +bool LLInventoryModelBackgroundFetch::libraryFetchInProgress() const { return libraryFetchStarted() && !libraryFetchCompleted(); } -bool LLInventoryModelBackgroundFetch::inventoryFetchStarted() +bool LLInventoryModelBackgroundFetch::inventoryFetchStarted() const { return mRecursiveInventoryFetchStarted; } -bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() +bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() const { return inventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID()); } -bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() +bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() const { return inventoryFetchStarted() && !inventoryFetchCompleted(); } -bool LLInventoryModelBackgroundFetch::isEverythingFetched() +bool LLInventoryModelBackgroundFetch::isEverythingFetched() const { return mAllFoldersFetched; } -BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() +BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const { return mBackgroundFetchActive; } @@ -132,7 +131,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive } else { - // specific folder requests go to front of queue + // Specific folder requests go to front of queue. if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id) { mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive)); @@ -187,7 +186,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() { if (mBackgroundFetchActive && gAgent.getRegion()) { - //If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); if (!url.empty()) { @@ -195,8 +194,12 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() return; } - //DEPRECATED OLD CODE FOLLOWS. - // no more categories to fetch, stop fetch process +#if 1 + //-------------------------------------------------------------------------------- + // DEPRECATED OLD CODE + // + + // No more categories to fetch, stop fetch process. if (mFetchQueue.empty()) { llinfos << "Inventory fetch completed" << llendl; @@ -209,11 +212,11 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() F32 slow_fetch_time = lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.5f); if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() > slow_fetch_time) { - // double timeouts on failure + // Double timeouts on failure. mMinTimeBetweenFetches = llmin(mMinTimeBetweenFetches * 2.f, 10.f); mMaxTimeBetweenFetches = llmin(mMaxTimeBetweenFetches * 2.f, 120.f); llinfos << "Inventory fetch times grown to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; - // fetch is no longer considered "timely" although we will wait for full time-out + // fetch is no longer considered "timely" although we will wait for full time-out. mTimelyFetchPending = FALSE; } @@ -226,14 +229,14 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() if(gDisconnected) { - // just bail if we are disconnected. + // Just bail if we are disconnected. break; } const FetchQueueInfo info = mFetchQueue.front(); LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID); - // category has been deleted, remove from queue. + // Category has been deleted, remove from queue. if (!cat) { mFetchQueue.pop_front(); @@ -243,8 +246,8 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches && LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) { - // category exists but has no children yet, fetch the descendants - // for now, just request every time and rely on retry timer to throttle + // Category exists but has no children yet, fetch the descendants + // for now, just request every time and rely on retry timer to throttle. if (cat->fetch()) { mFetchTimer.reset(); @@ -258,13 +261,13 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() break; } } - // do I have all my children? + // Do I have all my children? else if (gInventory.isCategoryComplete(info.mCatUUID)) { - // finished with this category, remove from queue + // Finished with this category, remove from queue. mFetchQueue.pop_front(); - // add all children to queue + // Add all children to queue. LLInventoryModel::cat_array_t* categories; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); @@ -275,10 +278,10 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive)); } - // we received a response in less than the fast time + // We received a response in less than the fast time. if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time) { - // shrink timeouts based on success + // Shrink timeouts based on success. mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); //llinfos << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; @@ -289,8 +292,8 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() } else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) { - // received first packet, but our num descendants does not match db's num descendants - // so try again later + // Received first packet, but our num descendants does not match db's num descendants + // so try again later. mFetchQueue.pop_front(); if (mNumFetchRetries++ < MAX_FETCH_RETRIES) @@ -303,9 +306,14 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() break; } - // not enough time has elapsed to do a new fetch + // Not enough time has elapsed to do a new fetch break; } + + // + // DEPRECATED OLD CODE + //-------------------------------------------------------------------------------- +#endif } } @@ -333,10 +341,10 @@ protected: BOOL getIsRecursive(const LLUUID& cat_id) const; private: LLSD mRequestSD; - uuid_vec_t mRecursiveCatUUIDs; // Hack for storing away which cat fetches are recursive. + uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive }; -//If we get back a normal response, handle it here +// If we get back a normal response, handle it here. void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) { LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); @@ -428,7 +436,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) gInventory.updateItem(titem); } - // set version and descendentcount according to message. + // Set version and descendentcount according to message. LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id); if(cat) { @@ -448,7 +456,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) { LLSD folder_sd = *folder_it; - //These folders failed on the dataserver. We probably don't want to retry them. + // These folders failed on the dataserver. We probably don't want to retry them. llinfos << "Folder " << folder_sd["folder_id"].asString() << "Error: " << folder_sd["error"].asString() << llendl; } @@ -465,7 +473,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) gInventory.notifyObservers("fetchDescendents"); } -//If we get back an error (not found, etc...), handle it here +// If we get back an error (not found, etc...), handle it here. void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason) { LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); @@ -475,7 +483,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str fetcher->incrBulkFetch(-1); - if (status==499) // Timed out. + if (status==499) // timed out { for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); folder_it != mRequestSD["folders"].endArray(); @@ -502,7 +510,8 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end()); } -//static Bundle up a bunch of requests to send all at once. +// Bundle up a bunch of requests to send all at once. +// static void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) { //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. @@ -521,7 +530,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) (mBulkFetchCount > max_concurrent_fetches) || (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) { - return; // just bail if we are disconnected. + return; // just bail if we are disconnected } U32 folder_count=0; diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index c1e37eda8f..04f96586d7 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -33,39 +33,15 @@ #ifndef LL_LLINVENTORYMODELBACKGROUNDFETCH_H #define LL_LLINVENTORYMODELBACKGROUNDFETCH_H -// Seraph clean this up -#include "llassettype.h" -#include "llfoldertype.h" -#include "lldarray.h" -#include "llframetimer.h" -#include "llhttpclient.h" +#include "llsingleton.h" #include "lluuid.h" -#include "llpermissionsflags.h" -#include "llstring.h" -#include <map> -#include <set> -#include <string> -#include <vector> - -// Seraph clean this up -class LLInventoryObserver; -class LLInventoryObject; -class LLInventoryItem; -class LLInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLMessageSystem; -class LLInventoryCollectFunctor; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryModelBackgroundFetch // -// This class handles background fetch. +// This class handles background fetches, which are fetches of +// inventory folder. Fetches can be recursive or not. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch> { friend class LLInventoryModelFetchDescendentsResponder; @@ -75,48 +51,37 @@ public: ~LLInventoryModelBackgroundFetch(); // Start and stop background breadth-first fetching of inventory contents. - // This gets triggered when performing a filter-search + // This gets triggered when performing a filter-search. void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); - BOOL backgroundFetchActive(); - bool isEverythingFetched(); - void incrBulkFetch(S16 fetching); - void stopBackgroundFetch(); // stop fetch process - bool isBulkFetchProcessingComplete(); - // Add categories to a list to be fetched in bulk. - void bulkFetch(std::string url); + BOOL backgroundFetchActive() const; + bool isEverythingFetched() const; // completing the fetch once per session should be sufficient - bool libraryFetchStarted(); - bool libraryFetchCompleted(); - bool libraryFetchInProgress(); + bool libraryFetchStarted() const; + bool libraryFetchCompleted() const; + bool libraryFetchInProgress() const; - bool inventoryFetchStarted(); - bool inventoryFetchCompleted(); - bool inventoryFetchInProgress(); - void findLostItems(); + bool inventoryFetchStarted() const; + bool inventoryFetchCompleted() const; + bool inventoryFetchInProgress() const; - void setAllFoldersFetched(); + void findLostItems(); +protected: + void incrBulkFetch(S16 fetching); + bool isBulkFetchProcessingComplete() const; + void bulkFetch(std::string url); - static void backgroundFetchCB(void*); // background fetch idle function void backgroundFetch(); - - struct FetchQueueInfo - { - FetchQueueInfo(const LLUUID& id, BOOL recursive) : - mCatUUID(id), mRecursive(recursive) - { - } - LLUUID mCatUUID; - BOOL mRecursive; - }; -protected: + static void backgroundFetchCB(void*); // background fetch idle function + void stopBackgroundFetch(); // stop fetch process + + void setAllFoldersFetched(); bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; private: BOOL mRecursiveInventoryFetchStarted; BOOL mRecursiveLibraryFetchStarted; BOOL mAllFoldersFetched; - // completing the fetch once per session should be sufficient BOOL mBackgroundFetchActive; S16 mBulkFetchCount; BOOL mTimelyFetchPending; @@ -126,6 +91,15 @@ private: F32 mMinTimeBetweenFetches; F32 mMaxTimeBetweenFetches; + struct FetchQueueInfo + { + FetchQueueInfo(const LLUUID& id, BOOL recursive) : + mCatUUID(id), mRecursive(recursive) + { + } + LLUUID mCatUUID; + BOOL mRecursive; + }; typedef std::deque<FetchQueueInfo> fetch_queue_t; fetch_queue_t mFetchQueue; }; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index d2b402fe14..bd35259670 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -62,13 +62,9 @@ #include "llsdutil.h" #include <deque> -// If the viewer gets a notification, your observer assumes -// that that notification is for itself and then tries to process -// the results. The notification could be for something else (e.g. -// you're fetching an item and a notification gets triggered because -// you renamed some other item). This counter is to specify how many -// notification to wait for before giving up. -static const U32 MAX_NUM_NOTIFICATIONS_TO_PROCESS = 127; +const U32 LLInventoryFetchItemsObserver::MAX_NUM_ATTEMPTS_TO_PROCESS = 10; +const F32 LLInventoryFetchItemsObserver::FETCH_TIMER_EXPIRY = 10.0f; + LLInventoryObserver::LLInventoryObserver() { @@ -149,7 +145,7 @@ void LLInventoryCompletionObserver::watchItem(const LLUUID& id) LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_id) : LLInventoryFetchObserver(item_id), - mNumTries(MAX_NUM_NOTIFICATIONS_TO_PROCESS) + mNumTries(MAX_NUM_ATTEMPTS_TO_PROCESS) { mIDs.clear(); mIDs.push_back(item_id); @@ -158,35 +154,47 @@ LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_ LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids) : LLInventoryFetchObserver(item_ids), - mNumTries(MAX_NUM_NOTIFICATIONS_TO_PROCESS) + mNumTries(MAX_NUM_ATTEMPTS_TO_PROCESS) { } void LLInventoryFetchItemsObserver::changed(U32 mask) { - BOOL any_items_missing = FALSE; - // scan through the incomplete items and move or erase them as // appropriate. if (!mIncomplete.empty()) { + // if period of an attempt expired... + if (mFetchingPeriod.hasExpired()) + { + // ...reset timer and reduce count of attempts + mFetchingPeriod.reset(); + mFetchingPeriod.setTimerExpirySec(FETCH_TIMER_EXPIRY); + + --mNumTries; + + LL_INFOS("InventoryFetch") << "LLInventoryFetchItemsObserver: " << this << ", attempt(s) left: " << (S32)mNumTries << LL_ENDL; + } + + // do we still have any attempts? + bool timeout_expired = mNumTries <= 0; + for (uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) { const LLUUID& item_id = (*it); LLViewerInventoryItem* item = gInventory.getItem(item_id); if (!item) { - any_items_missing = TRUE; - if (mNumTries > 0) + if (timeout_expired) { - // Keep trying. - ++it; + // Just concede that this item hasn't arrived in reasonable time and continue on. + LL_WARNS("InventoryFetch") << "Fetcher timed out when fetching inventory item UUID: " << item_id << LL_ENDL; + it = mIncomplete.erase(it); } else { - // Just concede that this item hasn't arrived in reasonable time and continue on. - llwarns << "Fetcher timed out when fetching inventory item assetID:" << item_id << llendl; - it = mIncomplete.erase(it); + // Keep trying. + ++it; } continue; } @@ -198,14 +206,10 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) } ++it; } - if (any_items_missing) - { - mNumTries--; - } if (mIncomplete.empty()) { - mNumTries = MAX_NUM_NOTIFICATIONS_TO_PROCESS; + mNumTries = MAX_NUM_ATTEMPTS_TO_PROCESS; done(); } } @@ -315,6 +319,10 @@ void LLInventoryFetchItemsObserver::startFetch() item_entry["item_id"] = (*it); items_llsd.append(item_entry); } + + mFetchingPeriod.resetWithExpiry(FETCH_TIMER_EXPIRY); + mNumTries = MAX_NUM_ATTEMPTS_TO_PROCESS; + fetch_items_from_llsd(items_llsd); } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 6d5a86a6fc..72c13f55c6 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -110,6 +110,22 @@ public: /*virtual*/ void changed(U32 mask); private: S8 mNumTries; // Number of times changed() was called without success + LLFrameTimer mFetchingPeriod; + + /** + * If the viewer gets a notification, your observer assumes + * that that notification is for itself and then tries to process + * the results. The notification could be for something else (e.g. + * you're fetching an item and a notification gets triggered because + * you renamed some other item). This counter is to specify how many + * periods of time to wait for before giving up. + */ + static const U32 MAX_NUM_ATTEMPTS_TO_PROCESS; + + /** + * Period of waiting a notification when requested items get added into inventory. + */ + static const F32 FETCH_TIMER_EXPIRY; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 9e1dc3a4b0..c2a1923dfe 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -53,7 +53,6 @@ static LLDefaultChildRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide"); static LLDefaultChildRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn"); static LLDefaultChildRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate"); -static LLDefaultChildRegistry::Register<LLJoystickCameraZoom> r4("joystick_zoom"); static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_track"); @@ -647,155 +646,3 @@ void LLJoystickCameraTrack::onHeldDown() gAgentCamera.setPanDownKey(getOrbitRate()); } } - - - -//------------------------------------------------------------------------------- -// LLJoystickCameraZoom -//------------------------------------------------------------------------------- - -LLJoystickCameraZoom::LLJoystickCameraZoom(const LLJoystickCameraZoom::Params& p) -: LLJoystick(p), - mInTop( FALSE ), - mInBottom( FALSE ), - mPlusInImage(p.plus_image), - mMinusInImage(p.minus_image) -{ -} - -BOOL LLJoystickCameraZoom::handleMouseDown(S32 x, S32 y, MASK mask) -{ - BOOL handled = LLJoystick::handleMouseDown(x, y, mask); - - if( handled ) - { - if (mFirstMouse.mY > getRect().getHeight() / 2) - { - mInitialQuadrant = JQ_UP; - } - else - { - mInitialQuadrant = JQ_DOWN; - } - } - return handled; -} - - -void LLJoystickCameraZoom::onHeldDown() -{ - updateSlop(); - - const F32 FAST_RATE = 2.5f; // two and a half times the normal rate - - S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY; - - if (dy > mVertSlopFar) - { - // Zoom in fast - gAgentCamera.unlockView(); - gAgentCamera.setOrbitInKey(FAST_RATE); - } - else if (dy > mVertSlopNear) - { - // Zoom in slow - gAgentCamera.unlockView(); - gAgentCamera.setOrbitInKey(getOrbitRate()); - } - else if (dy < -mVertSlopFar) - { - // Zoom out fast - gAgentCamera.unlockView(); - gAgentCamera.setOrbitOutKey(FAST_RATE); - } - else if (dy < -mVertSlopNear) - { - // Zoom out slow - gAgentCamera.unlockView(); - gAgentCamera.setOrbitOutKey(getOrbitRate()); - } -} - -// Only used for drawing -void LLJoystickCameraZoom::setToggleState( BOOL top, BOOL bottom ) -{ - mInTop = top; - mInBottom = bottom; -} - -void LLJoystickCameraZoom::draw() -{ - if( mInTop ) - { - mPlusInImage->draw(0,0); - } - else - if( mInBottom ) - { - mMinusInImage->draw(0,0); - } - else - { - getImageUnselected()->draw( 0, 0 ); - } -} - -void LLJoystickCameraZoom::updateSlop() -{ - mVertSlopNear = getRect().getHeight() / 4; - mVertSlopFar = getRect().getHeight() / 2; - - mHorizSlopNear = getRect().getWidth() / 4; - mHorizSlopFar = getRect().getWidth() / 2; - - // Compute initial mouse offset based on initial quadrant. - // Place the mouse evenly between the near and far zones. - switch (mInitialQuadrant) - { - case JQ_ORIGIN: - mInitialOffset.set(0, 0); - break; - - case JQ_UP: - mInitialOffset.mX = 0; - mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2; - break; - - case JQ_DOWN: - mInitialOffset.mX = 0; - mInitialOffset.mY = - (mVertSlopNear + mVertSlopFar) / 2; - break; - - case JQ_LEFT: - mInitialOffset.mX = - (mHorizSlopNear + mHorizSlopFar) / 2; - mInitialOffset.mY = 0; - break; - - case JQ_RIGHT: - mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2; - mInitialOffset.mY = 0; - break; - - default: - llerrs << "LLJoystick::LLJoystick() - bad switch case" << llendl; - break; - } - - return; -} - - -F32 LLJoystickCameraZoom::getOrbitRate() -{ - F32 time = getElapsedHeldDownTime(); - if( time < NUDGE_TIME ) - { - F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME; -// llinfos << "rate " << rate << " time " << time << llendl; - return rate; - } - else - { - return 1; - } -} diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index 2b071a8999..1dd30036ab 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -183,44 +183,4 @@ public: virtual void onHeldDown(); }; - -// Zoom the camera in and out -class LLJoystickCameraZoom -: public LLJoystick -{ -public: - struct Params - : public LLInitParam::Block<Params, LLJoystick::Params> - { - Optional<LLUIImage*> plus_image; - Optional<LLUIImage*> minus_image; - - Params() - : plus_image ("plus_image", NULL), - minus_image ("minus_image", NULL) - { - held_down_delay.seconds(0.0); - } - }; - LLJoystickCameraZoom(const Params&); - - virtual void setToggleState( BOOL top, BOOL bottom ); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual void onHeldDown(); - virtual void draw(); - -protected: - virtual void updateSlop(); - F32 getOrbitRate(); - -protected: - BOOL mInTop; - BOOL mInBottom; - LLUIImagePtr mPlusInImage; - LLUIImagePtr mMinusInImage; -}; - - - #endif // LL_LLJOYSTICKBUTTON_H diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp new file mode 100644 index 0000000000..5652a98981 --- /dev/null +++ b/indra/newview/lloutfitobserver.cpp @@ -0,0 +1,136 @@ +/** + * @file lloutfitobserver.cpp + * @brief Outfit observer facade. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llappearancemgr.h" +#include "lloutfitobserver.h" +#include "llinventorymodel.h" +#include "llviewerinventory.h" + +LLOutfitObserver::LLOutfitObserver() : + mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) +{ + gInventory.addObserver(this); +} + +LLOutfitObserver::~LLOutfitObserver() +{ + if (gInventory.containsObserver(this)) + { + gInventory.removeObserver(this); + } +} + +void LLOutfitObserver::changed(U32 mask) +{ + if (!gInventory.isInventoryUsable()) + return; + + bool COF_changed = checkCOF(); + + if (!COF_changed) + { + checkBaseOutfit(); + } +} + +// static +S32 LLOutfitObserver::getCategoryVersion(const LLUUID& cat_id) +{ + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (!cat) + return LLViewerInventoryCategory::VERSION_UNKNOWN; + + return cat->getVersion(); +} + +bool LLOutfitObserver::checkCOF() +{ + LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); + if (cof.isNull()) + return false; + + S32 cof_version = getCategoryVersion(cof); + + if (cof_version == mCOFLastVersion) + return false; + + mCOFLastVersion = cof_version; + + // dirtiness state should be updated before sending signal + LLAppearanceMgr::getInstance()->updateIsDirty(); + mCOFChanged(); + + return true; +} + +void LLOutfitObserver::checkBaseOutfit() +{ + LLUUID baseoutfit_id = + LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); + + if (baseoutfit_id == mBaseOutfitId) + { + if (baseoutfit_id.isNull()) + return; + + const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); + + if (baseoutfit_ver == mBaseOutfitLastVersion) + return; + } + else + { + mBaseOutfitId = baseoutfit_id; + mBOFReplaced(); + + if (baseoutfit_id.isNull()) + return; + + mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); + } + + LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); + // dirtiness state should be updated before sending signal + app_mgr.updateIsDirty(); + mBOFChanged(); + + if (mLastOutfitDirtiness != app_mgr.isOutfitDirty()) + { + if(!app_mgr.isOutfitDirty()) + { + mCOFSaved(); + } + mLastOutfitDirtiness = app_mgr.isOutfitDirty(); + } +} diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h new file mode 100644 index 0000000000..a4b5fbe04a --- /dev/null +++ b/indra/newview/lloutfitobserver.h @@ -0,0 +1,96 @@ +/** + * @file lloutfitobserver.h + * @brief Outfit observer facade. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_OUTFITOBSERVER_H +#define LL_OUTFITOBSERVER_H + +#include "llsingleton.h" + +/** + * Outfit observer facade that provides simple possibility to subscribe on + * BOF(base outfit) replaced, BOF changed, COF(current outfit) changed events. + */ +class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver> +{ +public: + virtual ~LLOutfitObserver(); + + friend class LLSingleton<LLOutfitObserver>; + + virtual void changed(U32 mask); + + void notifyOutfitLockChanged() { mOutfitLockChanged(); } + + typedef boost::signals2::signal<void (void)> signal_t; + + void addBOFReplacedCallback(const signal_t::slot_type& cb) { mBOFReplaced.connect(cb); } + + void addBOFChangedCallback(const signal_t::slot_type& cb) { mBOFChanged.connect(cb); } + + void addCOFChangedCallback(const signal_t::slot_type& cb) { mCOFChanged.connect(cb); } + + void addCOFSavedCallback(const signal_t::slot_type& cb) { mCOFSaved.connect(cb); } + + void addOutfitLockChangedCallback(const signal_t::slot_type& cb) { mOutfitLockChanged.connect(cb); } + +protected: + LLOutfitObserver(); + + /** Get a version of an inventory category specified by its UUID */ + static S32 getCategoryVersion(const LLUUID& cat_id); + + bool checkCOF(); + + void checkBaseOutfit(); + + //last version number of a COF category + S32 mCOFLastVersion; + + LLUUID mBaseOutfitId; + + S32 mBaseOutfitLastVersion; + + bool mLastOutfitDirtiness; + +private: + signal_t mBOFReplaced; + signal_t mBOFChanged; + signal_t mCOFChanged; + signal_t mCOFSaved; + + /** + * Signal for changing state of outfit lock. + */ + signal_t mOutfitLockChanged; +}; + +#endif /* LL_OUTFITOBSERVER_H */ diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 77db280487..e20b2e26be 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -53,6 +53,20 @@ static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y); +static const LLOutfitTabNameComparator OUTFIT_TAB_NAME_COMPARATOR; + +/*virtual*/ +bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const +{ + std::string name1 = tab1->getTitle(); + std::string name2 = tab2->getTitle(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; +} + ////////////////////////////////////////////////////////////////////////// class OutfitContextMenu : public LLListContextMenu @@ -158,6 +172,7 @@ LLOutfitsList::~LLOutfitsList() BOOL LLOutfitsList::postBuild() { mAccordion = getChild<LLAccordionCtrl>("outfits_accordion"); + mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR); return TRUE; } @@ -328,7 +343,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) updateOutfitTab(*items_iter); } - mAccordion->arrange(); + mAccordion->sort(); } void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) @@ -500,6 +515,8 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) void LLOutfitsList::applyFilter(const std::string& new_filter_substring) { + mAccordion->setFilterSubString(new_filter_substring); + for (outfits_map_t::iterator iter = mOutfitsMap.begin(), iter_end = mOutfitsMap.end(); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 44f6ec908b..bb516446d2 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -32,18 +32,34 @@ #ifndef LL_LLOUTFITSLIST_H #define LL_LLOUTFITSLIST_H +#include "llaccordionctrl.h" #include "llpanel.h" // newview #include "llinventorymodel.h" #include "llinventoryobserver.h" -class LLAccordionCtrl; class LLAccordionCtrlTab; class LLWearableItemsList; class LLListContextMenu; /** + * @class LLOutfitTabNameComparator + * + * Comparator of outfit tabs. + */ +class LLOutfitTabNameComparator : public LLAccordionCtrl::LLTabComparator +{ + LOG_CLASS(LLOutfitTabNameComparator); + +public: + LLOutfitTabNameComparator() {}; + virtual ~LLOutfitTabNameComparator() {}; + + /*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const; +}; + +/** * @class LLOutfitsList * * A list of agents's outfits from "My Outfits" inventory category diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 4982e98f8e..e07d5c064b 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -39,6 +39,7 @@ #include "llagentcamera.h" #include "llagentwearables.h" #include "llappearancemgr.h" +#include "lloutfitobserver.h" #include "llcofwearables.h" #include "llfilteredwearablelist.h" #include "llinventory.h" @@ -143,100 +144,6 @@ private: } }; -class LLCOFObserver : public LLInventoryObserver -{ -public: - LLCOFObserver(LLPanelOutfitEdit *panel) : mPanel(panel), - mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) - { - gInventory.addObserver(this); - } - - virtual ~LLCOFObserver() - { - if (gInventory.containsObserver(this)) - { - gInventory.removeObserver(this); - } - } - - virtual void changed(U32 mask) - { - if (!gInventory.isInventoryUsable()) return; - - bool panel_updated = checkCOF(); - - if (!panel_updated) - { - checkBaseOutfit(); - } - } - -protected: - - /** Get a version of an inventory category specified by its UUID */ - static S32 getCategoryVersion(const LLUUID& cat_id) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (!cat) return LLViewerInventoryCategory::VERSION_UNKNOWN; - - return cat->getVersion(); - } - - bool checkCOF() - { - LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); - if (cof.isNull()) return false; - - S32 cof_version = getCategoryVersion(cof); - - if (cof_version == mCOFLastVersion) return false; - - mCOFLastVersion = cof_version; - - mPanel->update(); - - return true; - } - - void checkBaseOutfit() - { - LLUUID baseoutfit_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); - - if (baseoutfit_id == mBaseOutfitId) - { - if (baseoutfit_id.isNull()) return; - - const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); - - if (baseoutfit_ver == mBaseOutfitLastVersion) return; - } - else - { - mBaseOutfitId = baseoutfit_id; - mPanel->updateCurrentOutfitName(); - - if (baseoutfit_id.isNull()) return; - - mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); - } - - mPanel->updateVerbs(); - } - - - - - LLPanelOutfitEdit *mPanel; - - //last version number of a COF category - S32 mCOFLastVersion; - - LLUUID mBaseOutfitId; - - S32 mBaseOutfitLastVersion; -}; - class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver { public: @@ -277,7 +184,6 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() mSearchFilter(NULL), mCOFWearables(NULL), mInventoryItemsPanel(NULL), - mCOFObserver(NULL), mGearMenu(NULL), mCOFDragAndDropObserver(NULL), mInitialized(false), @@ -288,7 +194,12 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); - mCOFObserver = new LLCOFObserver(this); + + LLOutfitObserver& observer = LLOutfitObserver::instance(); + observer.addBOFReplacedCallback(boost::bind(&LLPanelOutfitEdit::updateCurrentOutfitName, this)); + observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); + observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); + observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::update, this)); mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES); for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++) @@ -303,7 +214,6 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() { delete mSavedFolderState; - delete mCOFObserver; delete mCOFDragAndDropObserver; delete mWearableListMaskCollector; @@ -371,7 +281,7 @@ BOOL LLPanelOutfitEdit::postBuild() childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK); - mWearableListTypeCollector = new LLFindWearablesOfType(LLWearableType::WT_NONE); + mWearableListTypeCollector = new LLFindActualWearablesOfType(LLWearableType::WT_NONE); mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel"); mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list"); @@ -585,35 +495,10 @@ void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void) void LLPanelOutfitEdit::onEditWearableClicked(void) { - LLUUID id_to_edit = mCOFWearables->getSelectedUUID(); - LLViewerInventoryItem * item_to_edit = gInventory.getItem(id_to_edit); - - if (item_to_edit) + LLUUID selected_item_id = mCOFWearables->getSelectedUUID(); + if (selected_item_id.notNull()) { - // returns null if not a wearable (attachment, etc). - LLWearable* wearable_to_edit = gAgentWearables.getWearableFromAssetID(item_to_edit->getAssetUUID()); - if(wearable_to_edit) - { - bool can_modify = false; - bool is_complete = item_to_edit->isFinished(); - // if item_to_edit is a link, its properties are not appropriate, - // lets get original item with actual properties - LLViewerInventoryItem* original_item = gInventory.getItem(wearable_to_edit->getItemID()); - if(original_item) - { - can_modify = original_item->getPermissions().allowModifyBy(gAgentID); - is_complete = original_item->isFinished(); - } - - if (can_modify && is_complete) - { - LLSidepanelAppearance::editWearable(wearable_to_edit, getParent()); - if (mEditWearableBtn->getVisible()) - { - mEditWearableBtn->setVisible(FALSE); - } - } - } + gAgentWearables.editWearable(selected_item_id); } } @@ -756,16 +641,14 @@ void LLPanelOutfitEdit::updateCurrentOutfitName() //private void LLPanelOutfitEdit::updateVerbs() { - //*TODO implement better handling of COF dirtiness - LLAppearanceMgr::getInstance()->updateIsDirty(); - bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); + bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked(); bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull(); - mSaveComboBtn->setSaveBtnEnabled(outfit_is_dirty); + mSaveComboBtn->setSaveBtnEnabled(!outfit_locked && outfit_is_dirty); childSetEnabled(REVERT_BTN, outfit_is_dirty && has_baseoutfit); - mSaveComboBtn->setMenuItemEnabled("save_outfit", outfit_is_dirty); + mSaveComboBtn->setMenuItemEnabled("save_outfit", !outfit_locked && outfit_is_dirty); mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 802386c573..24ecf75c18 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -49,7 +49,7 @@ class LLButton; class LLCOFWearables; class LLTextBox; class LLInventoryCategory; -class LLCOFObserver; +class LLOutfitObserver; class LLCOFDragAndDropObserver; class LLInventoryPanel; class LLSaveFolderState; @@ -153,7 +153,6 @@ private: LLInventoryItemsList* mWearableItemsList; LLPanel* mWearableItemsPanel; - LLCOFObserver* mCOFObserver; LLCOFDragAndDropObserver* mCOFDragAndDropObserver; std::vector<LLLookItemType> mLookItemTypes; diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 5f67f3d989..8b451c156c 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -50,6 +50,7 @@ #include "lllineeditor.h" #include "llmodaldialog.h" #include "llnotificationsutil.h" +#include "lloutfitobserver.h" #include "lloutfitslist.h" #include "llsaveoutfitcombobtn.h" #include "llsidepanelappearance.h" @@ -204,6 +205,11 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() : mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this)); + + LLOutfitObserver& observer = LLOutfitObserver::instance(); + observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); + observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); + observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); } LLPanelOutfitsInventory::~LLPanelOutfitsInventory() @@ -517,12 +523,12 @@ void LLPanelOutfitsInventory::updateListCommands() { bool trash_enabled = isActionEnabled("delete"); bool wear_enabled = isActionEnabled("wear"); - bool make_outfit_enabled = isActionEnabled("make_outfit"); + bool make_outfit_enabled = isActionEnabled("save_outfit"); mListCommands->childSetEnabled("trash_btn", trash_enabled); mListCommands->childSetEnabled("wear_btn", wear_enabled); mListCommands->childSetVisible("wear_btn", wear_enabled); - mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled); + mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); } void LLPanelOutfitsInventory::showGearMenu() @@ -663,9 +669,12 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) return FALSE; } } - if (command_name == "make_outfit") + if (command_name == "save_outfit") { - return TRUE; + bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked(); + bool outfit_dirty =LLAppearanceMgr::getInstance()->isOutfitDirty(); + // allow save only if outfit isn't locked and is dirty + return !outfit_locked && outfit_dirty; } if (command_name == "edit" || @@ -789,6 +798,7 @@ void LLPanelOutfitsInventory::onWearablesLoaded() setWearablesLoading(false); } +// static LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP() { static LLSidepanelAppearance* panel_appearance = diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index aff7839bcc..d58ae554b0 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -75,7 +75,7 @@ public: void setParent(LLSidepanelAppearance *parent); LLFolderView* getRootFolder(); - LLSidepanelAppearance* getAppearanceSP(); + static LLSidepanelAppearance* getAppearanceSP(); static LLPanelOutfitsInventory* findInstance(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 0a4af00f78..f16d1d8fda 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1450,6 +1450,8 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded() LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion"); accordion->arrange(); + // *TODO: new empty_accordion_text attribute was implemented in accordion (EXT-7368). + // this code should be refactored to use it // keep help text in a synchronization with accordions visibility. updateFriendListHelpText(); } diff --git a/indra/newview/llsaveoutfitcombobtn.cpp b/indra/newview/llsaveoutfitcombobtn.cpp index b9b577084b..9518b0cbb3 100644 --- a/indra/newview/llsaveoutfitcombobtn.cpp +++ b/indra/newview/llsaveoutfitcombobtn.cpp @@ -34,6 +34,7 @@ #include "llappearancemgr.h" #include "llpaneloutfitsinventory.h" +#include "llsidepanelappearance.h" #include "llsaveoutfitcombobtn.h" #include "llviewermenu.h" diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 872939c209..e23643da0b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -42,6 +42,7 @@ #include "llfloaterreg.h" #include "llfloaterworldmap.h" #include "llfoldervieweventlistener.h" +#include "lloutfitobserver.h" #include "llpaneleditwearable.h" #include "llpaneloutfitsinventory.h" #include "llsidetray.h" @@ -73,26 +74,6 @@ private: LLSidepanelAppearance *mPanel; }; -class LLWatchForOutfitRenameObserver : public LLInventoryObserver -{ -public: - LLWatchForOutfitRenameObserver(LLSidepanelAppearance *panel) : - mPanel(panel) - {} - virtual void changed(U32 mask); - -private: - LLSidepanelAppearance *mPanel; -}; - -void LLWatchForOutfitRenameObserver::changed(U32 mask) -{ - if (mask & LABEL) - { - mPanel->refreshCurrentOutfitName(); - } -} - LLSidepanelAppearance::LLSidepanelAppearance() : LLPanel(), mFilterSubString(LLStringUtil::null), @@ -101,12 +82,13 @@ LLSidepanelAppearance::LLSidepanelAppearance() : mCurrOutfitPanel(NULL), mOpened(false) { + LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); + outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); } LLSidepanelAppearance::~LLSidepanelAppearance() { - gInventory.removeObserver(mOutfitRenameWatcher); - delete mOutfitRenameWatcher; } // virtual @@ -160,8 +142,6 @@ BOOL LLSidepanelAppearance::postBuild() mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook"); - mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this); - gInventory.addObserver(mOutfitRenameWatcher); setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 30022ae375..812d6362ef 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -40,7 +40,6 @@ class LLFilterEditor; class LLCurrentlyWornFetchObserver; -class LLWatchForOutfitRenameObserver; class LLPanelEditWearable; class LLWearable; class LLPanelOutfitsInventory; @@ -97,9 +96,6 @@ private: // Used to make sure the user's inventory is in memory. LLCurrentlyWornFetchObserver* mFetchWorn; - // Used to update title when currently worn outfit gets renamed. - LLWatchForOutfitRenameObserver* mOutfitRenameWatcher; - // Search string for filtering landmarks and teleport // history locations std::string mFilterSubString; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 3c97f01887..9406f80b75 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -469,6 +469,9 @@ void LLSideTray::reflectCollapseChange() } gFloaterView->refresh(); + + LLSD new_value = mCollapsed; + mCollapseSignal(this,new_value); } void LLSideTray::arrange() diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index e8fdee9430..e176ff5aff 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -159,6 +159,8 @@ public: void updateSidetrayVisibility(); + commit_signal_t& getCollapseSignal() { return mCollapseSignal; } + protected: LLSideTrayTab* getTab (const std::string& name); @@ -187,6 +189,8 @@ private: child_vector_t mTabs; LLSideTrayTab* mActiveTab; + commit_signal_t mCollapseSignal; + LLButton* mCollapseButton; bool mCollapsed; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e51e6363dd..fff80e57dc 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -781,9 +781,6 @@ bool idle_startup() gViewerWindow->getWindow()->show(); display_startup(); - //DEV-10530. do cleanup. remove at some later date. jan-2009 - LLFloaterPreference::cleanupBadSetting(); - // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. #ifdef _WIN32 diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 8996157258..fa21b1a866 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -96,7 +96,7 @@ LLVisualParamHint::LLVisualParamHint( mCamTargetJoint(jointp) { LLVisualParamHint::sInstances.insert( this ); - mBackgroundp = LLUI::getUIImage("avatar_thumb_bkgrnd.j2c"); + mBackgroundp = LLUI::getUIImage("avatar_thumb_bkgrnd.png"); llassert(width != 0); llassert(height != 0); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index face7124c2..40f15fe86a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -883,12 +883,8 @@ void ModifiedCOFCallback::fire(const LLUUID& inv_item) { LLAppearanceMgr::instance().updateAppearanceFromCOF(); - if (LLSideTray::getInstance()->isPanelActive("sidepanel_appearance")) - { - // *HACK: Edit the wearable that has just been worn - // only if the Appearance SP is currently opened. - LLAgentWearables::editWearable(inv_item); - } + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(inv_item); // TODO: camera mode may not be changed if a debug setting is tweaked if( gAgentCamera.cameraCustomizeAvatar() ) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5836aff4e7..b00fa39815 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2063,7 +2063,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // initiated by the other party) then... std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), @@ -2736,7 +2736,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id) { std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 7e779986df..9b5b210bf7 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -541,11 +541,6 @@ void LLViewerTexture::setBoostLevel(S32 level) if(mBoostLevel != LLViewerTexture::BOOST_NONE) { setNoDelete() ; - - if(LLViewerTexture::BOOST_AVATAR_BAKED_SELF == mBoostLevel || LLViewerTexture::BOOST_AVATAR_BAKED == mBoostLevel) - { - mCanResetMaxVirtualSize = false ; - } } if(gAuditTexture) { @@ -596,6 +591,11 @@ void LLViewerTexture::forceImmediateUpdate() { } +void LLViewerTexture::setResetMaxVirtualSizeFlag(bool flag) +{ + mCanResetMaxVirtualSize = flag ; +} + void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { if(needs_gltexture) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 1bd4cc793d..361f56e02f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -166,6 +166,7 @@ public: void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; void resetTextureStats(); + void setResetMaxVirtualSizeFlag(bool flag) ; virtual F32 getMaxVirtualSize() ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 83556452c0..0a65cb7330 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1591,6 +1591,9 @@ void LLViewerWindow::initBase() gDebugView->init(); gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); + // Initialize busy response message when logged in + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse)); + // Add the progress bar view (startup view), which overrides everything mProgressView = getRootView()->getChild<LLProgressView>("progress_view"); setShowProgress(FALSE); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 1fa953f157..3e93dc1a90 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4210,9 +4210,14 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); mMinPixelArea = llmin(pixel_area, mMinPixelArea); imagep->resetTextureStats(); + imagep->setResetMaxVirtualSizeFlag(false) ; imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures. imagep->addTextureStats(pixel_area / texel_area_ratio); imagep->setBoostLevel(boost_level); + if(boost_level == LLViewerTexture::BOOST_AVATAR_BAKED_SELF) + { + imagep->setAdditionalDecodePriority(1.0f) ; + } } //virtual diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index eae92f8992..a4d888cd72 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -975,12 +975,6 @@ void LLVOAvatarSelf::wearableUpdated( LLWearableType::EType type, BOOL upload_re const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second; const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first; - // if we're editing our appearance, ensure that we're not using baked textures - // The baked texture for alpha masks is set explicitly when you hit "save" - if (gAgentCamera.cameraCustomizeAvatar()) - { - setNewBakedTexture(index,IMG_DEFAULT_AVATAR); - } if (baked_dict) { for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); @@ -2036,7 +2030,11 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); imagep->setBoostLevel(getAvatarBoostLevel()); + + imagep->resetTextureStats(); + imagep->setResetMaxVirtualSizeFlag(false) ; imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->setAdditionalDecodePriority(1.0f) ; imagep->forceUpdateBindStats() ; if (imagep->getDiscardLevel() < 0) { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 96bde129ee..39649f0370 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5287,6 +5287,7 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled) LLVoiceChannel::getCurrentVoiceChannel()->deactivate(); status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED; } + notifyStatusObservers(status); } } diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 121e691710..46c736c853 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -705,7 +705,7 @@ void LLWearable::removeFromAvatar( LLWearableType::EType type, BOOL upload_bake } gAgentAvatarp->updateVisualParams(); - gAgentAvatarp->wearableUpdated(type, TRUE); + gAgentAvatarp->wearableUpdated(type, FALSE); // if( upload_bake ) // { diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 6c4774ba5a..6c410cf7a5 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -42,6 +42,7 @@ #include "llmenugl.h" // for LLContextMenu #include "lltransutil.h" #include "llviewerattachmenu.h" +#include "llvoavatarself.h" class LLFindOutfitItems : public LLInventoryCollectFunctor { @@ -258,6 +259,31 @@ BOOL LLPanelDeletableWearableListItem::postBuild() } +// static +LLPanelAttachmentListItem* LLPanelAttachmentListItem::create(LLViewerInventoryItem* item) +{ + LLPanelAttachmentListItem* list_item = NULL; + if(item) + { + list_item = new LLPanelAttachmentListItem(item); + list_item->init(); + } + return list_item; +} + +void LLPanelAttachmentListItem::setTitle(const std::string& title, const std::string& highlit_text) +{ + std::string title_joint = title; + + if (mItem && isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(mItem->getLinkedUUID())) + { + std::string joint = LLTrans::getString(gAgentAvatarp->getAttachedPointName(mItem->getLinkedUUID())); + title_joint = title + " (" + joint + ")"; + } + + LLPanelDeletableWearableListItem::setTitle(title_joint, highlit_text); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 2fdb8f0ab8..f03336186c 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -116,6 +116,21 @@ protected: /*virtual*/ void init(); }; +/** Outfit list item for an attachment */ +class LLPanelAttachmentListItem : public LLPanelDeletableWearableListItem +{ + LOG_CLASS(LLPanelAttachmentListItem); +public: + static LLPanelAttachmentListItem* create(LLViewerInventoryItem* item); + virtual ~LLPanelAttachmentListItem() {}; + + /** Set item title. Joint name is added to the title in parenthesis */ + /*virtual*/ void setTitle(const std::string& title, const std::string& highlit_text); + +protected: + LLPanelAttachmentListItem(LLViewerInventoryItem* item) : LLPanelDeletableWearableListItem(item) {}; +}; + /** * @class LLPanelClothingListItem * diff --git a/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.png b/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.png Binary files differnew file mode 100644 index 0000000000..84cc2159c1 --- /dev/null +++ b/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.png diff --git a/indra/newview/skins/default/xui/de/panel_bottomtray.xml b/indra/newview/skins/default/xui/de/panel_bottomtray.xml index d52b8dcf4d..83f67344ca 100644 --- a/indra/newview/skins/default/xui/de/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/de/panel_bottomtray.xml @@ -9,7 +9,7 @@ <layout_stack name="toolbar_stack"> <layout_panel name="speak_panel"> <talk_button name="talk"> - <speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" halign="right" /> + <speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" /> </talk_button> </layout_panel> <layout_panel name="gesture_panel"> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index f537c81860..c9b013099b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -33,7 +33,6 @@ name="panel_im_control_panel" layout="topleft" follows="left" - label="IM Control Panel" min_width="115" auto_resize="false" user_resize="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index f3d297c303..7d81c3e551 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -38,91 +38,129 @@ left="20" top_pad="-30" name="new_snapshot_btn" - width="23" /> + width="23" + commit_callback.function="Snapshot.Refresh"/> <line_editor border_style="line" border_thickness="1" - follows="left|top" - height="20" - layout="topleft" + follows="left|top" + height="20" + layout="topleft" left="10" - max_length="500" + max_length="500" name="description" - top_pad="15" - width="230" + top_pad="15" + width="230" label="Description"/> + <panel + top_pad="20" + left="10" + height="83" + name="panel_snapshot_main" + width="130"> + <button + label="Share Snapshot" + name="share" + top="0" + left="0" + width="130" + commit_callback.function="Snapshot.ShowButtons" + commit_callback.parameter="share"/> + <button + label="Save Snapshot" + name="save" + top_pad="7" + left_delta="0" + width="130" + commit_callback.function="Snapshot.ShowButtons" + commit_callback.parameter="save"/> + <button + label="Set As Profile Pic" + name="set_profile_pic" + top_pad="7" + left_delta="0" + width="130"/> + </panel> + <panel + top_delta="0" + left_delta="0" + height="83" + name="panel_snapshot_share" + width="130"> + <button + label="Share to Web" + name="share_to_web" + top="0" + left="0" + visible="false" + width="130"/> + <button + label="Email Snapshot" + name="share_to_email" + top_pad="7" + left_delta="0" + width="130"/> + <button + label="Back" + name="cancel_share" + top_pad="7" + left_delta="0" + width="130" + commit_callback.function="Snapshot.ShowButtons" + commit_callback.parameter="main"/> + </panel> + <panel + top_delta="0" + left_delta="0" + height="83" + name="panel_snapshot_save" + width="130"> + <button + label="Save to My Inventory" + name="save_to_inventory" + top="0" + left="0" + width="130"/> + <button + label="Save to My Computer" + name="save_to_computer" + top_pad="7" + left_delta="0" + width="130"/> + <button + label="Back" + name="cancel_save" + top_pad="7" + left_delta="0" + width="130" + commit_callback.function="Snapshot.ShowButtons" + commit_callback.parameter="main"/> + </panel> <button - label="Share Snapshot" - name="share" - top_pad="20" - left="10" - width="130"/> + follows="left" + height="22" + layout="topleft" + left="210" + name="show_advanced" + image_overlay="TabIcon_Close_Off" + bottom_delta="0" + width="30" + commit_callback.function="Snapshot.ShowAdvanced"/> <button - label="Share to Web" - name="share_to_web" - top_delta="0" - left="10" + follows="left" + height="22" + layout="topleft" + left="210" + name="hide_advanced" + image_overlay="TabIcon_Open_Off" + top_delta="0" visible="false" - width="130"/> - <button - label="Save to My Inventory" - name="save_to_inventory" - top_delta="0" - left="10" - width="130"/> - <button - label="Save Snapshot" - name="save" - top_pad="7" - left="10" - width="130"/> - <button - label="Email Snapshot" - name="share_to_email" - top_delta="0" - left="10" - width="130"/> - <button - label="Save to My Computer" - name="save_to_computer" - top_delta="0" - left="10" - width="130"/> - <button - label="Set As Profile Pic" - name="set_profile_pic" - top_pad="7" - left="10" - width="130"/> - <button - label="Back" - name="cancel" - top_delta="0" - left="10" - width="130"/> - <button - follows="left" - height="22" - layout="topleft" - left="210" - name="show_advanced" - image_overlay="TabIcon_Close_Off" - top_delta="1" - width="30"/> - <button - follows="left" - height="22" - layout="topleft" - left="210" - visible="false" - name="hide_advanced" - image_overlay="TabIcon_Open_Off" - top_delta="0" - width="30"/> + width="30" + commit_callback.function="Snapshot.HideAdvanced"/> <panel - visible="false" - left="250" - top="17" - name="snapshot_advanced" - filename="panel_snapshot_advanced.xml"/> + visible="false" + left="250" + top="17" + name="snapshot_advanced" + filename="panel_snapshot_advanced.xml"/> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml index 4e6a07d020..62365f7cc2 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -61,14 +61,6 @@ <menu_item_separator layout="topleft" /> <menu_item_call - label="Empty Trash" - layout="topleft" - name="empty_trash"> - <on_click - function="Inventory.GearDefault.Custom.Action" - parameter="empty_trash" /> - </menu_item_call> - <menu_item_call label="Empty Lost and Found" layout="topleft" name="empty_lostnfound"> @@ -111,4 +103,15 @@ function="Inventory.GearDefault.Enable" parameter="find_links" /> </menu_item_call> + <menu_item_separator + layout="topleft" /> + + <menu_item_call + label="Empty Trash" + layout="topleft" + name="empty_trash"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="empty_trash" /> + </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6d3d0f13bf..439f67e7b1 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6304,36 +6304,39 @@ Avatar '[NAME]' entered appearance mode. Avatar '[NAME]' left appearance mode. </notification> - <notification + <notification icon="alertmodal.tga" name="NoConnect" type="alertmodal"> - We're having trouble connecting using [PROTOCOL] [HOSTID]. - Please check your network and firewall setup. - <form name="form"> - <button - default="true" - index="0" - name="OK" - text="OK"/> - </form> - </notification> +We're having trouble connecting using [PROTOCOL] [HOSTID]. +Please check your network and firewall setup. + <form name="form"> + <button + default="true" + index="0" + name="OK" + text="OK"/> + </form> + </notification> - <notification - icon="alertmodal.tga" - name="NoVoiceConnect" - type="alertmodal"> - We're having trouble connecting your voiceserver using [HOSTID]. - Voice communications will not be available. - Please check your network and firewall setup. - <form name="form"> - <button - default="true" - index="0" - name="OK" - text="OK"/> - </form> - </notification> + <notification + icon="alertmodal.tga" + name="NoVoiceConnect" + type="alertmodal"> +We're having trouble connecting to your voice server: + +[HOSTID] + +Voice communications will not be available. +Please check your network and firewall setup. + <form name="form"> + <button + default="true" + index="0" + name="OK" + text="OK"/> + </form> + </notification> <notification icon="notifytip.tga" @@ -6361,7 +6364,7 @@ Are you sure you want to leave this call? name="okcancelignore" notext="No" yestext="Yes"/> - <unique/> + <unique/> </notification> <notification @@ -6378,7 +6381,7 @@ Mute everyone? name="okcancelignore" yestext="Ok" notext="Cancel"/> - <unique/> + <unique/> </notification> <global name="UnsupportedCPU"> diff --git a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml index a0bbc8f2ee..4e5f594ffe 100644 --- a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="top|right|left" - height="25" + height="23" layout="topleft" left="0" name="wearable_item" @@ -45,7 +45,7 @@ use_ellipses="true" name="item_name" text_color="white" - top="4" + top="5" value="..." width="359" /> <panel @@ -74,10 +74,10 @@ name="btn_edit_panel" layout="topleft" follows="top|right" - top="0" + top="1" left_pad="3" - height="24" - width="27" + height="23" + width="26" tab_stop="false"> <button name="btn_edit" @@ -86,8 +86,8 @@ image_overlay="Edit_Wrench" top="0" left="0" - height="24" - width="24" + height="23" + width="23" tab_stop="false" /> </panel> <icon @@ -97,7 +97,7 @@ layout="bottomleft" left="0" name="wearable_type_separator_icon" - top="3" + top="0" visible="true" width="380"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 82b2405ec9..4eff5bc48a 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -90,7 +90,7 @@ label="Speak" label_selected="Speak" name="speak_btn" - pad_right="22" + pad_right="20" tab_stop="true" use_ellipses="true" /> </talk_button> diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml index e41141f6bd..5d81aebbd5 100644 --- a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml @@ -33,7 +33,7 @@ follows="top|left" image_unselected="Toast_CloseBtn" image_selected="Toast_CloseBtn" - top="2" + top="3" left="0" height="18" width="18" @@ -56,7 +56,7 @@ use_ellipses="true" name="item_name" text_color="white" - top="4" + top="5" value="..." width="359" /> <button @@ -64,20 +64,20 @@ layout="topleft" follows="top|right" image_overlay="UpArrow_Off" - top="0" + top="1" left="0" - height="24" - width="24" + height="23" + width="23" tab_stop="false" /> <button name="btn_move_down" layout="topleft" follows="top|right" image_overlay="DownArrow_Off" - top="0" + top="1" left_pad="3" - height="24" - width="24" + height="23" + width="23" tab_stop="false" /> <panel background_visible="false" @@ -107,18 +107,18 @@ follows="top|right" top="0" left_pad="3" - height="24" - width="27" + height="23" + width="26" tab_stop="false"> <button name="btn_edit" layout="topleft" follows="top|right" image_overlay="Edit_Wrench" - top="0" + top="1" left="0" - height="24" - width="24" + height="23" + width="23" tab_stop="false" /> </panel> <icon diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 5f34c24bca..d36c2a4e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -11,7 +11,7 @@ <accordion fit_parent="true" follows="all" - height="200" + height="198" layout="topleft" left="0" single_expansion="true" @@ -28,6 +28,7 @@ allow_select="true" follows="all" height="10" + item_pad="2" layout="topleft" left="0" multi_select="true" @@ -43,6 +44,7 @@ allow_select="true" follows="all" height="10" + item_pad="2" layout="topleft" left="0" multi_select="true" @@ -58,6 +60,7 @@ allow_select="true" follows="all" height="10" + item_pad="2" layout="topleft" left="0" multi_select="true" diff --git a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml index b006d125ee..45031859f1 100644 --- a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="top|right|left" - height="25" + height="23" layout="topleft" left="0" name="deletable_wearable_item" @@ -33,7 +33,7 @@ follows="top|left" image_unselected="Toast_CloseBtn" image_selected="Toast_CloseBtn" - top="2" + top="3" left="0" height="18" width="18" @@ -56,7 +56,7 @@ use_ellipses="true" name="item_name" text_color="white" - top="4" + top="5" value="..." width="359" /> <icon @@ -66,7 +66,7 @@ layout="bottomleft" left="0" name="wearable_type_separator_icon" - top="3" + top="0" visible="true" width="380"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index 6c43635d49..20652df918 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="top|right|left" - height="25" + height="23" layout="topleft" left="0" name="dummy_clothing_item" @@ -56,8 +56,8 @@ image_overlay="AddItem_Off" top="0" left="0" - height="24" - width="24" + height="23" + width="23" tab_stop="false" /> <icon follows="left|right|top" @@ -66,7 +66,7 @@ layout="bottomleft" left="0" name="wearable_type_separator_icon" - top="3" + top="0" visible="true" width="380"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 67ff71cef1..645ee8a435 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -7,6 +7,7 @@ label="Wearable" layout="topleft" left="0" + help_topic="edit_wearable" name="panel_edit_wearable" top="0" width="333"> @@ -235,7 +236,7 @@ left="0" </panel> <panel follows="all" - height="408" + height="433" layout="topleft" left="0" name="edit_subpanel_container" @@ -246,7 +247,7 @@ left="0" <panel filename="panel_edit_shape.xml" follows="all" - height="408" + height="433" layout="topleft" left="0" name="edit_shape_panel" @@ -256,7 +257,7 @@ left="0" <panel filename="panel_edit_skin.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_skin_panel" @@ -266,7 +267,7 @@ left="0" <panel filename="panel_edit_hair.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_hair_panel" @@ -276,7 +277,7 @@ left="0" <panel filename="panel_edit_eyes.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_eyes_panel" @@ -286,7 +287,7 @@ left="0" <panel filename="panel_edit_shirt.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_shirt_panel" @@ -296,7 +297,7 @@ left="0" <panel filename="panel_edit_pants.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_pants_panel" @@ -306,7 +307,7 @@ left="0" <panel filename="panel_edit_shoes.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_shoes_panel" @@ -316,7 +317,7 @@ left="0" <panel filename="panel_edit_socks.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_socks_panel" @@ -326,7 +327,7 @@ left="0" <panel filename="panel_edit_jacket.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_jacket_panel" @@ -336,7 +337,7 @@ left="0" <panel filename="panel_edit_skirt.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_skirt_panel" @@ -346,7 +347,7 @@ left="0" <panel filename="panel_edit_gloves.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_gloves_panel" @@ -356,7 +357,7 @@ left="0" <panel filename="panel_edit_undershirt.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_undershirt_panel" @@ -366,7 +367,7 @@ left="0" <panel filename="panel_edit_underpants.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_underpants_panel" @@ -376,7 +377,7 @@ left="0" <panel filename="panel_edit_alpha.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_alpha_panel" @@ -386,7 +387,7 @@ left="0" <panel filename="panel_edit_tattoo.xml" follows="all" - height="400" + height="425" layout="topleft" left="0" name="edit_tattoo_panel" @@ -394,65 +395,7 @@ left="0" visible="false" width="333" /> </panel> - <panel - follows="bottom|left|right" - height="25" - label="gear_buttom_panel" - layout="topleft" - left="0" - name="gear_buttom_panel" - top_pad="0" - width="333"> - <button - follows="bottom|left" - tool_tip="Options" - height="25" - image_hover_unselected="Toolbar_Left_Over" - image_disabled="OptionsMenu_Disabled" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left="10" - name="friends_viewsort_btn" - top="0" - width="31" /> - <button - follows="bottom|left" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - image_disabled="AddItem_Disabled" - layout="topleft" - left_pad="1" - name="add_btn" - tool_tip="TODO" - width="31" /> - <icon - follows="bottom|left|right" - height="25" - image_name="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="dummy_right_icon" - width="218" > - </icon> - <button - follows="bottom|right" - height="25" - image_hover_unselected="Toolbar_Right_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Right_Selected" - image_unselected="Toolbar_Right_Off" - image_disabled="TrashItem_Disabled" - layout="topleft" - left_pad="1" - name="del_btn" - tool_tip="TODO" - width="31" /> - </panel> + <panel follows="bottom|left|right" height="23" diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 19fe2ea874..6523b0d491 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -74,16 +74,14 @@ Maximum 200 per group daily </text> <button follows="top|left" - height="18" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - image_disabled="AddItem_Disabled" + height="23" + image_overlay="AddItem_Off" layout="topleft" left="5" name="create_new_notice" tool_tip="Create a new notice" - top_delta="-3" - width="18" /> + top_delta="-3" + width="23" /> <button follows="top|left" height="23" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 769f9b7bbf..c9802a269c 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -5,8 +5,8 @@ border="false" height="600" follows="all" - label="Outfit Edit" layout="topleft" + help_topic="edit_outfit" left="0" min_height="350" name="outfit_edit" @@ -85,7 +85,6 @@ bevel_style="none" follows="top|left|right" height="40" - label="bottom_panel" layout="topleft" left="6" name="header_panel" @@ -106,7 +105,6 @@ bevel_style="none" follows="top|right" height="38" - label="bottom_panel" layout="topleft" left_pad="5" name="outfit_name_and_status" @@ -160,7 +158,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap <layout_panel layout="topleft" height="187" - label="IM Control Panel" min_height="100" name="outfit_wearables_panel" width="313" @@ -183,7 +180,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap bg_alpha_color="DkGray2" layout="topleft" height="154" - label="add_button_and_combobox" name="add_button_and_combobox" width="311" user_resize="false" @@ -256,15 +252,14 @@ It is calculated as border_size + 2*UIResizeBarOverlap background_image="TextField_Search_Off" enabled="true" follows="left|right|top" - font="SansSerif" - label="Filter" + label="Filter Inventory Wearables" layout="topleft" left="5" width="290" height="25" name="look_item_filter" + search_button_visible="true" text_color="black" - text_pad_left="25" visible="true"/> </layout_panel> @@ -344,7 +339,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap bevel_style="none" follows="bottom|left|right" height="27" - label="bottom_panel" layout="topleft" left="5" name="no_add_wearables_button_bar" @@ -379,7 +373,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap bevel_style="none" follows="left|right|bottom" height="27" - label="add_wearables_button_bar" layout="topleft" left="5" name="add_wearables_button_bar" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 13e1f5ba5c..de1f2cf31b 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -30,6 +30,7 @@ height="490" name="outfitslist_tab" background_visible="true" + help_topic="my_outfits_tab" follows="all" label="MY OUTFITS" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_list.xml b/indra/newview/skins/default/xui/en/panel_outfits_list.xml index 5cf94c25d7..5c9ae51a48 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_list.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_list.xml @@ -14,6 +14,7 @@ background_visible="true" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" + empty_accordion_text.value="Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]." follows="all" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index b79ef1e287..da28773c74 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -173,6 +173,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M background_visible="true" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" + empty_accordion_text.value="" follows="all" height="356" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index c9e41edd5a..59f1f6d638 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -2,7 +2,7 @@ <panel background_visible="true" follows="all" - height="570" + height="610" layout="topleft" left="0" min_height="350" @@ -181,7 +181,7 @@ <scroll_container color="DkGray2" follows="all" - height="532" + height="572" layout="topleft" left="9" name="place_scroll" @@ -191,7 +191,7 @@ <panel bg_alpha_color="DkGray2" follows="left|top|right" - height="540" + height="580" layout="topleft" left="0" min_height="300" @@ -337,21 +337,22 @@ <accordion fit_parent="true" follows="all" - height="223" + height="268" layout="topleft" single_expansion="true" left="0" name="advanced_info_accordion" - top_pad="10" + top_pad="5" width="313"> <accordion_tab - height="170" + fit_panel="false" + height="175" layout="topleft" name="parcel_characteristics_tab" title="Parcel"> <panel follows="all" - height="160" + height="175" layout="topleft" left="0" name="parcel_characteristics_panel" @@ -548,8 +549,8 @@ name="about_land_btn" right="-5" tab_stop="false" - top="138" - width="90"> + top_pad="2" + width="140"> <click_callback function="Floater.Show" parameter="about_land" /> @@ -558,7 +559,8 @@ </accordion_tab> <accordion_tab expanded="false" - height="150" + fit_panel="false" + height="125" layout="topleft" name="region_information_tab" title="Region"> @@ -677,7 +679,8 @@ name="region_info_btn" right="-5" tab_stop="false" - width="105"> + top_pad="2" + width="180"> <click_callback function="Floater.Show" parameter="region_info" /> @@ -686,13 +689,14 @@ </accordion_tab> <accordion_tab expanded="false" - height="190" + fit_panel="false" + height="180" layout="topleft" name="estate_information_tab" title="Estate"> <panel follows="all" - height="189" + height="180" layout="topleft" left="0" name="estate_information_panel" @@ -775,13 +779,14 @@ </accordion_tab> <accordion_tab expanded="false" - height="320" + fit_panel="false" + height="290" layout="topleft" name="sales_tab" title="For Sale"> <panel follows="all" - height="300" + height="290" layout="topleft" left="0" name="sales_panel" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 1c68d59993..a69e8d29b0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -348,7 +348,7 @@ Busy mode response: </text> <text_editor - control_name="BusyModeResponse2" + control_name="BusyModeResponse" text_readonly_color="LabelDisabledColor" bg_writeable_color="LtGray" use_ellipses="false" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 3d7b0b7edc..ae08a13793 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -111,6 +111,7 @@ width="333"> label="Filter Outfits" max_length="300" name="Filter" + search_button_visible="true" top_pad="10" width="303" /> <panel diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index c816fd1479..b736f5e29c 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -395,7 +395,7 @@ top_pad="10" label_width="75" left="120" width="170" - min_val="1" + min_val="0" height="23" max_val="999999999" top_pad="10"/> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion.xml b/indra/newview/skins/default/xui/en/widgets/accordion.xml new file mode 100644 index 0000000000..b817ba56ca --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/accordion.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<accordion + height="100" + name="accordion" + width="200"> + <empty_accordion_text + follows="all" + height="100" + h_pad="10" + name="no_visible_items_msg" + value="There are no visible content here." + v_pad="15" + width="200" + wrap="true "/> +</accordion> diff --git a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml index dfd301a770..48b987d7e8 100644 --- a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml +++ b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml @@ -4,5 +4,6 @@ name="color_swatch"> <color_swatch.caption_text name="caption" halign="center" - follows="left|right|bottom"/> + follows="left|right|bottom" + v_pad="2"/> </color_swatch> diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml index 33c3475eb2..757f0f49d1 100644 --- a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml +++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml @@ -3,7 +3,8 @@ <multiselect_text font="SansSerifSmall"/> <caption_text text="Multiple" halign="center" - font="SansSerifSmall"/> + font="SansSerifSmall" + v_pad="2"/> <border bevel_style="in"/> </texture_picker> diff --git a/indra/newview/skins/default/xui/ja/menu_bottomtray.xml b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml index 0e69671f06..e5703c559b 100644 --- a/indra/newview/skins/default/xui/ja/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml @@ -4,11 +4,11 @@ <menu_item_check label="移動ボタン" name="ShowMoveButton"/> <menu_item_check label="視界ボタン" name="ShowCameraButton"/> <menu_item_check label="スナップショットボタン" name="ShowSnapshotButton"/> - <menu_item_check label="サイドバーのボタン" name="ShowSidebarButton"/> - <menu_item_check label="制作のボタン" name="ShowBuildButton"/> - <menu_item_check label="検索のボタン" name="ShowSearchButton"/> - <menu_item_check label="地図のボタン" name="ShowWorldMapButton"/> - <menu_item_check label="ミニマップのボタン" name="ShowMiniMapButton"/> + <menu_item_check label="サイドバーボタン" name="ShowSidebarButton"/> + <menu_item_check label="制作ボタン" name="ShowBuildButton"/> + <menu_item_check label="検索ボタン" name="ShowSearchButton"/> + <menu_item_check label="地図ボタン" name="ShowWorldMapButton"/> + <menu_item_check label="ミニマップボタン" name="ShowMiniMapButton"/> <menu_item_call label="切り取り" name="NearbyChatBar_Cut"/> <menu_item_call label="コピー" name="NearbyChatBar_Copy"/> <menu_item_call label="貼り付け" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 1ac7677b07..c82f1198a4 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -349,7 +349,7 @@ L$ が不足しているのでこのグループに参加することができ <usetemplate name="okcancelbuttons" notext="もう一度試す" yestext="新しいアカウントを作成"/> </notification> <notification name="InvalidCredentialFormat"> - 「ユーザー名」欄にアバターのファーストネームとラストネーム両方を入力してからログインしてください。 + 「ユーザーネーム」欄にアバターのファーストネームとラストネーム両方を入力してからログインしてください。 </notification> <notification name="AddClassified"> クラシファイド広告は、検索ディレクトリと [http://secondlife.com/community/classifieds secondlife.com] の「クラシファイド広告」セクションに一週間掲載されます。 diff --git a/indra/newview/skins/default/xui/ja/panel_login.xml b/indra/newview/skins/default/xui/ja/panel_login.xml index f0ebc67ef5..47d7a88b4c 100644 --- a/indra/newview/skins/default/xui/ja/panel_login.xml +++ b/indra/newview/skins/default/xui/ja/panel_login.xml @@ -9,9 +9,9 @@ <layout_stack name="login_widgets"> <layout_panel name="login"> <text name="username_text"> - ユーザー名: + ユーザーネーム: </text> - <line_editor label="ユーザー名" name="username_edit" tool_tip="[SECOND_LIFE] ユーザー名"/> + <line_editor label="ユーザーネーム" name="username_edit" tool_tip="[SECOND_LIFE] ユーザーネーム"/> <text name="password_text"> パスワード: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 7671f58691..4044110b47 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -26,9 +26,9 @@ Placa gráfica: [GRAPHICS_CARD] Versão libcurl: [LIBCURL_VERSION] Versão J2C Decoder: [J2C_VERSION] -Versão do driver de áudio: [AUDIO_DRIVER_VERSION] +Versão do driver de áudio: [AUDIO_DRIVER_VERSION] Versão Qt Webkit: [QT_WEBKIT_VERSION] -Versão Vivox: [VIVOX_VERSION] +Versão do servidor de voz: [VOICE_VERSION] </floater.string> <floater.string name="none"> (nenhum) diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml index 787836a8bd..56ffcbdece 100644 --- a/indra/newview/skins/default/xui/pt/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml @@ -63,6 +63,9 @@ Nenhum lote selecionado. Vá para o menu Mundo > Sobre o terreno ou selecione outro lote para mostrar os detalhes. </panel.string> + <panel.string name="time_stamp_template"> + [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] + </panel.string> <text name="Name:"> Nome: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml index 5fb64f64b3..9473ee7ce9 100644 --- a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml @@ -3,41 +3,48 @@ <floater.string name="InvalidAvatar"> AVATAR INVÁLIDO </floater.string> - <text name="composite_label"> - Texturas compostas - </text> - <button label="Tombar" label_selected="Tombar" name="Dump"/> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> - <texture_picker label="Cabelo" name="hair-baked"/> - <texture_picker label="Cabelo" name="hair_grain"/> - <texture_picker label="Cabelo alpha" name="hair_alpha"/> - <texture_picker label="Cabeça" name="head-baked"/> - <texture_picker label="Maquilagem" name="head_bodypaint"/> - <texture_picker label="Cabeça Alpha" name="head_alpha"/> - <texture_picker label="Tatuagem na cabeça" name="head_tattoo"/> - <texture_picker label="Olhos" name="eyes-baked"/> - <texture_picker label="Olho" name="eyes_iris"/> - <texture_picker label="Olhos Alpha" name="eyes_alpha"/> - <texture_picker label="Cintura acima" name="upper-baked"/> - <texture_picker label="Pintura corporal, cintura para cima" name="upper_bodypaint"/> - <texture_picker label="Camiseta" name="upper_undershirt"/> - <texture_picker label="Luvas" name="upper_gloves"/> - <texture_picker label="Camisa" name="upper_shirt"/> - <texture_picker label="Jaqueta (cima)" name="upper_jacket"/> - <texture_picker label="Alpha de cima" name="upper_alpha"/> - <texture_picker label="Tatuagem parte de cima" name="upper_tattoo"/> - <texture_picker label="Cintura para baixo" name="lower-baked"/> - <texture_picker label="Pintura corporal, cintura para baixo" name="lower_bodypaint"/> - <texture_picker label="Roupa de baixo" name="lower_underpants"/> - <texture_picker label="Meias" name="lower_socks"/> - <texture_picker label="Sapatos" name="lower_shoes"/> - <texture_picker label="Calças" name="lower_pants"/> - <texture_picker label="Jaqueta" name="lower_jacket"/> - <texture_picker label="Alpha inferior" name="lower_alpha"/> - <texture_picker label="Tatuagem de baixo" name="lower_tattoo"/> - <texture_picker label="Saia" name="skirt-baked"/> - <texture_picker label="Saia" name="skirt"/> + <text name="label"> + Pronto +Texturas + </text> + <text name="composite_label"> + Compósito: +Texturas + </text> + <button label="Enviar IDs para painel" label_selected="Dump" name="Dump"/> + <panel name="scroll_content_panel"> + <texture_picker label="Cabelo" name="hair-baked"/> + <texture_picker label="Cabelo" name="hair_grain"/> + <texture_picker label="Cabelo alpha" name="hair_alpha"/> + <texture_picker label="Cabeça" name="head-baked"/> + <texture_picker label="Maquilagem" name="head_bodypaint"/> + <texture_picker label="Cabeça Alpha" name="head_alpha"/> + <texture_picker label="Tatuagem na cabeça" name="head_tattoo"/> + <texture_picker label="Olhos" name="eyes-baked"/> + <texture_picker label="Olho" name="eyes_iris"/> + <texture_picker label="Olhos Alpha" name="eyes_alpha"/> + <texture_picker label="Cintura acima" name="upper-baked"/> + <texture_picker label="Pintura corporal, cintura para cima" name="upper_bodypaint"/> + <texture_picker label="Camiseta" name="upper_undershirt"/> + <texture_picker label="Luvas" name="upper_gloves"/> + <texture_picker label="Camisa" name="upper_shirt"/> + <texture_picker label="Jaqueta (cima)" name="upper_jacket"/> + <texture_picker label="Alpha de cima" name="upper_alpha"/> + <texture_picker label="Tatuagem parte de cima" name="upper_tattoo"/> + <texture_picker label="Cintura para baixo" name="lower-baked"/> + <texture_picker label="Cintura para baixo" name="lower_bodypaint"/> + <texture_picker label="Roupa de baixo" name="lower_underpants"/> + <texture_picker label="Meias" name="lower_socks"/> + <texture_picker label="Sapatos" name="lower_shoes"/> + <texture_picker label="Calças" name="lower_pants"/> + <texture_picker label="Jaqueta" name="lower_jacket"/> + <texture_picker label="Alpha inferior" name="lower_alpha"/> + <texture_picker label="Tatuagem de baixo" name="lower_tattoo"/> + <texture_picker label="Saia" name="skirt-baked"/> + <texture_picker label="Saia" name="skirt"/> + </panel> </panel> </scroll_container> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml new file mode 100644 index 0000000000..24e41ac8c8 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_buy_currency_html" title="COMPRAR MOEDA"/> diff --git a/indra/newview/skins/default/xui/pt/floater_map.xml b/indra/newview/skins/default/xui/pt/floater_map.xml index 3a04528228..f8e4e76752 100644 --- a/indra/newview/skins/default/xui/pt/floater_map.xml +++ b/indra/newview/skins/default/xui/pt/floater_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Map" title="Mini Mapa"> +<floater name="Map" title=""> <floater.string name="mini_map_north"> N </floater.string> diff --git a/indra/newview/skins/default/xui/pt/floater_moveview.xml b/indra/newview/skins/default/xui/pt/floater_moveview.xml index 9c02570076..b1dc65e3af 100644 --- a/indra/newview/skins/default/xui/pt/floater_moveview.xml +++ b/indra/newview/skins/default/xui/pt/floater_moveview.xml @@ -6,18 +6,48 @@ <string name="walk_back_tooltip"> Andar para trás (flecha para baixo ou S) </string> + <string name="walk_left_tooltip"> + Andar para a esquerda (Shift + Seta esquerda ou A) + </string> + <string name="walk_right_tooltip"> + Andar para a direita (Shift + Seta direita ou D) + </string> <string name="run_forward_tooltip"> Correr para frente (flecha para cima ou W) </string> <string name="run_back_tooltip"> Correr para trás (flecha para baixo ou S) </string> + <string name="run_left_tooltip"> + Correr para a esquerda (Shift + Seta esquerda ou A) + </string> + <string name="run_right_tooltip"> + Correr para a direita (Shift + Seta direita ou D) + </string> <string name="fly_forward_tooltip"> Voar para frente (flecha para cima ou W) </string> <string name="fly_back_tooltip"> Voar para trás (flecha para baixo ou S) </string> + <string name="fly_left_tooltip"> + Voar para a esquerda (Shift + Seta esquerda ou A) + </string> + <string name="fly_right_tooltip"> + Voar para a direita (Shift + Seta direita ou D) + </string> + <string name="fly_up_tooltip"> + Voar para cima (tecla E) + </string> + <string name="fly_down_tooltip"> + Voar para baixo (tecla C) + </string> + <string name="jump_tooltip"> + Pular (tecla E) + </string> + <string name="crouch_tooltip"> + Agachar (tecla C) + </string> <string name="walk_title"> Andar </string> @@ -28,10 +58,12 @@ Voar </string> <panel name="panel_actions"> - <button label="" label_selected="" name="turn left btn" tool_tip="Virar à esquerda (flecha ESQ ou A)"/> - <button label="" label_selected="" name="turn right btn" tool_tip="Virar à direita (flecha DIR ou D)"/> <button label="" label_selected="" name="move up btn" tool_tip="Voar para cima (tecla E)"/> + <button label="" label_selected="" name="turn left btn" tool_tip="Virar à esquerda (flecha ESQ ou A)"/> + <joystick_slide name="move left btn" tool_tip="Andar para a esquerda (Shift + Seta esquerda ou A)"/> <button label="" label_selected="" name="move down btn" tool_tip="Voar para baixo (tecla C)"/> + <button label="" label_selected="" name="turn right btn" tool_tip="Virar à direita (flecha DIR ou D)"/> + <joystick_slide name="move right btn" tool_tip="Andar para a direita (Shift + Seta direita ou D)"/> <joystick_turn name="forward btn" tool_tip="Andar para frente (flecha para cima ou W)"/> <joystick_turn name="backward btn" tool_tip="Andar para trás (flecha para baixo ou S)"/> </panel> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml index e648a7d873..d094c1b63a 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml @@ -9,9 +9,6 @@ <floater.string name="Title"> Anotação: [NAME] </floater.string> - <floater.string label="Salvar" label_selected="Salvar" name="Save"> - Salvar - </floater.string> <text name="desc txt"> Descrição: </text> @@ -19,4 +16,5 @@ Carregando... </text_editor> <button label="Salvar" label_selected="Salvar" name="Save"/> + <button label="Excluir" label_selected="Excluir" name="Delete"/> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml index 74b45f1d1e..dbc8b3ffbe 100644 --- a/indra/newview/skins/default/xui/pt/floater_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_tools.xml @@ -67,9 +67,9 @@ <text name="RenderingCost" tool_tip="Mostra o cálculo do custo de renderização do objeto"> þ: [COUNT] </text> - <check_box name="checkbox uniform"/> - <text name="checkbox uniform label"> - Esticar ambos os lados + <check_box label="" name="checkbox uniform"/> + <text label="Esticar ambos lados" name="checkbox uniform label"> + Esticar ambos lados </text> <check_box initial_value="true" label="Esticar texturas" name="checkbox stretch textures"/> <check_box initial_value="true" label="Mostrar na grade" name="checkbox snap to grid"/> diff --git a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml index de3178b946..5cb1b211cf 100644 --- a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml @@ -5,7 +5,7 @@ <menu_item_call label="Tirar" name="Detach"/> <menu_item_call label="Largar" name="Drop"/> <menu_item_call label="Ficar de pé" name="Stand Up"/> - <menu_item_call label="Minha aparência" name="Appearance..."/> + <menu_item_call label="Trocar de look" name="Change Outfit"/> <menu_item_call label="Meus amigos" name="Friends..."/> <menu_item_call label="Meus grupos" name="Groups..."/> <menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml index ccbb921ebc..62055303b5 100644 --- a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml @@ -20,7 +20,9 @@ <context_menu label="Tirar ▶" name="Object Detach"/> <menu_item_call label="Tirar tudo" name="Detach All"/> </context_menu> - <menu_item_call label="Minha aparência" name="Appearance..."/> + <menu_item_call label="Trocar de look" name="Chenge Outfit"/> + <menu_item_call label="Editar meu look" name="Edit Outfit"/> + <menu_item_call label="Editar meu corpo" name="Edit My Shape"/> <menu_item_call label="Meus amigos" name="Friends..."/> <menu_item_call label="Meus grupos" name="Groups..."/> <menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml index 43b446a67e..479d02512f 100644 --- a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml @@ -4,6 +4,11 @@ <menu_item_check label="Botão de movimento" name="ShowMoveButton"/> <menu_item_check label="Botão de ver" name="ShowCameraButton"/> <menu_item_check label="Botão de fotos" name="ShowSnapshotButton"/> + <menu_item_check label="Botão da Barra lateral" name="ShowSidebarButton"/> + <menu_item_check label="Botão Construir" name="ShowBuildButton"/> + <menu_item_check label="Botão Buscar" name="ShowSearchButton"/> + <menu_item_check label="Botão Mapa" name="ShowWorldMapButton"/> + <menu_item_check label="Botão do Mini Mapa" name="ShowMiniMapButton"/> <menu_item_call label="Cortar" name="NearbyChatBar_Cut"/> <menu_item_call label="Copiar" name="NearbyChatBar_Copy"/> <menu_item_call label="Colar" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml index effc970eb8..c3e0608954 100644 --- a/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <menu name="Gear Menu"> <menu_item_call label="Ficar de pé" name="stand_up"/> - <menu_item_call label="Minha aparência" name="my_appearance"/> + <menu_item_call label="Trocar de look" name="change_outfit"/> <menu_item_call label="Meu perfil" name="my_profile"/> <menu_item_call label="Meus amigos" name="my_friends"/> <menu_item_call label="Meus grupos" name="my_groups"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml index 345534261a..1b86b37075 100644 --- a/indra/newview/skins/default/xui/pt/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml @@ -54,6 +54,7 @@ <menu_item_call label="Remover item" name="Purge Item"/> <menu_item_call label="Restaurar item" name="Restore Item"/> <menu_item_call label="Abrir" name="Open"/> + <menu_item_call label="Abrir original" name="Open Original"/> <menu_item_call label="Propriedades" name="Properties"/> <menu_item_call label="Renomear" name="Rename"/> <menu_item_call label="Copiar item UUID" name="Copy Asset UUID"/> diff --git a/indra/newview/skins/default/xui/pt/menu_login.xml b/indra/newview/skins/default/xui/pt/menu_login.xml index 8ea87a06d1..a43ac271a9 100644 --- a/indra/newview/skins/default/xui/pt/menu_login.xml +++ b/indra/newview/skins/default/xui/pt/menu_login.xml @@ -2,7 +2,7 @@ <menu_bar name="Login Menu"> <menu label="Eu" name="File"> <menu_item_call label="Preferências" name="Preferences..."/> - <menu_item_call label="Sair" name="Quit"/> + <menu_item_call label="Sair do [APP_NAME]" name="Quit"/> </menu> <menu label="Ajuda" name="Help"> <menu_item_call label="Ajuda do [SECOND_LIFE]" name="Second Life Help"/> diff --git a/indra/newview/skins/default/xui/pt/menu_participant_list.xml b/indra/newview/skins/default/xui/pt/menu_participant_list.xml index c0db7752af..01f1d4ef80 100644 --- a/indra/newview/skins/default/xui/pt/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/pt/menu_participant_list.xml @@ -14,8 +14,8 @@ <context_menu label="Opções do moderador >" name="Moderator Options"> <menu_item_check label="Pode bater papo por escrito" name="AllowTextChat"/> <menu_item_call label="Silenciar este participante" name="ModerateVoiceMuteSelected"/> - <menu_item_call label="Silenciar os demais" name="ModerateVoiceMuteOthers"/> <menu_item_call label="Desfazer silenciar deste participante" name="ModerateVoiceUnMuteSelected"/> - <menu_item_call label="Desfazer silenciar dos demais" name="ModerateVoiceUnMuteOthers"/> + <menu_item_call label="Silenciar todos" name="ModerateVoiceMute"/> + <menu_item_call label="Desfazer silenciar para todos" name="ModerateVoiceUnmute"/> </context_menu> </context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index 84ad056df6..b091cc2c97 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -7,7 +7,7 @@ </menu_item_call> <menu_item_call label="Comprar L$" name="Buy and Sell L$"/> <menu_item_call label="Meu perfil" name="Profile"/> - <menu_item_call label="Minha aparência" name="Appearance"/> + <menu_item_call label="Trocar de look" name="ChangeOutfit"/> <menu_item_check label="Meu inventário" name="Inventory"/> <menu_item_check label="Meu inventário" name="ShowSidetrayInventory"/> <menu_item_check label="Meus gestos" name="Gestures"/> @@ -162,6 +162,7 @@ <menu_item_check label="Objetos flexíveis" name="Flexible Objects"/> </menu> <menu_item_check label="Executar diversas instâncias" name="Run Multiple Threads"/> + <menu_item_check label="Usar plugin de leitura de threads" name="Use Plugin Read Thread"/> <menu_item_call label="Limpar cache de grupo" name="ClearGroupCache"/> <menu_item_check label="Smoothing de mouse" name="Mouse Smoothing"/> <menu label="Atalhos" name="Shortcuts"> @@ -188,7 +189,6 @@ <menu_item_call label="Mais zoom" name="Zoom In"/> <menu_item_call label="Zoom padrão" name="Zoom Default"/> <menu_item_call label="Menos zoom" name="Zoom Out"/> - <menu_item_call label="Alternar tela inteira" name="Toggle Fullscreen"/> </menu> <menu_item_call label="Mostrar configurações de depuração" name="Debug Settings"/> <menu_item_check label="Show Develop Menu" name="Debug Mode"/> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 462dcf2b21..e64940ecb1 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -323,6 +323,9 @@ Você precisa de uma conta para entrar no [SECOND_LIFE]. Você gostaria de abrir </url> <usetemplate name="okcancelbuttons" notext="Tentar novamente" yestext="Abrir conta"/> </notification> + <notification name="InvalidCredentialFormat"> + Digite o nome e sobrenome do seu avatar no campo Nome de usuário, depois faça o login novamente. + </notification> <notification name="AddClassified"> Os anúncios serão publicados na seção 'Classificados' das buscas e em [http://secondlife.com/community/classifieds secondlife.com] durante uma semana. Escreva seu anúncio e clique em 'Publicar...' @@ -603,6 +606,11 @@ Esperada [VALIDS] <notification name="CannotEncodeFile"> Impossível codificar o arquivo: [FILE] </notification> + <notification name="CorruptedProtectedDataStore"> + Não foi possível fazer a leitura dos dados protegidos, redefinindo. + Isso pode ocorrer após mudanças na configuração da rede. + <usetemplate name="okbutton" yestext="OK"/> + </notification> <notification name="CorruptResourceFile"> Fonte do arquivo corrompida: [FILE] </notification> @@ -962,6 +970,12 @@ em TODOS OS TERRENOS deste sim? Por favor, insira um valor maior. </notification> + <notification name="ConfirmItemDeleteHasLinks"> + Pelo menos um dos itens possui links que levam a ele. Ao excluir o item, os links não funcionarão mais. Por isso, recomendamos excluir os links primeiro. + +Tem certeza de que quer excluir estes items? + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> + </notification> <notification name="ConfirmObjectDeleteLock"> Pelo menos um dos itens que você selecionou está trancado. @@ -1103,6 +1117,42 @@ Pressione a tecla F1 para ajuda ou aprender mais sobre [SECOND_LIFE]. Por favor, escolha se o seu avatar é feminino ou masculino. Você pode mudar de idéia depois. <usetemplate name="okcancelbuttons" notext="Feminino" yestext="Masculino"/> </notification> + <notification name="CantTeleportToGrid"> + Não foi possível ir para [SLURL], que fica em outro grid ([GRID]) em relação ao grid atual, ([CURRENT_GRID]). Feche o Visualizador e tente novamente. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GeneralCertificateError"> + Falha de conexão com o servidor. +[REASON] + +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Válido de: [VALID_FROM] +Válido até: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +Impressão digital SHA1: [MD5_DIGEST] +Uso da chave: [KEYUSAGE] +Uso estendido da chave: [EXTENDEDKEYUSAGE] +Identificador chave de assunto: [SUBJECTKEYIDENTIFIER] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TrustCertificateError"> + A autoridade de certificação deste servidor é desconhecida. + +Dados do certificado: +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Válido de: [VALID_FROM] +Válido até: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +Impressão digital SHA1: [MD5_DIGEST] +Uso da chave: [KEYUSAGE] +Uso estendido da chave: [EXTENDEDKEYUSAGE] +Identificador chave de assunto: [SUBJECTKEYIDENTIFIER] + +Confiar nesta autoridade? + <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Confiança"/> + </notification> <notification name="NotEnoughCurrency"> [NAME] L$ [PRICE] Você não possui suficientes L$ para fazer isso. </notification> @@ -1493,9 +1543,9 @@ Ir para o Banco de Conhecimento para maiores informações sobre Classificaçõe Você não é permitido nesta região devido à sua Classificação de maturidade. </notification> <notification name="RegionEntryAccessBlocked_Change"> - Você não pode entrar nessa região devido à sua seleção de maturidade. + Você não pode entrar nessa região devido à sua seleção de maturidade. -Clique em 'Mudar preferência' para aumentar o nível de maturidade e entrar nessa região. De agora em diante você pode buscar e acessar conteúdo [REGIONMATURITY] . Para modificar esta configuração, vá à Eu > Preferências > Geral. +Clique em 'Mudar preferência' para aumentar seu nível de maturidade e ganhar acesso imediato. Você então poderá fazer buscas e acessar conteúdo [REGIONMATURITY]. Para modificar o nível de maturidade, use o menu Eu > Preferências > Gerais. <form name="form"> <button name="OK" text="Mudar preferência"/> <button default="true" name="Cancel" text="Fechar"/> @@ -2262,15 +2312,6 @@ Por favor, tente novamente em alguns instantes. <button name="Mute" text="Bloquear"/> </form> </notification> - <notification name="ObjectGiveItemUnknownUser"> - Um objeto chamado [OBJECTFROMNAME] de (residente desconhecido) lhe deu [OBJECTTYPE]: -[ITEM_SLURL] - <form name="form"> - <button name="Keep" text="Segure"/> - <button name="Discard" text="Descarte"/> - <button name="Mute" text="Bloquear"/> - </form> - </notification> <notification name="UserGiveItem"> [NAME_SLURL] lhe deu [OBJECTTYPE]: [ITEM_SLURL] @@ -2583,8 +2624,52 @@ O botão será exibido quando houver espaço suficente. <notification name="ShareNotification"> Arraste itens do inventário para uma pessoa no seletor de residentes </notification> + <notification name="DeedToGroupFail"> + Ocorreu uma falha durante a doação ao grupo. + </notification> <notification name="AvatarRezNotification"> - O avatar de '[NAME]' renderizou em [TIME] s. + ( [EXISTENCE] segundos de vida ) +O avatar de '[NAME]' emergiu em [TIME] segundos. + </notification> + <notification name="AvatarRezSelfNotification"> + ( [EXISTENCE] segundos de vida ) +Você confeccionou seu look em [TIME] segundos. + </notification> + <notification name="AvatarRezCloudNotification"> + ( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' transformou-se em nuvem. + </notification> + <notification name="AvatarRezArrivedNotification"> + ( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' surgiu. + </notification> + <notification name="AvatarRezLeftCloudNotification"> + ( [EXISTENCE] segundos de vida ) +O avatar de '[NAME]' transformou-se em nuvem depois de [TIME] segundos. + </notification> + <notification name="AvatarRezEnteredAppearanceNotification"> + ( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' entrou no modo aparência. + </notification> + <notification name="AvatarRezLeftAppearanceNotification"> + ( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' sair do modo aparecer. + </notification> + <notification name="AvatarRezLeftNotification"> + ( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' saiu totalmente carregado. + </notification> + <notification name="ConfirmLeaveCall"> + Tem certeza de que quer sair desta ligação? + <usetemplate ignoretext="Confirmar antes de deixar ligação" name="okcancelignore" notext="Não" yestext="Sim"/> + </notification> + <notification name="ConfirmMuteAll"> + Você silenciou todos os participantes de uma ligação de grupo. +Todos os demais residentes que entrarem na ligação mais tarde também serão silenciados, mesmo se você sair da ligação. + + +Silenciar todos? + <usetemplate ignoretext="Confirmar antes de silenciar todos os participantes em ligações de grupo." name="okcancelignore" notext="OK" yestext="Cancelar"/> </notification> <global name="UnsupportedCPU"> - A velocidade da sua CPU não suporta os requisitos mínimos exigidos. diff --git a/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..094a03553b --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Trocar" name="switch_btn"/> + <button label="Comprar >" name="bodyparts_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_bottomtray.xml b/indra/newview/skins/default/xui/pt/panel_bottomtray.xml index 092135bd42..9fd7da55df 100644 --- a/indra/newview/skins/default/xui/pt/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/pt/panel_bottomtray.xml @@ -1,11 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="bottom_tray"> - <string name="SpeakBtnToolTip"> - Liga e desliga o microfone - </string> - <string name="VoiceControlBtnToolTip"> - Mostra/oculta os controles de voz - </string> + <string name="SpeakBtnToolTip" value="Liga e desliga o microfone"/> + <string name="VoiceControlBtnToolTip" value="Mostra/oculta os controles de voz"/> <layout_stack name="toolbar_stack"> <layout_panel name="speak_panel"> <talk_button name="talk"> @@ -24,6 +20,21 @@ <layout_panel name="snapshot_panel"> <button label="" name="snapshots" tool_tip="Tirar foto"/> </layout_panel> + <layout_panel name="sidebar_btn_panel"> + <button label="Barra lateral" name="sidebar_btn" tool_tip="Mostra/oculta a barra lateral"/> + </layout_panel> + <layout_panel name="build_btn_panel"> + <button label="Construir" name="build_btn" tool_tip="Mostra/oculta ferramentas de Construção"/> + </layout_panel> + <layout_panel name="search_btn_panel"> + <button label="Busca" name="search_btn" tool_tip="Mostra/oculta os gestos"/> + </layout_panel> + <layout_panel name="world_map_btn_panel"> + <button label="Mapa" name="world_map_btn" tool_tip="Mostra/oculta o Mapa Múndi"/> + </layout_panel> + <layout_panel name="mini_map_btn_panel"> + <button label="Mini Mapa" name="mini_map_btn" tool_tip="Mostra/oculta o Mini Mapa"/> + </layout_panel> <layout_panel name="im_well_panel"> <chiclet_im_well name="im_well"> <button name="Unread IM messages" tool_tip="Conversas"/> diff --git a/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..bfdc7290d2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Adicionar +" name="add_btn"/> + <button label="Comprar >" name="clothing_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml b/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml new file mode 100644 index 0000000000..3e4b12b001 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="cof_wearables"> + <accordion name="cof_wearables_accordion"> + <accordion_tab name="tab_attachments" title="Anexos"/> + <accordion_tab name="tab_clothing" title="Vestuário"/> + <accordion_tab name="tab_body_parts" title="Corpo"/> + </accordion> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml new file mode 100644 index 0000000000..91d90a5660 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="deletable_wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml new file mode 100644 index 0000000000..6af84de0c7 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="dummy_clothing_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_shape.xml b/indra/newview/skins/default/xui/pt/panel_edit_shape.xml index 504486c3bb..6b9ac94cac 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_shape.xml @@ -1,14 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="edit_shape_panel"> - <panel name="avatar_sex_panel"> - <text name="gender_text"> - Sexo: - </text> - <radio_group name="sex_radio"> - <radio_item label="Feminino" name="radio"/> - <radio_item label="Masculino" name="radio2"/> - </radio_group> - </panel> + <text name="avatar_height"> + [HEIGHT] metros de altura + </text> <panel label="Camisa" name="accordion_panel"> <accordion name="wearable_accordion"> <accordion_tab name="shape_body_tab" title="Corpo"/> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml index 23cde50acc..f85bb3c499 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml @@ -4,5 +4,6 @@ <texture_picker label="Tatuagem de cabeça" name="Head Tattoo" tool_tip="Clique para escolher uma foto"/> <texture_picker label="Tatuagem superior" name="Upper Tattoo" tool_tip="Selecione uma foto"/> <texture_picker label="Tatuagem inferior" name="Lower Tattoo" tool_tip="Selecione uma foto"/> + <color_swatch label="Cor/Tonalidade" name="Color/Tint" tool_tip="Selecionar a cor"/> </panel> </panel> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml index a78539f274..f14a04f440 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml @@ -93,6 +93,12 @@ <text name="edit_wearable_title" value="Editando forma"/> <panel label="Camisa" name="wearable_type_panel"> <text name="description_text" value="Forma:"/> + <radio_group name="sex_radio"> + <radio_item label="" name="sex_male" tool_tip="Masculino" value="1"/> + <radio_item label="" name="sex_female" tool_tip="Feminino" value="0"/> + </radio_group> + <icon name="male_icon" tool_tip="Masculino"/> + <icon name="female_icon" tool_tip="Feminino"/> </panel> <panel label="gear_buttom_panel" name="gear_buttom_panel"> <button name="friends_viewsort_btn" tool_tip="Opções"/> diff --git a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml index 6f21b78b10..e57a85a726 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml @@ -6,6 +6,9 @@ <panel.string name="cant_view_group_land_text"> Você não está autorizado a acessar terrenos de grupos </panel.string> + <panel.string name="epmty_view_group_land_text"> + Nada consta + </panel.string> <panel.string name="cant_view_group_accounting_text"> Você não está autorizado a acessar os dados de contabilidade do grupo. </panel.string> diff --git a/indra/newview/skins/default/xui/pt/panel_group_notices.xml b/indra/newview/skins/default/xui/pt/panel_group_notices.xml index 4b5a00c761..9ccb85cdf6 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_notices.xml @@ -39,6 +39,7 @@ Cada grupo pode enviar no máximo 200 avisos/dia <text name="string"> Arrastar e soltar o item aqui para anexá-lo: </text> + <button label="Inventário" name="open_inventory" tool_tip="Inventário aberto"/> <button label="Tirar" label_selected="Remover o anexo" name="remove_attachment" tool_tip="Remover anexo da notificação."/> <button label="Enviar" label_selected="Enviar" name="send_notice"/> <group_drop_target name="drop_target" tool_tip="Arrastar um item do inventário para a caixa para enviá-lo com o aviso. É preciso ter autorização de cópia e transferência do item para anexá-lo ao aviso."/> diff --git a/indra/newview/skins/default/xui/pt/panel_login.xml b/indra/newview/skins/default/xui/pt/panel_login.xml index 588b8deaa3..94a885960a 100644 --- a/indra/newview/skins/default/xui/pt/panel_login.xml +++ b/indra/newview/skins/default/xui/pt/panel_login.xml @@ -8,18 +8,15 @@ </panel.string> <layout_stack name="login_widgets"> <layout_panel name="login"> - <text name="first_name_text"> - Primeiro nome: + <text name="username_text"> + Nome de usuário: </text> - <line_editor label="Nome" name="first_name_edit" tool_tip="[SECOND_LIFE] First Name"/> - <text name="last_name_text"> - Sobrenome: - </text> - <line_editor label="Sobrenome" name="last_name_edit" tool_tip="[SECOND_LIFE] Last Name"/> + <line_editor label="Nome de usuário" name="username_edit" tool_tip="[SECOND_LIFE] Nome de usuário"/> <text name="password_text"> Senha: </text> <check_box label="Lembrar senha" name="remember_check"/> + <button label="conectar" name="connect_btn"/> <text name="start_location_text"> Começar em: </text> @@ -27,7 +24,6 @@ <combo_box.item label="Última posição" name="MyLastLocation"/> <combo_box.item label="Meu início" name="MyHome"/> </combo_box> - <button label="conectar" name="connect_btn"/> </layout_panel> <layout_panel name="links"> <text name="create_new_account_text"> diff --git a/indra/newview/skins/default/xui/pt/panel_main_inventory.xml b/indra/newview/skins/default/xui/pt/panel_main_inventory.xml index 104c3bface..dbf8e4fa52 100644 --- a/indra/newview/skins/default/xui/pt/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/pt/panel_main_inventory.xml @@ -9,62 +9,20 @@ <text name="ItemcountText"> Itens: </text> - <menu_bar name="Inventory Menu"> - <menu label="Arquivo" name="File"> - <menu_item_call label="Abrir" name="Open"/> - <menu label="Upload" name="upload"> - <menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/> - <menu_item_call label="Som (L$[COST])..." name="Upload Sound"/> - <menu_item_call label="Animação (L$[COST])..." name="Upload Animation"/> - <menu_item_call label="Volume (L$[COST] per file)..." name="Bulk Upload"/> - </menu> - <menu_item_call label="Nova janela" name="New Window"/> - <menu_item_call label="Mostrar filtros" name="Show Filters"/> - <menu_item_call label="Restabelecer filtros" name="Reset Current"/> - <menu_item_call label="Fechar todas as pastas" name="Close All Folders"/> - <menu_item_call label="Esvaziar lixeira" name="Empty Trash"/> - <menu_item_call label="Esvaziar achados e perdidos" name="Empty Lost And Found"/> - </menu> - <menu label="Crie" name="Create"> - <menu_item_call label="Nova pasta" name="New Folder"/> - <menu_item_call label="Novo script" name="New Script"/> - <menu_item_call label="Nova anotação" name="New Note"/> - <menu_item_call label="Novo gesto" name="New Gesture"/> - <menu label="Novas roupas" name="New Clothes"> - <menu_item_call label="Nova camisa" name="New Shirt"/> - <menu_item_call label="Novas calças" name="New Pants"/> - <menu_item_call label="Novos sapatos" name="New Shoes"/> - <menu_item_call label="Novas meias" name="New Socks"/> - <menu_item_call label="Nova blusa" name="New Jacket"/> - <menu_item_call label="Nova saia" name="New Skirt"/> - <menu_item_call label="Novas luvas" name="New Gloves"/> - <menu_item_call label="Nova camiseta" name="New Undershirt"/> - <menu_item_call label="Novas roupa de baixo" name="New Underpants"/> - <menu_item_call label="Novo alpha" name="New Alpha"/> - <menu_item_call label="Nova tatuagem" name="New Tattoo"/> - </menu> - <menu label="Nova parte do corpo" name="New Body Parts"> - <menu_item_call label="Nova forma" name="New Shape"/> - <menu_item_call label="Nova pele" name="New Skin"/> - <menu_item_call label="Novo cabelo" name="New Hair"/> - <menu_item_call label="Novos olhos" name="New Eyes"/> - </menu> - </menu> - <menu label="Classificar" name="Sort"> - <menu_item_check label="Por nome" name="By Name"/> - <menu_item_check label="Por data" name="By Date"/> - <menu_item_check label="Pastas sempre por nome" name="Folders Always By Name"/> - <menu_item_check label="Pastas do sistema no topo" name="System Folders To Top"/> - </menu> - </menu_bar> <filter_editor label="Filtro" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Todos os itens" name="All Items"/> - <inventory_panel label="Itens recentes" name="Recent Items"/> + <recent_inventory_panel label="Itens recentes" name="Recent Items"/> </tab_container> - <panel name="bottom_panel"> - <button name="options_gear_btn" tool_tip="Mostrar opções adicionais"/> - <button name="add_btn" tool_tip="Adicionar novo item"/> - <dnd_button name="trash_btn" tool_tip="Remover item selecionado"/> - </panel> + <layout_stack name="bottom_panel"> + <layout_panel name="options_gear_btn_panel"> + <button name="options_gear_btn" tool_tip="Mostrar opções adicionais"/> + </layout_panel> + <layout_panel name="add_btn_panel"> + <button name="add_btn" tool_tip="Adicionar novo item"/> + </layout_panel> + <layout_panel name="trash_btn_panel"> + <dnd_button name="trash_btn" tool_tip="Remover item selecionado"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml b/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml index 3dc8b4cc75..61e470586e 100644 --- a/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml @@ -2,6 +2,8 @@ <!-- Side tray Outfit Edit panel --> <panel label="Editar look" name="outfit_edit"> <string name="No Outfit" value="Nenhum"/> + <string name="unsaved_changes" value="Mudanças não salvas"/> + <string name="now_editing" value="Editando..."/> <panel.string name="not_available"> (N\A) </panel.string> @@ -21,18 +23,13 @@ </panel> <layout_stack name="im_panels"> <layout_panel label="Painel de controle de MIs" name="outfit_wearables_panel"> - <scroll_list name="look_items_list"> - <scroll_list.columns label="Ver item" name="look_item"/> - <scroll_list.columns label="Ordenar itens" name="look_item_sort"/> - </scroll_list> <panel label="bottom_panel" name="edit_panel"/> </layout_panel> <layout_panel name="add_wearables_panel"> - <filter_editor label="Filtro" name="look_item_filter"/> + <text name="add_to_outfit_label" value="Adicionar ao look:"/> <layout_stack name="filter_panels"> - <layout_panel label="Painel de controle de MIs" name="filter_button_panel"> - <text name="add_to_outfit_label" value="Adicionar ao look:"/> - <button label="O" name="filter_button"/> + <layout_panel label="Painel de controle de MIs" name="filter_panel"> + <filter_editor label="Filtro" name="look_item_filter"/> </layout_panel> </layout_stack> <panel label="add_wearables_button_bar" name="add_wearables_button_bar"> diff --git a/indra/newview/skins/default/xui/pt/panel_people.xml b/indra/newview/skins/default/xui/pt/panel_people.xml index 17f5b6cbac..efeea89fa9 100644 --- a/indra/newview/skins/default/xui/pt/panel_people.xml +++ b/indra/newview/skins/default/xui/pt/panel_people.xml @@ -2,9 +2,9 @@ <!-- Side tray panel --> <panel label="Pessoas" name="people_panel"> <string name="no_recent_people" value="Ninguém, recentemente. Em busca de alguém para conversar? Use a [secondlife:///app/search/people Busca] ou o [secondlife:///app/worldmap Mapa-Múndi]."/> - <string name="no_filtered_recent_people" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> + <string name="no_filtered_recent_people" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]."/> <string name="no_one_near" value="Ninguém por perto Em busca de alguém para conversar? Use a [secondlife:///app/search/people Busca] ou o [secondlife:///app/worldmap Mapa-Múndi]."/> - <string name="no_one_filtered_near" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> + <string name="no_one_filtered_near" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]."/> <string name="no_friends_online" value="Nenhum amigo online"/> <string name="no_friends" value="Nenhum amigo"/> <string name="no_friends_msg"> @@ -12,11 +12,11 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-Múndi]. </string> <string name="no_filtered_friends_msg"> - Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]. + Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]. </string> <string name="people_filter_label" value="Filtro de pessoas"/> <string name="groups_filter_label" value="Filtro de grupos"/> - <string name="no_filtered_groups_msg" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> + <string name="no_filtered_groups_msg" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/groups/[SEARCH_TERM] Search]."/> <string name="no_groups_msg" value="À procura de grupos interessantes? Tente fazer uma [secondlife:///app/search/groups Busca]."/> <filter_editor label="Filtro" name="filter_input"/> <tab_container name="tabs"> @@ -55,8 +55,8 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa- <button label="Perfil" name="view_profile_btn" tool_tip="Exibir fotografia, grupos e outras informações dos residentes" width="50"/> <button label="MI" name="im_btn" tool_tip="Iniciar MI" width="24"/> <button label="Chamada" name="call_btn" tool_tip="Ligar para este residente" width="61"/> - <button label="Compartilhar" name="share_btn" width="82"/> - <button label="Teletransporte" name="teleport_btn" tool_tip="Oferecer teletransporte" width="86"/> + <button label="Compartilhar" name="share_btn" tool_tip="Compartilhar item de inventário" width="82"/> + <button label="Teletransporte" name="teleport_btn" tool_tip="Oferecer teletransporte" width="86"/> <button label="Perfil do grupo" name="group_info_btn" tool_tip="Exibir informação de grupo"/> <button label="Bate-papo de grupo" name="chat_btn" tool_tip="Iniciar bate-papo"/> <button label="Ligar para o grupo" name="group_call_btn" tool_tip="Ligar para este grupo"/> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml index 6f2cae0476..885aafc350 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml @@ -13,6 +13,7 @@ </text> <check_box label="Construção/Edição" name="edit_camera_movement" tool_tip="Use o posicionamento automático da câmera quando entrar e sair do modo de edição"/> <check_box label="Aparência" name="appearance_camera_movement" tool_tip="Use o posicionamento automático da câmera quando em modo de edição"/> + <check_box initial_value="1" label="Barra lateral" name="appearance_sidebar_positioning" tool_tip="Usar posicionamento automático da câmera na barra lateral"/> <check_box label="Mostre-me em visão de mouse" name="first_person_avatar_visible"/> <check_box label="Teclas de seta sempre me movem" name="arrow_keys_move_avatar_check"/> <check_box label="Dê dois toques e pressione para correr" name="tap_tap_hold_to_run"/> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml index e566fde27c..02b0ef35fe 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml @@ -45,6 +45,7 @@ </text> <check_box initial_value="true" label="Executar animação digitada quando estiver conversando" name="play_typing_animation"/> <check_box label="Enviar MIs por email se estiver desconectado" name="send_im_to_email"/> + <check_box label="Ativar MIs e bate-papos de texto simples" name="plain_text_chat_history"/> <text name="show_ims_in_label"> Mostrar MIs em: </text> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml index eb38323940..ccf213099e 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml @@ -1,8 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Gráficos" name="Display panel"> - <text name="UI Size:"> - Interface: - </text> <text name="QualitySpeed"> Qualidade e velocidade: </text> @@ -53,6 +50,10 @@ rápido m </text> <slider label="Contador máx. de partículas:" name="MaxParticleCount"/> + <slider label="Distância máx. desenho avatar:" name="MaxAvatarDrawDistance"/> + <text name="DrawDistanceMeterText3"> + m + </text> <slider label="Qualidade de Pós-processamento:" name="RenderPostProcess"/> <text name="MeshDetailText"> Detalhes de Malha: diff --git a/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml b/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml index b8bbb4051a..f075f45b8f 100644 --- a/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml @@ -1,9 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Looks" name="appearance panel"> <string name="No Outfit" value="Nenhum"/> + <string name="Unsaved Changes" value="Mudanças não salvas"/> + <string name="Now Wearing" value="Look atual..."/> <panel name="panel_currentlook"> - <text name="currentlook_title"> - (não salvo) + <button label="E" name="editappearance_btn"/> + <button label="O" name="openoutfit_btn"/> + <text name="currentlook_status"> + (Status) </text> </panel> <filter_editor label="Filtrar looks" name="Filter"/> diff --git a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml index f634236cd2..31c96cad4c 100644 --- a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml @@ -4,6 +4,7 @@ <panel name="button_panel"> <button label="Perfil" name="info_btn"/> <button label="Compartilhar" name="share_btn"/> + <button label="Comprar" name="shop_btn"/> <button label="Vestir" name="wear_btn"/> <button label="Tocar" name="play_btn"/> <button label="Teletransportar" name="teleport_btn"/> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 51b6581d42..f865124009 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -88,6 +88,24 @@ <string name="LoginDownloadingClothing"> Baixando roupas... </string> + <string name="InvalidCertificate"> + O servidor respondeu com um certificado inválido ou corrompido. Por favor contate o administrador do Grid. + </string> + <string name="CertInvalidHostname"> + Um hostname inválido foi usado para acessar o servidor. Verifique o SLURL ou hostname do Grid. + </string> + <string name="CertExpired"> + O certificado dado pelo Grid parece estar vencido. Verifique o relógio do sistema ou contate o administrador do Grid. + </string> + <string name="CertKeyUsage"> + O certificado dado pelo servidor não pôde ser usado para SSL. Por favor contate o administrador do Grid. + </string> + <string name="CertBasicConstraints"> + A cadeia de certificados do servidor tinha certificados demais. Por favor contate o administrador do Grid. + </string> + <string name="CertInvalidSignature"> + A assinatura do certificado dado pelo servidor do Grid não pôde ser verificada. Por favor contate o administrador do Grid. + </string> <string name="LoginFailedNoNetwork"> Erro de rede: Não foi possível estabelecer a conexão, verifique sua conexão de rede. </string> @@ -819,6 +837,42 @@ <string name="invalid"> Inválido </string> + <string name="shirt_not_worn"> + Camisa não vestida + </string> + <string name="pants_not_worn"> + Calças não vestidas + </string> + <string name="shoes_not_worn"> + Sapatos não calçados + </string> + <string name="socks_not_worn"> + Meias não calçadas + </string> + <string name="jacket_not_worn"> + Jaqueta não vestida + </string> + <string name="gloves_not_worn"> + Luvas não calçadas + </string> + <string name="undershirt_not_worn"> + Camiseta não vestida + </string> + <string name="underpants_not_worn"> + Roupa de baixo não vestida + </string> + <string name="skirt_not_worn"> + Saia não vestida + </string> + <string name="alpha_not_worn"> + Alpha não vestido + </string> + <string name="tattoo_not_worn"> + Tatuagem não usada + </string> + <string name="invalid_not_worn"> + inválido + </string> <string name="NewWearable"> Novo [WEARABLE_ITEM] </string> @@ -889,7 +943,10 @@ Pressione ESC para retornar para visão do mundo </string> <string name="InventoryNoMatchingItems"> - Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]. + Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]. + </string> + <string name="PlacesNoMatchingItems"> + Não encontrou o que procura? Tente buscar no [secondlife:///app/search/groups/[SEARCH_TERM] Search]. </string> <string name="FavoritesNoMatchingItems"> Arraste um marco para adicioná-lo aos seus favoritos. @@ -919,6 +976,7 @@ <string name="Wave" value="Acenar"/> <string name="HelloAvatar" value="Olá, avatar!"/> <string name="ViewAllGestures" value="Ver todos>>"/> + <string name="GetMoreGestures" value="Mais >>"/> <string name="Animations" value="Animações,"/> <string name="Calling Cards" value="Cartões de visitas,"/> <string name="Clothing" value="Vestuário,"/> @@ -1542,6 +1600,9 @@ <string name="MuteGroup"> (grupo) </string> + <string name="MuteExternal"> + (Externo) + </string> <string name="RegionNoCovenant"> Não foi definido um contrato para essa região. </string> @@ -3299,11 +3360,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="answered_call"> Ligação atendida </string> - <string name="started_call"> - Iniciou uma ligação de voz + <string name="you_started_call"> + Você iniciou uma ligação de voz + </string> + <string name="you_joined_call"> + Você entrou na ligação </string> - <string name="joined_call"> - Entrou na ligação + <string name="name_started_call"> + [NAME] iniciou uma ligação de voz </string> <string name="ringing-im"> Entrando em ligação de voz... @@ -3502,6 +3566,90 @@ Denunciar abuso <string name="Contents"> Conteúdo </string> + <string name="Gesture"> + Gesto + </string> + <string name="Male Gestures"> + Gestos masculinos + </string> + <string name="Female Gestures"> + Gestos femininos + </string> + <string name="Other Gestures"> + Outros gestos + </string> + <string name="Speech Gestures"> + Gestos da fala + </string> + <string name="Common Gestures"> + Gestos comuns + </string> + <string name="Male - Excuse me"> + Perdão - masculino + </string> + <string name="Male - Get lost"> + Deixe-me em paz - masculino + </string> + <string name="Male - Blow kiss"> + Mandar beijo - masculino + </string> + <string name="Male - Boo"> + Vaia - masculino + </string> + <string name="Male - Bored"> + Maçante - masculino + </string> + <string name="Male - Hey"> + Ôpa! - masculino + </string> + <string name="Male - Laugh"> + Risada - masculino + </string> + <string name="Male - Repulsed"> + Quero distância! - masculino + </string> + <string name="Male - Shrug"> + Encolher de ombros - masculino + </string> + <string name="Male - Stick tougue out"> + Mostrar a língua - masculino + </string> + <string name="Male - Wow"> + Wow - masculino + </string> + <string name="FeMale - Excuse me"> + Perdão - masc/fem + </string> + <string name="FeMale - Get lost"> + Deixe-me em paz - feminino + </string> + <string name="FeMale - Blow kiss"> + Mandar beijo - masc/fem + </string> + <string name="FeMale - Boo"> + Vaia - masc/fem + </string> + <string name="Female - Bored"> + Maçante - feminino + </string> + <string name="Female - Hey"> + Ôpa - feminino + </string> + <string name="Female - Laugh"> + Risada - feminina + </string> + <string name="Female - Repulsed"> + Quero distância! - feminino + </string> + <string name="Female - Shrug"> + Encolher ombros - feminino + </string> + <string name="Female - Stick tougue out"> + Mostrar a língua - feminino + </string> + <string name="Female - Wow"> + Wow - feminino + </string> <string name="AvatarBirthDateFormat"> [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt] </string> |