Merge branch 'master' of https://vcs.firestormviewer.org/phoenix-firestorm
|
|
@ -4,6 +4,9 @@ include(Variables)
|
|||
include(GLEXT)
|
||||
include(Prebuilt)
|
||||
|
||||
include_guard()
|
||||
|
||||
add_library( sdl INTERFACE IMPORTED )
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindSDL)
|
||||
|
||||
|
|
@ -18,11 +21,17 @@ else (USESYSTEMLIBS)
|
|||
if( NOT USE_SDL2 )
|
||||
use_prebuilt_binary(SDL)
|
||||
set (SDL_FOUND TRUE)
|
||||
set (SDL_LIBRARY SDL directfb fusion direct X11)
|
||||
|
||||
target_link_libraries (sdl INTERFACE SDL directfb fusion direct X11)
|
||||
target_compile_definitions( sdl INTERFACE LL_SDL=1 )
|
||||
|
||||
else()
|
||||
use_prebuilt_binary(SDL2)
|
||||
set (SDL2_FOUND TRUE)
|
||||
set (SDL_LIBRARY SDL2 SDL2_mixer X11)
|
||||
|
||||
target_link_libraries( sdl INTERFACE SDL2 X11 )
|
||||
target_compile_definitions( sdl INTERFACE LL_SDL2=1 LL_SDL=1 )
|
||||
|
||||
endif()
|
||||
|
||||
endif (LINUX)
|
||||
|
|
|
|||
|
|
@ -76,11 +76,6 @@ if (OPENAL)
|
|||
)
|
||||
endif (OPENAL)
|
||||
|
||||
if(SDL2_FOUND)
|
||||
list(APPEND llaudio_SOURCE_FILES llaudioengine_sdl2.cpp )
|
||||
list(APPEND llaudio_HEADER_FILES llaudioengine_sdl2.h )
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${llaudio_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,489 +0,0 @@
|
|||
#include "llaudioengine_sdl2.h"
|
||||
#include "llstreamingaudio.h"
|
||||
#include "lllistener.h"
|
||||
|
||||
#include "SDL2/SDL_mixer.h"
|
||||
|
||||
#include "curl/curl.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string getMixerError()
|
||||
{
|
||||
auto pError = Mix_GetError();
|
||||
if(!pError)
|
||||
return "Mix_Error: returned nullptr";
|
||||
|
||||
return std::string{ "Mix_error: " } + pError;
|
||||
}
|
||||
}
|
||||
|
||||
struct RWData
|
||||
{
|
||||
std::string mURL;
|
||||
CURLM *mMulti{ nullptr };
|
||||
CURL *mEasy{ nullptr };
|
||||
};
|
||||
|
||||
Sint64 SDLCALL stream_size (struct SDL_RWops * context)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Sint64(SDLCALL stream_seek) (struct SDL_RWops * context, Sint64 offset,
|
||||
int whence)
|
||||
{
|
||||
if( !context )
|
||||
return -1;
|
||||
|
||||
RWData *pData = reinterpret_cast<RWData*>(context->hidden.unknown.data1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t SDLCALL stream_read (struct SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
||||
{
|
||||
if( !context )
|
||||
return 0;
|
||||
|
||||
RWData *pData = reinterpret_cast<RWData*>(context->hidden.unknown.data1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SDLCALL stream_write (struct SDL_RWops * context, const void *ptr,
|
||||
size_t size, size_t num)
|
||||
{
|
||||
if( !context )
|
||||
return 0;
|
||||
|
||||
RWData *pData = reinterpret_cast<RWData*>(context->hidden.unknown.data1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDLCALL stream_close (struct SDL_RWops * context)
|
||||
{
|
||||
if( !context )
|
||||
return 0;
|
||||
|
||||
RWData *pData = reinterpret_cast<RWData*>(context->hidden.unknown.data1);
|
||||
// Free curl multi and easy
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
class LLListenerSDL2: public LLListener
|
||||
{
|
||||
LLAudioEngineSDL2 *mEngine;
|
||||
public:
|
||||
LLListenerSDL2(LLAudioEngineSDL2 *aEngine )
|
||||
: mEngine( aEngine )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class LLStreamingAudioSDL2: public LLStreamingAudioInterface
|
||||
{
|
||||
std::string mURL;
|
||||
F32 mVolume { 1.0 };
|
||||
Mix_Music *mMusic{nullptr};
|
||||
SDL_RWops *mReader{ nullptr };
|
||||
RWData *mData;
|
||||
public:
|
||||
|
||||
void start(const std::string& url) override
|
||||
{
|
||||
mURL = url;
|
||||
//mMusic = Mix_LoadMUS( url.c_str() );
|
||||
mReader = SDL_AllocRW();
|
||||
mData = new RWData{};
|
||||
mReader->hidden.unknown.data1 = mData;
|
||||
|
||||
mReader->size = stream_size;
|
||||
mReader->seek = stream_seek;
|
||||
mReader->read = stream_read;
|
||||
mReader->write = stream_write;
|
||||
mReader->close = stream_close;
|
||||
|
||||
mMusic = Mix_LoadMUS_RW( mReader, 0 );
|
||||
if( mMusic )
|
||||
{
|
||||
auto x = Mix_PlayMusic( mMusic, 0 );
|
||||
LL_WARNS() << "SDL2: " << getMixerError() << " " << x << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "SDL2: MixLoadMUS failed: " << getMixerError() << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void stop() override
|
||||
{
|
||||
}
|
||||
|
||||
void pause(int pause) override
|
||||
{
|
||||
}
|
||||
|
||||
void update() override
|
||||
{
|
||||
}
|
||||
|
||||
int isPlaying() override
|
||||
{
|
||||
return mMusic != nullptr;
|
||||
}
|
||||
|
||||
void setGain(F32 vol) override
|
||||
{
|
||||
mVolume = vol;
|
||||
}
|
||||
|
||||
F32 getGain() override
|
||||
{
|
||||
return mVolume;
|
||||
}
|
||||
|
||||
std::string getURL() override
|
||||
{
|
||||
return mURL;
|
||||
}
|
||||
|
||||
bool supportsAdjustableBufferSizes() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBufferSizes(U32 streambuffertime, U32 decodebuffertime) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class LLAudioBufferSDL2: public LLAudioBuffer
|
||||
{
|
||||
public:
|
||||
Mix_Chunk *mChunk;
|
||||
|
||||
~LLAudioBufferSDL2()
|
||||
{
|
||||
if( mChunk )
|
||||
Mix_FreeChunk(mChunk);
|
||||
}
|
||||
|
||||
bool loadWAV(const std::string& filename)
|
||||
{
|
||||
mChunk = Mix_LoadWAV( filename.c_str() );
|
||||
return mChunk != nullptr;
|
||||
}
|
||||
|
||||
U32 getLength()
|
||||
{
|
||||
return 0; // Not needed here
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class LLAudioChannelSDL2: public LLAudioChannel
|
||||
{
|
||||
S32 mChannel;
|
||||
LLAudioEngineSDL2 *mEngine;
|
||||
bool mPlayback{false};
|
||||
|
||||
uint32_t caclulateVolume()
|
||||
{
|
||||
if( mChannel < 0 || !mCurrentSourcep || !mEngine)
|
||||
return 0.0f;
|
||||
|
||||
|
||||
F32 gain = mCurrentSourcep->getGain() * getSecondaryGain() * mEngine->getMasterGain();
|
||||
llclamp(gain, 0.0f, 1.f );
|
||||
gain *= 255.f;
|
||||
return static_cast<uint32_t>(gain);
|
||||
|
||||
}
|
||||
public:
|
||||
LLAudioChannelSDL2( S32 nChannel, LLAudioEngineSDL2 *aEngine )
|
||||
: mChannel( nChannel )
|
||||
, mEngine( aEngine )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~LLAudioChannelSDL2()
|
||||
{
|
||||
mEngine->deleteChannel( mChannel );
|
||||
}
|
||||
|
||||
void play() override
|
||||
{
|
||||
startPlayback();
|
||||
}
|
||||
|
||||
void startPlayback()
|
||||
{
|
||||
if( mChannel < 0 )
|
||||
return;
|
||||
|
||||
//if( mPlayback )
|
||||
// return;
|
||||
|
||||
Mix_HaltChannel( mChannel );
|
||||
LLAudioBufferSDL2* pBuffer = (LLAudioBufferSDL2*)mCurrentBufferp;
|
||||
if( !pBuffer )
|
||||
return;
|
||||
|
||||
mPlayback = true;
|
||||
Mix_PlayChannel( mChannel, pBuffer->mChunk, mCurrentSourcep->isLoop()?-1:0 );
|
||||
Mix_Volume( mChannel, caclulateVolume());
|
||||
}
|
||||
|
||||
void playSynced(LLAudioChannel *channelp) override
|
||||
{
|
||||
play();
|
||||
}
|
||||
|
||||
void cleanup() override
|
||||
{
|
||||
if( mChannel < 0 )
|
||||
return;
|
||||
|
||||
mPlayback = false;
|
||||
Mix_HaltChannel( mChannel );
|
||||
}
|
||||
|
||||
bool isPlaying() override
|
||||
{
|
||||
if( mChannel < 0 )
|
||||
return false;
|
||||
|
||||
if( !mPlayback )
|
||||
return false;
|
||||
|
||||
bool bRet = Mix_Playing( mChannel ) == 1;
|
||||
if( !bRet )
|
||||
{
|
||||
mPlayback = false;
|
||||
Mix_HaltChannel( mChannel );
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool updateBuffer() override
|
||||
{
|
||||
if( !mCurrentSourcep || mChannel < 0)
|
||||
return false;
|
||||
|
||||
if( LLAudioChannel::updateBuffer() )
|
||||
{
|
||||
if(mCurrentSourcep)
|
||||
{
|
||||
startPlayback();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( mCurrentSourcep )
|
||||
{
|
||||
if( mPlayback )
|
||||
Mix_Volume( mChannel, caclulateVolume());
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mPlayback )
|
||||
Mix_HaltChannel(mChannel);
|
||||
mPlayback = false;
|
||||
}
|
||||
return mCurrentSourcep != 0;
|
||||
}
|
||||
|
||||
void update3DPosition() override
|
||||
{
|
||||
if(!mCurrentSourcep || mChannel < 0)
|
||||
return;
|
||||
|
||||
if(mPlayback)
|
||||
{
|
||||
auto pos = mEngine->getListenerPos();
|
||||
LLVector3 soundpos{mCurrentSourcep->getPositionGlobal()};
|
||||
F32 dist = dist_vec(soundpos, pos);
|
||||
dist = llclamp(dist, 0.0f, 255.0f);
|
||||
Mix_SetPosition(mChannel, 0, (uint8_t) dist);
|
||||
}
|
||||
}
|
||||
|
||||
void updateLoop() override
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct LLAudioEngineSDL2::ImplData
|
||||
{
|
||||
std::vector< uint8_t > mChannels;
|
||||
bool mReady { false };
|
||||
};
|
||||
|
||||
LLAudioEngineSDL2::LLAudioEngineSDL2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLAudioEngineSDL2::~LLAudioEngineSDL2()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool LLAudioEngineSDL2::init(const S32 num_channels, void *userdata, const std::string &app_title)
|
||||
{
|
||||
LL_INFOS() << "Initializing SDL2 audio" << LL_ENDL;
|
||||
mData = std::make_unique<ImplData>();
|
||||
|
||||
LLAudioEngine::init(num_channels, userdata, app_title);
|
||||
|
||||
int flags = MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_MP3;
|
||||
if( flags != Mix_Init( flags ) )
|
||||
LL_WARNS() << "Mix_Init failed to intialize all formats: " << getMixerError () << LL_ENDL;
|
||||
|
||||
if( 0 != Mix_OpenAudio(44100, AUDIO_S16LSB, MIX_DEFAULT_CHANNELS, 1024 ) )
|
||||
{
|
||||
LL_WARNS() << "Mix_OpenAudio failed " << getMixerError() << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
mData->mChannels.resize( num_channels+2 );
|
||||
Mix_AllocateChannels( num_channels );
|
||||
mData->mReady = true;
|
||||
|
||||
// Impl is stubbed out, but nothing more
|
||||
// if (!getStreamingAudioImpl())
|
||||
// setStreamingAudioImpl( new LLStreamingAudioSDL2() );
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
std::string LLAudioEngineSDL2::getDriverName(bool verbose)
|
||||
{
|
||||
return "SDL mixer";
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::shutdown()
|
||||
{
|
||||
Mix_CloseAudio();
|
||||
Mix_Quit();
|
||||
|
||||
mData = nullptr;
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::updateWind(LLVector3 direction, F32 camera_height_above_water)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::idle(F32 max_decode_time )
|
||||
{
|
||||
LLAudioEngine::idle(max_decode_time);
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::updateChannels()
|
||||
{
|
||||
LLAudioEngine::updateChannels();
|
||||
}
|
||||
|
||||
LLAudioEngineSDL2::output_device_map_t LLAudioEngineSDL2::getDevices()
|
||||
{
|
||||
// Impl looks like this, but it might not be possible to support this right now
|
||||
/*
|
||||
if(mDevices.size())
|
||||
return;
|
||||
|
||||
auto numDevices{SDL_GetNumAudioDevices(0)};
|
||||
if( numDevices <= 0 )
|
||||
return {};
|
||||
|
||||
LLAudioEngineSDL2::output_device_map_t devices{};
|
||||
for( auto i{0}; i < numDevices; ++i )
|
||||
{
|
||||
auto pName{SDL_GetAudioDeviceName(i, 0)};
|
||||
if( !pName )
|
||||
continue;
|
||||
|
||||
std::string strName{ pName };
|
||||
|
||||
devices[ LLUUID::generateNewID( strName )] = strName;
|
||||
}
|
||||
*/
|
||||
|
||||
return mDevices;
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::setDevice(const LLUUID &device_uuid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLAudioBuffer *LLAudioEngineSDL2::createBuffer()
|
||||
{
|
||||
return new LLAudioBufferSDL2();
|
||||
}
|
||||
|
||||
LLAudioChannel *LLAudioEngineSDL2::createChannel()
|
||||
{
|
||||
S32 channelNum{ -1 };
|
||||
if( mData && mData->mReady )
|
||||
{
|
||||
for( S32 i = 0; i < mData->mChannels.size(); ++i )
|
||||
{
|
||||
if( !mData->mChannels[i])
|
||||
{
|
||||
channelNum = i;
|
||||
mData->mChannels[i] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( channelNum == -1 )
|
||||
{
|
||||
channelNum = mData->mChannels.size();
|
||||
mData->mChannels.push_back(0);
|
||||
Mix_AllocateChannels( mData->mChannels.size() );
|
||||
}
|
||||
}
|
||||
|
||||
return new LLAudioChannelSDL2(channelNum, this);
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::deleteChannel(S32 aChannel)
|
||||
{
|
||||
if( !mData )
|
||||
return;
|
||||
|
||||
if( aChannel < 0 || aChannel >= mData->mChannels.size() )
|
||||
return;
|
||||
|
||||
mData->mChannels[aChannel] = 0;
|
||||
}
|
||||
|
||||
bool LLAudioEngineSDL2::initWind()
|
||||
{
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::cleanupWind()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::setInternalGain(F32 gain)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LLAudioEngineSDL2::allocateListener()
|
||||
{
|
||||
mListenerp = new LLListenerSDL2(this);
|
||||
}
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef LL_AUDIOENGINE_SDL2_H
|
||||
#define LL_AUDIOENGINE_SDL2_H
|
||||
|
||||
#include "llaudioengine.h"
|
||||
#include "llwindgen.h"
|
||||
|
||||
class LLAudioEngineSDL2 : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngineSDL2();
|
||||
~LLAudioEngineSDL2();
|
||||
|
||||
bool init(const S32 num_channels, void *userdata, const std::string &app_title) override;
|
||||
std::string getDriverName(bool verbose) override;
|
||||
void shutdown() override;
|
||||
|
||||
void updateWind(LLVector3 direction, F32 camera_height_above_water) override;
|
||||
void idle(F32 max_decode_time = 0.f) override;
|
||||
void updateChannels() override;
|
||||
|
||||
output_device_map_t getDevices() override;
|
||||
void setDevice(const LLUUID& device_uuid) override;
|
||||
|
||||
|
||||
void deleteChannel( S32 aChannel );
|
||||
|
||||
protected:
|
||||
LLAudioBuffer *createBuffer() override;
|
||||
LLAudioChannel *createChannel() override;
|
||||
|
||||
bool initWind() override;
|
||||
void cleanupWind() override;
|
||||
void setInternalGain(F32 gain) override;
|
||||
|
||||
void allocateListener() override;
|
||||
|
||||
output_device_map_t mDevices;
|
||||
|
||||
struct ImplData;
|
||||
std::unique_ptr< ImplData > mData;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -4,12 +4,14 @@ project(llmath)
|
|||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLMeshOptimizer)
|
||||
include(bugsplat)
|
||||
include(Boost)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
${LLMESHOPTIMIZER_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llmath_SOURCE_FILES
|
||||
|
|
@ -114,6 +116,7 @@ add_library (llmath ${llmath_SOURCE_FILES})
|
|||
|
||||
target_link_libraries(llmath
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${LLMESHOPTIMIZER_LIBRARIES}
|
||||
)
|
||||
|
||||
# Add tests
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "llvector4a.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "llmeshoptimizer.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
#define DEBUG_SILHOUETTE_BINORMALS 0
|
||||
|
|
@ -5021,6 +5022,50 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a
|
|||
return a.mV[2] < b.mV[2];
|
||||
}
|
||||
|
||||
void LLVolumeFace::remap()
|
||||
{
|
||||
// Generate a remap buffer
|
||||
std::vector<unsigned int> remap(mNumVertices);
|
||||
S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0],
|
||||
mIndices,
|
||||
mNumIndices,
|
||||
mPositions,
|
||||
mNormals,
|
||||
mTexCoords,
|
||||
mNumVertices);
|
||||
|
||||
// Allocate new buffers
|
||||
S32 size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF;
|
||||
U16* remap_indices = (U16*)ll_aligned_malloc_16(size);
|
||||
|
||||
S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF;
|
||||
LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size);
|
||||
LLVector4a* remap_normals = remap_positions + remap_vertices_count;
|
||||
LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count);
|
||||
|
||||
// Fill the buffers
|
||||
LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]);
|
||||
LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]);
|
||||
LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]);
|
||||
LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]);
|
||||
|
||||
// Free unused buffers
|
||||
ll_aligned_free_16(mIndices);
|
||||
ll_aligned_free<64>(mPositions);
|
||||
|
||||
// Tangets are now invalid
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = NULL;
|
||||
|
||||
// Assign new values
|
||||
mIndices = remap_indices;
|
||||
mPositions = remap_positions;
|
||||
mNormals = remap_normals;
|
||||
mTexCoords = remap_tex_coords;
|
||||
mNumVertices = remap_vertices_count;
|
||||
mNumAllocatedVertices = remap_vertices_count;
|
||||
}
|
||||
|
||||
void LLVolumeFace::optimize(F32 angle_cutoff)
|
||||
{
|
||||
LLVolumeFace new_face;
|
||||
|
|
|
|||
|
|
@ -905,6 +905,10 @@ public:
|
|||
typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
|
||||
};
|
||||
|
||||
// Eliminates non unique triangles, takes positions,
|
||||
// normals and texture coordinates into account.
|
||||
void remap();
|
||||
|
||||
void optimize(F32 angle_cutoff = 2.f);
|
||||
bool cacheOptimize();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include "meshoptimizer.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include "v2math.h"
|
||||
|
||||
LLMeshOptimizer::LLMeshOptimizer()
|
||||
{
|
||||
// Todo: Looks like for memory management, we can add allocator and deallocator callbacks
|
||||
|
|
@ -40,24 +43,218 @@ LLMeshOptimizer::~LLMeshOptimizer()
|
|||
}
|
||||
|
||||
//static
|
||||
void LLMeshOptimizer::generateShadowIndexBuffer(U16 *destination,
|
||||
const U16 *indices,
|
||||
void LLMeshOptimizer::generateShadowIndexBufferU32(U32 *destination,
|
||||
const U32 *indices,
|
||||
U64 index_count,
|
||||
const LLVector4a *vertex_positions,
|
||||
U64 vertex_count,
|
||||
U64 vertex_positions_stride
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count
|
||||
)
|
||||
{
|
||||
meshopt_generateShadowIndexBuffer<unsigned short>(destination,
|
||||
meshopt_Stream streams[3];
|
||||
|
||||
S32 index = 0;
|
||||
if (vertex_positions)
|
||||
{
|
||||
streams[index].data = (const float*)vertex_positions;
|
||||
// Despite being LLVector4a, only x, y and z are in use
|
||||
streams[index].size = sizeof(F32) * 3;
|
||||
streams[index].stride = sizeof(F32) * 4;
|
||||
index++;
|
||||
}
|
||||
if (normals)
|
||||
{
|
||||
streams[index].data = (const float*)normals;
|
||||
streams[index].size = sizeof(F32) * 3;
|
||||
streams[index].stride = sizeof(F32) * 4;
|
||||
index++;
|
||||
}
|
||||
if (text_coords)
|
||||
{
|
||||
streams[index].data = (const float*)text_coords;
|
||||
streams[index].size = sizeof(F32) * 2;
|
||||
streams[index].stride = sizeof(F32) * 2;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
// invalid
|
||||
return;
|
||||
}
|
||||
|
||||
meshopt_generateShadowIndexBufferMulti<unsigned int>(destination,
|
||||
indices,
|
||||
index_count,
|
||||
(const float*)vertex_positions, // verify that it is correct to convert to float
|
||||
vertex_count,
|
||||
sizeof(LLVector4a),
|
||||
vertex_positions_stride
|
||||
streams,
|
||||
index
|
||||
);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMeshOptimizer::generateShadowIndexBufferU16(U16 *destination,
|
||||
const U16 *indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count
|
||||
)
|
||||
{
|
||||
meshopt_Stream streams[3];
|
||||
|
||||
S32 index = 0;
|
||||
if (vertex_positions)
|
||||
{
|
||||
streams[index].data = (const float*)vertex_positions;
|
||||
streams[index].size = sizeof(F32) * 3;
|
||||
streams[index].stride = sizeof(F32) * 4;
|
||||
index++;
|
||||
}
|
||||
if (normals)
|
||||
{
|
||||
streams[index].data = (const float*)normals;
|
||||
streams[index].size = sizeof(F32) * 3;
|
||||
streams[index].stride = sizeof(F32) * 4;
|
||||
index++;
|
||||
}
|
||||
if (text_coords)
|
||||
{
|
||||
streams[index].data = (const float*)text_coords;
|
||||
streams[index].size = sizeof(F32) * 2;
|
||||
streams[index].stride = sizeof(F32) * 2;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
// invalid
|
||||
return;
|
||||
}
|
||||
|
||||
meshopt_generateShadowIndexBufferMulti<unsigned short>(destination,
|
||||
indices,
|
||||
index_count,
|
||||
vertex_count,
|
||||
streams,
|
||||
index);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::optimizeVertexCacheU32(U32 * destination, const U32 * indices, U64 index_count, U64 vertex_count)
|
||||
{
|
||||
meshopt_optimizeVertexCache<unsigned int>(destination, indices, index_count, vertex_count);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::optimizeVertexCacheU16(U16 * destination, const U16 * indices, U64 index_count, U64 vertex_count)
|
||||
{
|
||||
meshopt_optimizeVertexCache<unsigned short>(destination, indices, index_count, vertex_count);
|
||||
}
|
||||
|
||||
size_t LLMeshOptimizer::generateRemapMultiU32(
|
||||
unsigned int* remap,
|
||||
const U32 * indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count)
|
||||
{
|
||||
meshopt_Stream streams[] = {
|
||||
{(const float*)vertex_positions, sizeof(F32) * 3, sizeof(F32) * 4},
|
||||
{(const float*)normals, sizeof(F32) * 3, sizeof(F32) * 4},
|
||||
{(const float*)text_coords, sizeof(F32) * 2, sizeof(F32) * 2},
|
||||
};
|
||||
|
||||
// Remap can function without indices,
|
||||
// but providing indices helps with removing unused vertices
|
||||
U64 indeces_cmp = indices ? index_count : vertex_count;
|
||||
|
||||
// meshopt_generateVertexRemapMulti will throw an assert if (indices[i] >= vertex_count)
|
||||
return meshopt_generateVertexRemapMulti(&remap[0], indices, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0]));
|
||||
}
|
||||
|
||||
size_t LLMeshOptimizer::generateRemapMultiU16(
|
||||
unsigned int* remap,
|
||||
const U16 * indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count)
|
||||
{
|
||||
S32 out_of_range_count = 0;
|
||||
U32* indices_u32 = NULL;
|
||||
if (indices)
|
||||
{
|
||||
indices_u32 = (U32*)ll_aligned_malloc_32(index_count * sizeof(U32));
|
||||
for (U64 i = 0; i < index_count; i++)
|
||||
{
|
||||
if (indices[i] < vertex_count)
|
||||
{
|
||||
indices_u32[i] = (U32)indices[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
out_of_range_count++;
|
||||
indices_u32[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out_of_range_count)
|
||||
{
|
||||
LL_WARNS() << out_of_range_count << " indices are out of range." << LL_ENDL;
|
||||
}
|
||||
|
||||
size_t unique = generateRemapMultiU32(remap, indices_u32, index_count, vertex_positions, normals, text_coords, vertex_count);
|
||||
|
||||
ll_aligned_free_32(indices_u32);
|
||||
|
||||
return unique;
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::remapIndexBufferU32(U32 * destination_indices,
|
||||
const U32 * indices,
|
||||
U64 index_count,
|
||||
const unsigned int* remap)
|
||||
{
|
||||
meshopt_remapIndexBuffer<unsigned int>(destination_indices, indices, index_count, remap);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::remapIndexBufferU16(U16 * destination_indices,
|
||||
const U16 * indices,
|
||||
U64 index_count,
|
||||
const unsigned int* remap)
|
||||
{
|
||||
meshopt_remapIndexBuffer<unsigned short>(destination_indices, indices, index_count, remap);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::remapPositionsBuffer(LLVector4a * destination_vertices,
|
||||
const LLVector4a * vertex_positions,
|
||||
U64 vertex_count,
|
||||
const unsigned int* remap)
|
||||
{
|
||||
meshopt_remapVertexBuffer((float*)destination_vertices, (const float*)vertex_positions, vertex_count, sizeof(LLVector4a), remap);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::remapNormalsBuffer(LLVector4a * destination_normalss,
|
||||
const LLVector4a * normals,
|
||||
U64 mormals_count,
|
||||
const unsigned int* remap)
|
||||
{
|
||||
meshopt_remapVertexBuffer((float*)destination_normalss, (const float*)normals, mormals_count, sizeof(LLVector4a), remap);
|
||||
}
|
||||
|
||||
void LLMeshOptimizer::remapUVBuffer(LLVector2 * destination_uvs,
|
||||
const LLVector2 * uv_positions,
|
||||
U64 uv_count,
|
||||
const unsigned int* remap)
|
||||
{
|
||||
meshopt_remapVertexBuffer((float*)destination_uvs, (const float*)uv_positions, uv_count, sizeof(LLVector2), remap);
|
||||
}
|
||||
|
||||
//static
|
||||
U64 LLMeshOptimizer::simplifyU32(U32 *destination,
|
||||
const U32 *indices,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmath.h"
|
||||
class LLVector4a;
|
||||
class LLVector2;
|
||||
|
||||
class LLMeshOptimizer
|
||||
{
|
||||
|
|
@ -36,13 +37,85 @@ public:
|
|||
LLMeshOptimizer();
|
||||
~LLMeshOptimizer();
|
||||
|
||||
static void generateShadowIndexBuffer(
|
||||
static void generateShadowIndexBufferU32(
|
||||
U32 *destination,
|
||||
const U32 *indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count);
|
||||
|
||||
static void generateShadowIndexBufferU16(
|
||||
U16 *destination,
|
||||
const U16 *indices,
|
||||
U64 index_count,
|
||||
const LLVector4a *vertex_positions,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count);
|
||||
|
||||
static void optimizeVertexCacheU32(
|
||||
U32 *destination,
|
||||
const U32 *indices,
|
||||
U64 index_count,
|
||||
U64 vertex_count);
|
||||
|
||||
static void optimizeVertexCacheU16(
|
||||
U16 *destination,
|
||||
const U16 *indices,
|
||||
U64 index_count,
|
||||
U64 vertex_count);
|
||||
|
||||
// Remap functions
|
||||
// Welds indentical vertexes together.
|
||||
// Removes unused vertices if indices were provided.
|
||||
|
||||
static size_t generateRemapMultiU32(
|
||||
unsigned int* remap,
|
||||
const U32 * indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count);
|
||||
|
||||
static size_t generateRemapMultiU16(
|
||||
unsigned int* remap,
|
||||
const U16 * indices,
|
||||
U64 index_count,
|
||||
const LLVector4a * vertex_positions,
|
||||
const LLVector4a * normals,
|
||||
const LLVector2 * text_coords,
|
||||
U64 vertex_count);
|
||||
|
||||
static void remapIndexBufferU32(U32 * destination_indices,
|
||||
const U32 * indices,
|
||||
U64 index_count,
|
||||
const unsigned int* remap);
|
||||
|
||||
static void remapIndexBufferU16(U16 * destination_indices,
|
||||
const U16 * indices,
|
||||
U64 index_count,
|
||||
const unsigned int* remap);
|
||||
|
||||
|
||||
static void remapPositionsBuffer(LLVector4a * destination_vertices,
|
||||
const LLVector4a * vertex_positions,
|
||||
U64 vertex_count,
|
||||
U64 vertex_positions_stride);
|
||||
const unsigned int* remap);
|
||||
|
||||
static void remapNormalsBuffer(LLVector4a * destination_normalss,
|
||||
const LLVector4a * normals,
|
||||
U64 mormals_count,
|
||||
const unsigned int* remap);
|
||||
|
||||
static void remapUVBuffer(LLVector2 * destination_uvs,
|
||||
const LLVector2 * uv_positions,
|
||||
U64 uv_count,
|
||||
const unsigned int* remap);
|
||||
|
||||
// Simplification
|
||||
|
||||
// returns amount of indices in destiantion
|
||||
// sloppy engages a variant of a mechanizm that does not respect topology as much
|
||||
|
|
|
|||
|
|
@ -2721,7 +2721,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
|
|||
|
||||
if (!mNoOptimize)
|
||||
{
|
||||
ret->optimizeVolumeFaces();
|
||||
ret->remapVolumeFaces();
|
||||
}
|
||||
|
||||
volume_faces = remainder.size();
|
||||
|
|
|
|||
|
|
@ -110,6 +110,14 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
|||
}
|
||||
}
|
||||
|
||||
void LLModel::remapVolumeFaces()
|
||||
{
|
||||
for (U32 i = 0; i < getNumVolumeFaces(); ++i)
|
||||
{
|
||||
mVolumeFaces[i].remap();
|
||||
}
|
||||
}
|
||||
|
||||
void LLModel::optimizeVolumeFaces()
|
||||
{
|
||||
for (U32 i = 0; i < getNumVolumeFaces(); ++i)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ public:
|
|||
void sortVolumeFacesByMaterialName();
|
||||
void normalizeVolumeFaces();
|
||||
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
|
||||
void remapVolumeFaces();
|
||||
void optimizeVolumeFaces();
|
||||
void offsetMesh( const LLVector3& pivotPoint );
|
||||
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
|
||||
|
|
|
|||
|
|
@ -111,17 +111,6 @@ endif (BUILD_HEADLESS)
|
|||
|
||||
add_library (llrender ${llrender_SOURCE_FILES})
|
||||
|
||||
if (SDL_FOUND)
|
||||
set_property(TARGET llrender
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL=1
|
||||
)
|
||||
endif (SDL_FOUND)
|
||||
if (SDL2_FOUND)
|
||||
set_property(TARGET llrender
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL2=1 LL_SDL=1
|
||||
)
|
||||
endif ()
|
||||
|
||||
# Libraries on which this library depends, needed for Linux builds
|
||||
# Sort by high-level to low-level
|
||||
target_link_libraries(llrender
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ LLButton::Params::Params()
|
|||
scale_image("scale_image", true),
|
||||
hover_glow_amount("hover_glow_amount"),
|
||||
commit_on_return("commit_on_return", true),
|
||||
commit_on_capture_lost("commit_on_capture_lost", false),
|
||||
display_pressed_state("display_pressed_state", true),
|
||||
use_draw_context_alpha("use_draw_context_alpha", true),
|
||||
badge("badge"),
|
||||
|
|
@ -172,6 +173,7 @@ LLButton::LLButton(const LLButton::Params& p)
|
|||
mBottomVPad(p.pad_bottom),
|
||||
mHoverGlowStrength(p.hover_glow_amount),
|
||||
mCommitOnReturn(p.commit_on_return),
|
||||
mCommitOnCaptureLost(p.commit_on_capture_lost),
|
||||
mFadeWhenDisabled(FALSE),
|
||||
mForcePressedState(false),
|
||||
mDisplayPressedState(p.display_pressed_state),
|
||||
|
|
@ -532,6 +534,10 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
|
|||
// We only handle the click if the click both started and ended within us
|
||||
if( hasMouseCapture() )
|
||||
{
|
||||
// reset timers before focus change, to not cause
|
||||
// additional commits if mCommitOnCaptureLost.
|
||||
resetMouseDownTimer();
|
||||
|
||||
// Always release the mouse
|
||||
gFocusMgr.setMouseCapture( NULL );
|
||||
|
||||
|
|
@ -546,8 +552,6 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
|
|||
// Regardless of where mouseup occurs, handle callback
|
||||
if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
|
||||
|
||||
resetMouseDownTimer();
|
||||
|
||||
// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
|
||||
// If mouseup in the widget, it's been clicked
|
||||
if (pointInView(x, y))
|
||||
|
|
@ -1270,6 +1274,18 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen
|
|||
|
||||
void LLButton::onMouseCaptureLost()
|
||||
{
|
||||
if (mCommitOnCaptureLost
|
||||
&& mMouseDownTimer.getStarted())
|
||||
{
|
||||
if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
|
||||
|
||||
if (mIsToggle)
|
||||
{
|
||||
toggleState();
|
||||
}
|
||||
|
||||
LLUICtrl::onCommit();
|
||||
}
|
||||
resetMouseDownTimer();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ public:
|
|||
Optional<bool> is_toggle,
|
||||
scale_image,
|
||||
commit_on_return,
|
||||
commit_on_capture_lost,
|
||||
display_pressed_state;
|
||||
|
||||
Optional<F32> hover_glow_amount;
|
||||
|
|
@ -391,6 +392,7 @@ protected:
|
|||
F32 mCurGlowStrength;
|
||||
|
||||
bool mCommitOnReturn;
|
||||
bool mCommitOnCaptureLost;
|
||||
bool mFadeWhenDisabled;
|
||||
bool mForcePressedState;
|
||||
bool mDisplayPressedState;
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ void LLDockableFloater::setMinimized(BOOL minimize)
|
|||
{
|
||||
// minimizing a docked floater just hides it
|
||||
setVisible(FALSE);
|
||||
gFocusMgr.releaseFocusIfNeeded(this); // <FS:Ansariel> FIRE-31882: Release focus or main menu bar would receive it in LLViewerWindow::updateKeyboardFocus()
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -106,16 +106,21 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
|
|||
// Spin buttons
|
||||
LLButton::Params up_button_params(p.up_button);
|
||||
up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);
|
||||
up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
|
||||
// Click callback starts within the button and ends within the button,
|
||||
// but LLSpinCtrl handles the action continuosly so subsribers needs to
|
||||
// be informed about click ending even if outside view, use 'up' instead
|
||||
up_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
|
||||
up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
|
||||
up_button_params.commit_on_capture_lost = true;
|
||||
|
||||
mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);
|
||||
addChild(mUpBtn);
|
||||
|
||||
LLButton::Params down_button_params(p.down_button);
|
||||
down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);
|
||||
down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
|
||||
down_button_params.mouse_up_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
|
||||
down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
|
||||
down_button_params.commit_on_capture_lost = true;
|
||||
mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
|
||||
addChild(mDownBtn);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ if (LINUX)
|
|||
#${LLWINDOW_LIBRARIES} # <FS:Ansariel> Don't link to itself - causes CMP0038
|
||||
${LLXML_LIBRARIES}
|
||||
${UI_LIBRARIES} # for GTK
|
||||
${SDL_LIBRARY}
|
||||
sdl
|
||||
libfontconfig.a # For FCInit and other FC* functions.
|
||||
libfreetype.a
|
||||
)
|
||||
|
|
@ -201,16 +201,5 @@ endif (llwindow_HEADER_FILES)
|
|||
${viewer_SOURCE_FILES}
|
||||
)
|
||||
|
||||
if (SDL_FOUND)
|
||||
set_property(TARGET llwindow
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL=1
|
||||
)
|
||||
endif ()
|
||||
if (SDL2_FOUND)
|
||||
set_property(TARGET llwindow
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL2=1 LL_SDL=1
|
||||
)
|
||||
endif ()
|
||||
|
||||
target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
|
||||
|
||||
|
|
|
|||
|
|
@ -565,22 +565,26 @@ U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol )
|
|||
mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
|
||||
mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
|
||||
|
||||
mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL?
|
||||
mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE;
|
||||
mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY;
|
||||
mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT?
|
||||
mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD?
|
||||
mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN;
|
||||
mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0;
|
||||
mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1;
|
||||
mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2;
|
||||
mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3;
|
||||
mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4;
|
||||
mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5;
|
||||
mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6;
|
||||
mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7;
|
||||
mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8;
|
||||
mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9;
|
||||
|
||||
// map numpad keys as best we can, mapping to VK_NUMPADx will break things
|
||||
// for SDL2, so we use the actual functions
|
||||
mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_INSERT; // VK_NUMPAD0
|
||||
mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_END; // VK_NUMPAD1
|
||||
mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_DOWN; // VK_NUMPAD2
|
||||
mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NEXT; // VK_NUMPAD3
|
||||
mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_LEFT; // VK_NUMPAD4
|
||||
mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5; // has no function
|
||||
mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_RIGHT; // VK_NUMPAD6
|
||||
mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_HOME; // VK_NUMPAD7
|
||||
mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_UP; // VK_NUMPAD8
|
||||
mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_PRIOR; // VK_NUMPAD9
|
||||
|
||||
mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_DELETE; // VK_OEM_PERIOD;
|
||||
|
||||
// ?
|
||||
|
||||
|
|
|
|||
|
|
@ -1783,7 +1783,13 @@ void LLWindowSDL::gatherInput()
|
|||
for( auto key: string )
|
||||
{
|
||||
mKeyVirtualKey = key;
|
||||
handleUnicodeUTF16( key, mKeyModifiers );
|
||||
|
||||
// filter ctrl and left-alt keypresses from line inputs so we don't end up with e.g.
|
||||
// "h" in teleport history filter input after pressing alt+h to call up the floater
|
||||
if (mKeyModifiers & (MASK_CONTROL | MASK_ALT))
|
||||
gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers);
|
||||
else
|
||||
handleUnicodeUTF16(key, mKeyModifiers);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ if (LINUX)
|
|||
|
||||
list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER})
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'")
|
||||
list(APPEND media_plugin_cef_LINK_LIBRARIES llwindow )
|
||||
elseif (DARWIN)
|
||||
list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher_null.cpp)
|
||||
find_library(CORESERVICES_LIBRARY CoreServices)
|
||||
|
|
@ -87,6 +88,7 @@ add_library(media_plugin_cef
|
|||
# ${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
#)
|
||||
|
||||
|
||||
target_link_libraries(media_plugin_cef
|
||||
${media_plugin_cef_LINK_LIBRARIES}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1051,13 +1051,37 @@ void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_dat
|
|||
|
||||
// <FS:ND> Keyboard handling for Linux.
|
||||
#if LL_LINUX
|
||||
#if LL_SDL2
|
||||
|
||||
uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); // this is actually the SDL event.key.keysym.sym;
|
||||
uint32_t native_virtual_key_win = (uint32_t)(native_key_data["virtual_key_win"].asInteger());
|
||||
uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
|
||||
|
||||
// only for non-printable keysyms, the actual text input is done in unicodeInput() below
|
||||
if (native_virtual_key <= 0x1b || native_virtual_key >= 0x7f)
|
||||
{
|
||||
// set keypad flag, not sure if this even does anything
|
||||
bool keypad = false;
|
||||
if (native_virtual_key_win >= 0x60 && native_virtual_key_win <= 0x6f)
|
||||
{
|
||||
keypad = true;
|
||||
}
|
||||
|
||||
// yes, we send native_virtual_key_win twice because native_virtual_key breaks it
|
||||
mCEFLib->nativeKeyboardEventSDL2(key_event, native_virtual_key_win, native_virtual_key_win, native_modifiers, keypad);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger());
|
||||
uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
|
||||
uint32_t native_modifiers = (uint32_t)(native_key_data["cef_modifiers"].asInteger());
|
||||
if( native_scan_code == '\n' )
|
||||
native_scan_code = '\r';
|
||||
mCEFLib->nativeKeyboardEvent(key_event, native_scan_code, native_virtual_key, native_modifiers);
|
||||
#endif
|
||||
|
||||
#endif // LL_SDL2
|
||||
#endif // LL_LINUX
|
||||
// </FS:ND>
|
||||
};
|
||||
|
||||
|
|
@ -1089,6 +1113,18 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD
|
|||
U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
|
||||
mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam);
|
||||
#endif
|
||||
|
||||
#if LL_LINUX
|
||||
# if LL_SDL2
|
||||
|
||||
uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger());
|
||||
uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
|
||||
uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
|
||||
|
||||
mCEFLib->nativeKeyboardEvent(dullahan::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers);
|
||||
|
||||
#endif // LL_SDL2
|
||||
#endif // LL_LINUX
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -2201,17 +2201,6 @@ add_executable(${VIEWER_BINARY_NAME}
|
|||
${viewer_SOURCE_FILES}
|
||||
)
|
||||
|
||||
if (SDL_FOUND)
|
||||
set_property(TARGET ${VIEWER_BINARY_NAME}
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL=1
|
||||
)
|
||||
endif (SDL_FOUND)
|
||||
if (SDL2_FOUND)
|
||||
set_property(TARGET ${VIEWER_BINARY_NAME}
|
||||
PROPERTY COMPILE_DEFINITIONS LL_SDL2=1 LL_SDL=1
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (USE_BUGSPLAT)
|
||||
set_property(TARGET ${VIEWER_BINARY_NAME}
|
||||
PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
|
||||
|
|
@ -2525,7 +2514,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${GLOD_LIBRARIES} # <FS:Beq/> restore GLOD dependencies
|
||||
${OPENGL_LIBRARIES}
|
||||
${JSONCPP_LIBRARIES}
|
||||
${SDL_LIBRARY}
|
||||
#${SDL_LIBRARY}
|
||||
${SMARTHEAP_LIBRARY}
|
||||
${UI_LIBRARIES}
|
||||
${WINDOWS_LIBRARIES}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.6.2
|
||||
6.6.3
|
||||
|
|
|
|||
|
|
@ -3223,19 +3223,14 @@ bool LLAppViewer::initConfiguration()
|
|||
|
||||
if (clp.hasOption("graphicslevel"))
|
||||
{
|
||||
// User explicitly requested --graphicslevel on the command line. We
|
||||
// expect this switch has already set RenderQualityPerformance. Check
|
||||
// that value for validity.
|
||||
U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");
|
||||
if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel))
|
||||
{
|
||||
// graphicslevel is valid: save it and engage it later. Capture
|
||||
// the requested value separately from the settings variable
|
||||
// because, if this is the first run, LLViewerWindow's constructor
|
||||
// will call LLFeatureManager::applyRecommendedSettings(), which
|
||||
// overwrites this settings variable!
|
||||
mForceGraphicsLevel = graphicslevel;
|
||||
}
|
||||
// User explicitly requested --graphicslevel on the command line. We
|
||||
// expect this switch has already set RenderQualityPerformance. Check
|
||||
// that value for validity later.
|
||||
// Capture the requested value separately from the settings variable
|
||||
// because, if this is the first run, LLViewerWindow's constructor
|
||||
// will call LLFeatureManager::applyRecommendedSettings(), which
|
||||
// overwrites this settings variable!
|
||||
mForceGraphicsLevel = gSavedSettings.getU32("RenderQualityPerformance");
|
||||
}
|
||||
|
||||
// <FS:Beq> Start profiling immediately unless deferred.
|
||||
|
|
@ -3676,7 +3671,7 @@ bool LLAppViewer::initWindow()
|
|||
// Initialize GL stuff
|
||||
//
|
||||
|
||||
if (mForceGraphicsLevel)
|
||||
if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel)))
|
||||
{
|
||||
LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
|
||||
gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
|
||||
|
|
|
|||
|
|
@ -825,7 +825,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
|
|||
{
|
||||
case LLModelPreview::MESH_OPTIMIZER_AUTO:
|
||||
case LLModelPreview::MESH_OPTIMIZER_SLOPPY:
|
||||
case LLModelPreview::MESH_OPTIMIZER_COMBINE:
|
||||
case LLModelPreview::MESH_OPTIMIZER_PRECISE:
|
||||
mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, mode);
|
||||
break;
|
||||
case LLModelPreview::GENERATE:
|
||||
|
|
@ -1962,7 +1962,7 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
|
|||
if (index == LLModelPreview::MESH_OPTIMIZER_AUTO
|
||||
|| index == LLModelPreview::GENERATE // <FS:Beq/> Improved LOD generation
|
||||
|| index == LLModelPreview::MESH_OPTIMIZER_SLOPPY
|
||||
|| index == LLModelPreview::MESH_OPTIMIZER_COMBINE)
|
||||
|| index == LLModelPreview::MESH_OPTIMIZER_PRECISE)
|
||||
{ //rebuild LoD to update triangle counts
|
||||
onLODParamCommit(lod, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,53 +642,75 @@ void LLFloaterTools::refresh()
|
|||
else
|
||||
#endif
|
||||
{
|
||||
F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost();
|
||||
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
|
||||
F32 link_cost = selection->getSelectedLinksetCost();
|
||||
// <FS:CR> FIRE-9287 - LI/Prim count not reflected on OpenSim
|
||||
#ifdef OPENSIM
|
||||
S32 prim_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
|
||||
S32 prim_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
|
||||
#endif // OPENSIM
|
||||
// </FS:CR>
|
||||
S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount();
|
||||
S32 link_count = selection->getRootObjectCount();
|
||||
//S32 object_count = selection->getObjectCount(); // <FS:Ansariel> We got this already
|
||||
|
||||
LLCrossParcelFunctor func;
|
||||
if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true))
|
||||
{
|
||||
// Selection crosses parcel bounds.
|
||||
// We don't display remaining land capacity in this case.
|
||||
const LLStringExplicit empty_str("");
|
||||
childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", empty_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerObject* selected_object = mObjectSelection->getFirstObject();
|
||||
if (selected_object)
|
||||
{
|
||||
// Select a parcel at the currently selected object's position.
|
||||
// <FS:Ansariel> FIRE-20387: Editing HUD attachment shows [CAPACITY_STRING] in tools floater
|
||||
//LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal());
|
||||
if (!selected_object->isAttachment())
|
||||
{
|
||||
LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal());
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLStringExplicit empty_str("");
|
||||
childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", empty_str);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Failed to get selected object" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
LLCrossParcelFunctor func;
|
||||
if (!LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true))
|
||||
{
|
||||
// Unless multiple parcels selected, higlight parcel object is at.
|
||||
LLViewerObject* selected_object = mObjectSelection->getFirstObject();
|
||||
if (selected_object)
|
||||
{
|
||||
// Select a parcel at the currently selected object's position.
|
||||
LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal());
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Failed to get selected object" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:Ansariel> We got this already
|
||||
//if (object_count == 1)
|
||||
//{
|
||||
// // "selection_faces" shouldn't be visible if not LLToolFace::getInstance()
|
||||
// // But still need to be populated in case user switches
|
||||
|
||||
// std::string faces_str = "";
|
||||
|
||||
// for (LLObjectSelection::iterator iter = selection->begin(); iter != selection->end();)
|
||||
// {
|
||||
// LLObjectSelection::iterator nextiter = iter++; // not strictly needed, we have only one object
|
||||
// LLSelectNode* node = *nextiter;
|
||||
// LLViewerObject* object = (*nextiter)->getObject();
|
||||
// if (!object)
|
||||
// continue;
|
||||
// S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces());
|
||||
// for (S32 te = 0; te < num_tes; ++te)
|
||||
// {
|
||||
// if (node->isTESelected(te))
|
||||
// {
|
||||
// if (!faces_str.empty())
|
||||
// {
|
||||
// faces_str += ", ";
|
||||
// }
|
||||
// faces_str += llformat("%d", te);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// childSetTextArg("selection_faces", "[FACES_STRING]", faces_str);
|
||||
//}
|
||||
|
||||
//bool show_faces = (object_count == 1)
|
||||
// && LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool();
|
||||
//getChildView("selection_faces")->setVisible(show_faces);
|
||||
// </FS:Ansariel>
|
||||
|
||||
LLStringUtil::format_map_t selection_args;
|
||||
selection_args["OBJ_COUNT"] = llformat("%.1d", link_count);
|
||||
// <FS:CR> FIRE-9287 - LI/Prim count not reflected on OpenSim
|
||||
#ifdef OPENSIM
|
||||
if (LLGridManager::getInstance()->isInOpenSim())
|
||||
selection_args["LAND_IMPACT"] = llformat("%.1d", (link_cost ? (S32)link_cost : (S32)prim_count));
|
||||
selection_args["LAND_IMPACT"] = llformat("%.1d", (link_cost ? (S32)link_cost : prim_count));
|
||||
else
|
||||
#endif // OPENSIM
|
||||
// </FS:CR>
|
||||
|
|
@ -1046,8 +1068,11 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
|
|||
|
||||
bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty();
|
||||
|
||||
// <FS>
|
||||
getChildView("more info label")->setVisible(!land_visible && have_selection);
|
||||
getChildView("selection_count")->setVisible(!land_visible && have_selection);
|
||||
getChildView("remaining_capacity")->setVisible(!land_visible && have_selection);
|
||||
getChildView("selection_faces")->setVisible(LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()
|
||||
&& LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1);
|
||||
getChildView("selection_empty")->setVisible(!land_visible && !have_selection);
|
||||
|
||||
//mTab->setVisible(!land_visible);
|
||||
|
|
@ -1371,7 +1396,7 @@ void LLFloaterTools::onClickGridOptions()
|
|||
{
|
||||
LLFloater* floaterp = LLFloaterReg::showInstance("build_options");
|
||||
// position floater next to build tools, not over
|
||||
floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
|
||||
floaterp->setShape(gFloaterView->findNeighboringPosition(this, floaterp), true);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -1460,26 +1485,6 @@ void LLFloaterTools::updateLandImpacts()
|
|||
return;
|
||||
}
|
||||
|
||||
S32 rezzed_prims = parcel->getSimWidePrimCount();
|
||||
S32 total_capacity = parcel->getSimWideMaxPrimCapacity();
|
||||
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
|
||||
if (region)
|
||||
{
|
||||
S32 max_tasks_per_region = (S32)region->getMaxTasks();
|
||||
total_capacity = llmin(total_capacity, max_tasks_per_region);
|
||||
}
|
||||
std::string remaining_capacity_str = "";
|
||||
|
||||
bool show_mesh_cost = gMeshRepo.meshRezEnabled();
|
||||
if (show_mesh_cost)
|
||||
{
|
||||
LLStringUtil::format_map_t remaining_capacity_args;
|
||||
remaining_capacity_args["LAND_CAPACITY"] = llformat("%d", total_capacity - rezzed_prims);
|
||||
remaining_capacity_str = getString("status_remaining_capacity", remaining_capacity_args);
|
||||
}
|
||||
|
||||
childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str);
|
||||
|
||||
// Update land impacts info in the weights floater
|
||||
LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights");
|
||||
if(object_weights_floater)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
//#include "llfirstuse.h"
|
||||
#include "llfloaterreg.h" // getTypedInstance()
|
||||
#include "llfocusmgr.h"
|
||||
//#include "lliconctrl.h" // <FS:Ansariel> Use own expand/collapse function
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llinventorymodelbackgroundfetch.h"
|
||||
|
|
@ -368,6 +369,9 @@ BOOL LLFloaterWorldMap::postBuild()
|
|||
|
||||
mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f);
|
||||
getChild<LLUICtrl>("zoom slider")->setValue(mCurZoomVal);
|
||||
|
||||
// <FS:Ansariel> Use own expand/collapse function
|
||||
//getChild<LLPanel>("expand_btn_panel")->setMouseDownCallback(boost::bind(&LLFloaterWorldMap::onExpandCollapseBtn, this));
|
||||
|
||||
setDefaultBtn(NULL);
|
||||
|
||||
|
|
@ -1648,6 +1652,24 @@ void LLFloaterWorldMap::onCopySLURL()
|
|||
LLNotificationsUtil::add("CopySLURL", args);
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Use own expand/collapse function
|
||||
//void LLFloaterWorldMap::onExpandCollapseBtn()
|
||||
//{
|
||||
// LLLayoutStack* floater_stack = getChild<LLLayoutStack>("floater_map_stack");
|
||||
// LLLayoutPanel* controls_panel = getChild<LLLayoutPanel>("controls_lp");
|
||||
|
||||
// bool toggle_collapse = !controls_panel->isCollapsed();
|
||||
// floater_stack->collapsePanel(controls_panel, toggle_collapse);
|
||||
// floater_stack->updateLayout();
|
||||
|
||||
// std::string image_name = getString(toggle_collapse ? "expand_icon" : "collapse_icon");
|
||||
// std::string tooltip = getString(toggle_collapse ? "expand_tooltip" : "collapse_tooltip");
|
||||
// getChild<LLIconCtrl>("expand_collapse_icon")->setImage(LLUI::getUIImage(image_name));
|
||||
// getChild<LLIconCtrl>("expand_collapse_icon")->setToolTip(tooltip);
|
||||
// getChild<LLPanel>("expand_btn_panel")->setToolTip(tooltip);
|
||||
//}
|
||||
// </FS:Ansariel>
|
||||
|
||||
// <FS:Ansariel> Alchemy region tracker
|
||||
void LLFloaterWorldMap::onTrackRegion()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ protected:
|
|||
// <FS:Ansariel> Alchemy region tracker
|
||||
void onTrackRegion();
|
||||
|
||||
// <FS:Ansariel> Use own expand/collapse function
|
||||
//void onExpandCollapseBtn();
|
||||
|
||||
void centerOnTarget(BOOL animate);
|
||||
void updateLocation();
|
||||
|
||||
|
|
|
|||
|
|
@ -855,6 +855,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||
// disabled_items.push_back(std::string("Copy"));
|
||||
//}
|
||||
|
||||
if (isAgentInventory())
|
||||
{
|
||||
items.push_back(std::string("New folder from selected"));
|
||||
items.push_back(std::string("Subfolder Separator"));
|
||||
std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
|
||||
uuid_vec_t ids;
|
||||
std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
|
||||
if (!is_only_items_selected(ids) && !is_only_cats_selected(ids))
|
||||
{
|
||||
disabled_items.push_back(std::string("New folder from selected"));
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->getIsLinkType())
|
||||
{
|
||||
items.push_back(std::string("Find Original"));
|
||||
|
|
@ -4723,7 +4736,16 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
|
|||
items.push_back(std::string("Conference Chat Folder"));
|
||||
items.push_back(std::string("IM All Contacts In Folder"));
|
||||
}
|
||||
|
||||
if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren())
|
||||
{
|
||||
items.push_back(std::string("Ungroup folder items"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disabled_items.push_back(std::string("New folder from selected"));
|
||||
}
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory)
|
||||
|
|
|
|||
|
|
@ -1995,6 +1995,86 @@ void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
|
|||
}
|
||||
}
|
||||
|
||||
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids)
|
||||
{
|
||||
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
|
||||
{
|
||||
LLInventoryItem* inv_item = gInventory.getItem(*it);
|
||||
if (inv_item)
|
||||
{
|
||||
change_item_parent(*it, new_cat_uuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLInventoryCategory* inv_cat = gInventory.getCategory(*it);
|
||||
if (inv_cat && !LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
|
||||
{
|
||||
gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory");
|
||||
if (!floater_inventory)
|
||||
{
|
||||
LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
|
||||
if (sidepanel_inventory)
|
||||
{
|
||||
if (sidepanel_inventory->getActivePanel())
|
||||
{
|
||||
sidepanel_inventory->getActivePanel()->setSelection(new_cat_uuid, TAKE_FOCUS_YES);
|
||||
LLFolderViewItem* fv_folder = sidepanel_inventory->getActivePanel()->getItemByID(new_cat_uuid);
|
||||
if (fv_folder)
|
||||
{
|
||||
fv_folder->setOpen(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_only_cats_selected(const uuid_vec_t& selected_uuids)
|
||||
{
|
||||
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
|
||||
{
|
||||
LLInventoryCategory* inv_cat = gInventory.getCategory(*it);
|
||||
if (!inv_cat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_only_items_selected(const uuid_vec_t& selected_uuids)
|
||||
{
|
||||
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
|
||||
{
|
||||
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
|
||||
if (!inv_item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name)
|
||||
{
|
||||
LLInventoryObject* first_item = gInventory.getObject(*selected_uuids.begin());
|
||||
if (!first_item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids);
|
||||
gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func);
|
||||
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLInventoryCollectFunctor implementations
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -2767,6 +2847,81 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
|
|||
{
|
||||
(new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile();
|
||||
}
|
||||
else if ("new_folder_from_selected" == action)
|
||||
{
|
||||
|
||||
LLInventoryObject* first_item = gInventory.getObject(*ids.begin());
|
||||
if (!first_item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const LLUUID& parent_uuid = first_item->getParentUUID();
|
||||
for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
LLInventoryObject *item = gInventory.getObject(*it);
|
||||
if (!item || item->getParentUUID() != parent_uuid)
|
||||
{
|
||||
LLNotificationsUtil::add("SameFolderRequired");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LLSD args;
|
||||
args["DESC"] = LLTrans::getString("New Folder");
|
||||
|
||||
LLNotificationsUtil::add("CreateSubfolder", args, LLSD(),
|
||||
[ids](const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 opt = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
if (opt == 0)
|
||||
{
|
||||
std::string settings_name = response["message"].asString();
|
||||
|
||||
LLInventoryObject::correctInventoryName(settings_name);
|
||||
if (settings_name.empty())
|
||||
{
|
||||
settings_name = LLTrans::getString("New Folder");
|
||||
}
|
||||
move_items_to_new_subfolder(ids, settings_name);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if ("ungroup_folder_items" == action)
|
||||
{
|
||||
if (selected_uuid_set.size() == 1)
|
||||
{
|
||||
LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin());
|
||||
if (!inv_cat || LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
const LLUUID &new_cat_uuid = inv_cat->getParentUUID();
|
||||
LLInventoryModel::cat_array_t* cat_array;
|
||||
LLInventoryModel::item_array_t* item_array;
|
||||
gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array);
|
||||
LLInventoryModel::cat_array_t cats = *cat_array;
|
||||
LLInventoryModel::item_array_t items = *item_array;
|
||||
|
||||
for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter)
|
||||
{
|
||||
LLViewerInventoryCategory* cat = *cat_iter;
|
||||
if (cat)
|
||||
{
|
||||
gInventory.changeCategoryParent(cat, new_cat_uuid, false);
|
||||
}
|
||||
}
|
||||
for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter)
|
||||
{
|
||||
LLViewerInventoryItem* item = *item_iter;
|
||||
if(item)
|
||||
{
|
||||
gInventory.changeItemParent(item, new_cat_uuid, false);
|
||||
}
|
||||
}
|
||||
gInventory.removeCategory(inv_cat->getUUID());
|
||||
gInventory.notifyObservers();
|
||||
}
|
||||
}
|
||||
// <FS:Ansariel> FIRE-22851: Show texture "Save as" file picker subsequently instead all at once
|
||||
else if (action == "save_as") // "save_as" is only available for textures as of 01/08/2018
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
|
|||
S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
|
||||
|
||||
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id);
|
||||
void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name);
|
||||
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids);
|
||||
bool is_only_cats_selected(const uuid_vec_t& selected_uuids);
|
||||
bool is_only_items_selected(const uuid_vec_t& selected_uuids);
|
||||
|
||||
/** Miscellaneous global functions
|
||||
** **
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public:
|
|||
LLUUID getWorldID(LLUUID tracking_id);
|
||||
bool isLocal(LLUUID world_id);
|
||||
std::string getFilename(LLUUID tracking_id);
|
||||
|
||||
|
||||
void feedScrollList(LLScrollListCtrl* ctrl);
|
||||
void doUpdates();
|
||||
void setNeedsRebake();
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
|
|||
}
|
||||
|
||||
mViewOption["show_textures"] = false;
|
||||
|
||||
mFMP = fmp;
|
||||
glodInit(); // <FS:Beq/> Improved LOD generation
|
||||
mHasPivot = false;
|
||||
|
|
@ -597,7 +598,7 @@ void LLModelPreview::rebuildUploadData()
|
|||
std::ostringstream out;
|
||||
out << "Attempting to use model index " << idx;
|
||||
// <FS:Beq> better debug (watch for dangling single line else)
|
||||
if(i==4)
|
||||
if (i==4)
|
||||
{
|
||||
out << " for PHYS";
|
||||
}
|
||||
|
|
@ -953,7 +954,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
|
|||
std::map<std::string, std::string> joint_alias_map;
|
||||
getJointAliases(joint_alias_map);
|
||||
|
||||
std::array<std::string,LLModel::NUM_LODS> lod_suffix;
|
||||
std::array<std::string, LLModel::NUM_LODS> lod_suffix;
|
||||
for(int i=0; i < LLModel::NUM_LODS; i++)
|
||||
{
|
||||
lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]);
|
||||
|
|
@ -1077,8 +1078,10 @@ void LLModelPreview::clearIncompatible(S32 lod)
|
|||
// at this point we don't care about sub-models,
|
||||
// different amount of sub-models means face count mismatch, not incompatibility
|
||||
U32 lod_size = countRootModels(mModel[lod]);
|
||||
bool replaced_base_model = (lod == LLModel::LOD_HIGH);
|
||||
for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
|
||||
{ //clear out any entries that aren't compatible with this model
|
||||
{
|
||||
// Clear out any entries that aren't compatible with this model
|
||||
if (i != lod)
|
||||
{
|
||||
if (countRootModels(mModel[i]) != lod_size)
|
||||
|
|
@ -1092,11 +1095,50 @@ void LLModelPreview::clearIncompatible(S32 lod)
|
|||
mBaseModel = mModel[lod];
|
||||
mBaseScene = mScene[lod];
|
||||
mVertexBuffer[5].clear();
|
||||
replaced_base_model = true;
|
||||
|
||||
clearGLODGroup(); // <FS:Beq/> Improved LOD generation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (replaced_base_model && !mGenLOD)
|
||||
{
|
||||
// In case base was replaced, we might need to restart generation
|
||||
|
||||
// Check if already started
|
||||
bool subscribe_for_generation = mLodsQuery.empty();
|
||||
|
||||
// Remove previously scheduled work
|
||||
mLodsQuery.clear();
|
||||
|
||||
LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
|
||||
if (!fmp) return;
|
||||
|
||||
// Schedule new work
|
||||
for (S32 i = LLModel::LOD_HIGH; i >= 0; --i)
|
||||
{
|
||||
if (mModel[i].empty())
|
||||
{
|
||||
// Base model was replaced, regenerate this lod if applicable
|
||||
LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[i]);
|
||||
if (!lod_combo) return;
|
||||
|
||||
S32 lod_mode = lod_combo->getCurrentIndex();
|
||||
if (lod_mode != LOD_FROM_FILE)
|
||||
{
|
||||
mLodsQuery.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe if we have pending work and not subscribed yet
|
||||
if (!mLodsQuery.empty() && subscribe_for_generation)
|
||||
{
|
||||
doOnIdleRepeating(lodQueryCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:Beq> Improved LOD generation
|
||||
|
|
@ -1951,8 +1993,9 @@ void LLModelPreview::genGlodLODs(S32 which_lod, U32 decimation, bool enforce_tri
|
|||
// Runs per object, but likely it is a better way to run per model+submodels
|
||||
// returns a ratio of base model indices to resulting indices
|
||||
// returns -1 in case of failure
|
||||
F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, bool sloppy)
|
||||
F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode)
|
||||
{
|
||||
// I. Weld faces together
|
||||
// Figure out buffer size
|
||||
S32 size_indices = 0;
|
||||
S32 size_vertices = 0;
|
||||
|
|
@ -1987,20 +2030,21 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
{
|
||||
const LLVolumeFace &face = base_model->getVolumeFace(face_idx);
|
||||
|
||||
// vertices
|
||||
// Vertices
|
||||
S32 copy_bytes = face.mNumVertices * sizeof(LLVector4a);
|
||||
LLVector4a::memcpyNonAliased16((F32*)(combined_positions + combined_positions_shift), (F32*)face.mPositions, copy_bytes);
|
||||
|
||||
// normals
|
||||
// Normals
|
||||
LLVector4a::memcpyNonAliased16((F32*)(combined_normals + combined_positions_shift), (F32*)face.mNormals, copy_bytes);
|
||||
|
||||
// tex coords
|
||||
// Tex coords
|
||||
copy_bytes = face.mNumVertices * sizeof(LLVector2);
|
||||
memcpy((void*)(combined_tex_coords + combined_positions_shift), (void*)face.mTexCoords, copy_bytes);
|
||||
|
||||
combined_positions_shift += face.mNumVertices;
|
||||
|
||||
// indices, sadly can't do dumb memcpy for indices, need to adjust each value
|
||||
// Indices
|
||||
// Sadly can't do dumb memcpy for indices, need to adjust each value
|
||||
for (S32 i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
U16 idx = face.mIndices[i];
|
||||
|
|
@ -2011,10 +2055,42 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
indices_idx_shift += face.mNumVertices;
|
||||
}
|
||||
|
||||
// Now that we have buffers, optimize
|
||||
// II. Generate a shadow buffer if nessesary.
|
||||
// Welds together vertices if possible
|
||||
|
||||
U32* shadow_indices = NULL;
|
||||
// if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32
|
||||
// won't do anything new, model was remaped on a per face basis.
|
||||
// Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless
|
||||
// since 'simplifySloppy' ignores all topology, including normals and uvs.
|
||||
// Note: simplifySloppy can affect UVs significantly.
|
||||
if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS)
|
||||
{
|
||||
// strip normals, reflections should restore relatively correctly
|
||||
shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32));
|
||||
LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, combined_tex_coords, size_vertices);
|
||||
}
|
||||
if (simplification_mode == MESH_OPTIMIZER_NO_UVS)
|
||||
{
|
||||
// strip uvs, can heavily affect textures
|
||||
shadow_indices = (U32*)ll_aligned_malloc_32(size_indices * sizeof(U32));
|
||||
LLMeshOptimizer::generateShadowIndexBufferU32(shadow_indices, combined_indices, size_indices, combined_positions, NULL, NULL, size_vertices);
|
||||
}
|
||||
|
||||
U32* source_indices = NULL;
|
||||
if (shadow_indices)
|
||||
{
|
||||
source_indices = shadow_indices;
|
||||
}
|
||||
else
|
||||
{
|
||||
source_indices = combined_indices;
|
||||
}
|
||||
|
||||
// III. Simplify
|
||||
S32 target_indices = 0;
|
||||
F32 result_error = 0; // how far from original the model is, 1 == 100%
|
||||
S32 new_indices = 0;
|
||||
S32 size_new_indices = 0;
|
||||
|
||||
if (indices_decimator > 0)
|
||||
{
|
||||
|
|
@ -2024,30 +2100,30 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
{
|
||||
target_indices = 3;
|
||||
}
|
||||
new_indices = LLMeshOptimizer::simplifyU32(
|
||||
|
||||
size_new_indices = LLMeshOptimizer::simplifyU32(
|
||||
output_indices,
|
||||
combined_indices,
|
||||
source_indices,
|
||||
size_indices,
|
||||
combined_positions,
|
||||
size_vertices,
|
||||
LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],
|
||||
target_indices,
|
||||
error_threshold,
|
||||
sloppy,
|
||||
simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY,
|
||||
&result_error);
|
||||
|
||||
|
||||
if (result_error < 0)
|
||||
{
|
||||
// <FS:Beq> Log these properly
|
||||
// LL_WARNS() << "Negative result error from meshoptimizer for model " << target_model->mLabel
|
||||
// << " target Indices: " << target_indices
|
||||
// << " new Indices: " << new_indices
|
||||
// << " new Indices: " << size_new_indices
|
||||
// << " original count: " << size_indices << LL_ENDL;
|
||||
std::ostringstream out;
|
||||
out << "Negative result error from meshoptimizer for model " << target_model->mLabel
|
||||
<< " target Indices: " << target_indices
|
||||
<< " new Indices: " << new_indices
|
||||
<< " new Indices: " << size_new_indices
|
||||
<< " original count: " << size_indices ;
|
||||
LL_WARNS() << out.str() << LL_ENDL;
|
||||
LLFloaterModelPreview::addStringToLog(out, true);
|
||||
|
|
@ -2059,7 +2135,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
std::ostringstream out;
|
||||
out << "Good result error from meshoptimizer for model " << target_model->mLabel
|
||||
<< " target Indices: " << target_indices
|
||||
<< " new Indices: " << new_indices
|
||||
<< " new Indices: " << size_new_indices
|
||||
<< " original count: " << size_indices << " (result error:" << result_error << ")";
|
||||
LL_DEBUGS() << out.str() << LL_ENDL;
|
||||
LLFloaterModelPreview::addStringToLog(out, true);
|
||||
|
|
@ -2067,17 +2143,22 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
// </FS:Beq>
|
||||
}
|
||||
|
||||
if (new_indices < 3)
|
||||
// free unused buffers
|
||||
ll_aligned_free_32(combined_indices);
|
||||
ll_aligned_free_32(shadow_indices);
|
||||
combined_indices = NULL;
|
||||
shadow_indices = NULL;
|
||||
|
||||
if (size_new_indices < 3)
|
||||
{
|
||||
// Model should have at least one visible triangle
|
||||
ll_aligned_free<64>(combined_positions);
|
||||
ll_aligned_free_32(output_indices);
|
||||
ll_aligned_free_32(combined_indices);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// repack back into individual faces
|
||||
// IV. Repack back into individual faces
|
||||
|
||||
LLVector4a* buffer_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * size_vertices + tc_bytes_size);
|
||||
LLVector4a* buffer_normals = buffer_positions + size_vertices;
|
||||
|
|
@ -2108,7 +2189,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
}
|
||||
|
||||
// Copy relevant indices and vertices
|
||||
for (S32 i = 0; i < new_indices; ++i)
|
||||
for (S32 i = 0; i < size_new_indices; ++i)
|
||||
{
|
||||
U32 idx = output_indices[i];
|
||||
|
||||
|
|
@ -2132,7 +2213,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
// LL_WARNS() << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for"
|
||||
// << " model " << target_model->mLabel
|
||||
// << " target Indices: " << target_indices
|
||||
// << " new Indices: " << new_indices
|
||||
// << " new Indices: " << size_new_indices
|
||||
// << " original count: " << size_indices
|
||||
// << " error treshold: " << error_threshold
|
||||
// << LL_ENDL;
|
||||
|
|
@ -2142,20 +2223,20 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
out << "Over triangle limit. Failed to optimize in 'per object' mode, falling back to per face variant for"
|
||||
<< " model " << target_model->mLabel
|
||||
<< " target Indices: " << target_indices
|
||||
<< " new Indices: " << new_indices
|
||||
<< " new Indices: " << size_new_indices
|
||||
<< " original count: " << size_indices
|
||||
<< " error treshold: " << error_threshold;
|
||||
LL_DEBUGS() << out.str() << LL_ENDL;
|
||||
LLFloaterModelPreview::addStringToLog(out, true);
|
||||
}
|
||||
// U16 vertices overflow shouldn't happen, but just in case
|
||||
new_indices = 0;
|
||||
size_new_indices = 0;
|
||||
valid_faces = 0;
|
||||
for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx)
|
||||
{
|
||||
genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false);
|
||||
genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, simplification_mode);
|
||||
const LLVolumeFace &face = target_model->getVolumeFace(face_idx);
|
||||
new_indices += face.mNumIndices;
|
||||
size_new_indices += face.mNumIndices;
|
||||
if (face.mNumIndices >= 3)
|
||||
{
|
||||
valid_faces++;
|
||||
|
|
@ -2163,7 +2244,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
}
|
||||
if (valid_faces)
|
||||
{
|
||||
return (F32)size_indices / (F32)new_indices;
|
||||
return (F32)size_indices / (F32)size_new_indices;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2233,18 +2314,17 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
|
|||
ll_aligned_free<64>(buffer_positions);
|
||||
ll_aligned_free_32(output_indices);
|
||||
ll_aligned_free_16(buffer_indices);
|
||||
ll_aligned_free_32(combined_indices);
|
||||
|
||||
if (new_indices < 3 || valid_faces == 0)
|
||||
if (size_new_indices < 3 || valid_faces == 0)
|
||||
{
|
||||
// Model should have at least one visible triangle
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (F32)size_indices / (F32)new_indices;
|
||||
return (F32)size_indices / (F32)size_new_indices;
|
||||
}
|
||||
|
||||
F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, bool sloppy)
|
||||
F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_decimator, F32 error_threshold, eSimplificationMode simplification_mode)
|
||||
{
|
||||
const LLVolumeFace &face = base_model->getVolumeFace(face_idx);
|
||||
S32 size_indices = face.mNumIndices;
|
||||
|
|
@ -2252,14 +2332,40 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
{
|
||||
return -1;
|
||||
}
|
||||
// todo: do not allocate per each face, add one large buffer somewhere
|
||||
// faces have limited amount of indices
|
||||
|
||||
S32 size = (size_indices * sizeof(U16) + 0xF) & ~0xF;
|
||||
U16* output = (U16*)ll_aligned_malloc_16(size);
|
||||
U16* output_indices = (U16*)ll_aligned_malloc_16(size);
|
||||
|
||||
U16* shadow_indices = NULL;
|
||||
// if MESH_OPTIMIZER_FULL, just leave as is, since generateShadowIndexBufferU32
|
||||
// won't do anything new, model was remaped on a per face basis.
|
||||
// Similar for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless
|
||||
// since 'simplifySloppy' ignores all topology, including normals and uvs.
|
||||
if (simplification_mode == MESH_OPTIMIZER_NO_NORMALS)
|
||||
{
|
||||
U16* shadow_indices = (U16*)ll_aligned_malloc_16(size);
|
||||
LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, face.mTexCoords, face.mNumVertices);
|
||||
}
|
||||
if (simplification_mode == MESH_OPTIMIZER_NO_UVS)
|
||||
{
|
||||
U16* shadow_indices = (U16*)ll_aligned_malloc_16(size);
|
||||
LLMeshOptimizer::generateShadowIndexBufferU16(shadow_indices, face.mIndices, size_indices, face.mPositions, NULL, NULL, face.mNumVertices);
|
||||
}
|
||||
// Don't run ShadowIndexBuffer for MESH_OPTIMIZER_NO_TOPOLOGY, it's pointless
|
||||
|
||||
U16* source_indices = NULL;
|
||||
if (shadow_indices)
|
||||
{
|
||||
source_indices = shadow_indices;
|
||||
}
|
||||
else
|
||||
{
|
||||
source_indices = face.mIndices;
|
||||
}
|
||||
|
||||
S32 target_indices = 0;
|
||||
F32 result_error = 0; // how far from original the model is, 1 == 100%
|
||||
S32 new_indices = 0;
|
||||
S32 size_new_indices = 0;
|
||||
|
||||
if (indices_decimator > 0)
|
||||
{
|
||||
|
|
@ -2269,26 +2375,26 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
{
|
||||
target_indices = 3;
|
||||
}
|
||||
new_indices = LLMeshOptimizer::simplify(
|
||||
output,
|
||||
face.mIndices,
|
||||
|
||||
size_new_indices = LLMeshOptimizer::simplify(
|
||||
output_indices,
|
||||
source_indices,
|
||||
size_indices,
|
||||
face.mPositions,
|
||||
face.mNumVertices,
|
||||
LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX],
|
||||
target_indices,
|
||||
error_threshold,
|
||||
sloppy,
|
||||
simplification_mode == MESH_OPTIMIZER_NO_TOPOLOGY,
|
||||
&result_error);
|
||||
|
||||
|
||||
if (result_error < 0)
|
||||
{
|
||||
// <FS:Beq> Log these properly
|
||||
// LL_WARNS() << "Negative result error from meshoptimizer for face " << face_idx
|
||||
// << " of model " << target_model->mLabel
|
||||
// << " target Indices: " << target_indices
|
||||
// << " new Indices: " << new_indices
|
||||
// << " new Indices: " << size_new_indices
|
||||
// << " original count: " << size_indices
|
||||
// << " error treshold: " << error_threshold
|
||||
// << LL_ENDL;
|
||||
|
|
@ -2296,7 +2402,7 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
out << "Negative result error from meshoptimizer for face " << face_idx
|
||||
<< " of model " << target_model->mLabel
|
||||
<< " target Indices: " << target_indices
|
||||
<< " new Indices: " << new_indices
|
||||
<< " new Indices: " << size_new_indices
|
||||
<< " original count: " << size_indices
|
||||
<< " error treshold: " << error_threshold;
|
||||
LL_WARNS() << out.str() << LL_ENDL;
|
||||
|
|
@ -2310,7 +2416,7 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
out << "Good result error from meshoptimizer for face " << face_idx
|
||||
<< " of model " << target_model->mLabel
|
||||
<< " target Indices: " << target_indices
|
||||
<< " new Indices: " << new_indices
|
||||
<< " new Indices: " << size_new_indices
|
||||
<< " original count: " << size_indices
|
||||
<< " error treshold: " << error_threshold << " (result error:" << result_error << ")";
|
||||
LL_DEBUGS("MeshUpload") << out.str() << LL_ENDL;
|
||||
|
|
@ -2324,10 +2430,9 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
// Copy old values
|
||||
new_face = face;
|
||||
|
||||
|
||||
if (new_indices < 3)
|
||||
if (size_new_indices < 3)
|
||||
{
|
||||
if (!sloppy)
|
||||
if (simplification_mode != MESH_OPTIMIZER_NO_TOPOLOGY)
|
||||
{
|
||||
// meshopt_optimizeSloppy() can optimize triangles away even if target_indices is > 2,
|
||||
// but optimize() isn't supposed to
|
||||
|
|
@ -2359,23 +2464,24 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
|
|||
else
|
||||
{
|
||||
// Assign new values
|
||||
new_face.resizeIndices(new_indices); // will wipe out mIndices, so new_face can't substitute output
|
||||
S32 idx_size = (new_indices * sizeof(U16) + 0xF) & ~0xF;
|
||||
LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output, idx_size);
|
||||
new_face.resizeIndices(size_new_indices); // will wipe out mIndices, so new_face can't substitute output
|
||||
S32 idx_size = (size_new_indices * sizeof(U16) + 0xF) & ~0xF;
|
||||
LLVector4a::memcpyNonAliased16((F32*)new_face.mIndices, (F32*)output_indices, idx_size);
|
||||
|
||||
// clear unused values
|
||||
// Clear unused values
|
||||
new_face.optimize();
|
||||
}
|
||||
|
||||
ll_aligned_free_16(output);
|
||||
ll_aligned_free_16(output_indices);
|
||||
ll_aligned_free_16(shadow_indices);
|
||||
|
||||
if (new_indices < 3)
|
||||
if (size_new_indices < 3)
|
||||
{
|
||||
// At least one triangle is needed
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (F32)size_indices / (F32)new_indices;
|
||||
return (F32)size_indices / (F32)size_new_indices;
|
||||
}
|
||||
|
||||
void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation, bool enforce_tri_limit)
|
||||
|
|
@ -2506,7 +2612,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
// std::string name = base->mLabel + getLodSuffix(lod);
|
||||
std::string name = stripSuffix(base->mLabel);
|
||||
std::string suffix = getLodSuffix(lod);
|
||||
if ( suffix.size() > 0 )
|
||||
if (suffix.size() > 0)
|
||||
{
|
||||
name += suffix;
|
||||
}
|
||||
|
|
@ -2522,16 +2628,19 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
|
||||
// Ideally this should run not per model,
|
||||
// but combine all submodels with origin model as well
|
||||
if (model_meshopt_mode == MESH_OPTIMIZER_COMBINE)
|
||||
if (model_meshopt_mode == MESH_OPTIMIZER_PRECISE)
|
||||
{
|
||||
// Run meshoptimizer for each model/object, up to 8 faces in one model.
|
||||
|
||||
// Ideally this should run not per model,
|
||||
// but combine all submodels with origin model as well
|
||||
F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
|
||||
if (res < 0)
|
||||
// Run meshoptimizer for each face
|
||||
for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
|
||||
{
|
||||
target_model->copyVolumeFaces(base);
|
||||
F32 res = genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);
|
||||
if (res < 0)
|
||||
{
|
||||
// Mesh optimizer failed and returned an invalid model
|
||||
const LLVolumeFace &face = base->getVolumeFace(face_idx);
|
||||
LLVolumeFace &new_face = target_model->getVolumeFace(face_idx);
|
||||
new_face = face;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2540,19 +2649,29 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
// Run meshoptimizer for each face
|
||||
for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
|
||||
{
|
||||
if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0)
|
||||
if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY) < 0)
|
||||
{
|
||||
// Sloppy failed and returned an invalid model
|
||||
genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
|
||||
genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model_meshopt_mode == MESH_OPTIMIZER_AUTO)
|
||||
{
|
||||
// Switches between 'combine' method and 'sloppy' based on combine's result.
|
||||
F32 allowed_ratio_drift = 2.f;
|
||||
F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
|
||||
// Remove progressively more data if we can't reach the target.
|
||||
F32 allowed_ratio_drift = 1.8f;
|
||||
F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);
|
||||
|
||||
if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
|
||||
{
|
||||
precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_NORMALS);
|
||||
}
|
||||
|
||||
if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
|
||||
{
|
||||
precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS);
|
||||
}
|
||||
|
||||
if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
|
||||
{
|
||||
|
|
@ -2560,10 +2679,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
// Sloppy variant can fail entirely and has issues with precision,
|
||||
// so code needs to do multiple attempts with different decimators.
|
||||
// Todo: this is a bit of a mess, needs to be refined and improved
|
||||
|
||||
F32 last_working_decimator = 0.f;
|
||||
F32 last_working_ratio = F32_MAX;
|
||||
|
||||
F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true);
|
||||
F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
|
||||
|
||||
if (sloppy_ratio > 0)
|
||||
{
|
||||
|
|
@ -2586,13 +2706,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
// side due to overal lack of precision, and we don't need an ideal result, which
|
||||
// likely does not exist, just a better one, so a partial correction is enough.
|
||||
F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2;
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true);
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
|
||||
}
|
||||
|
||||
if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio)
|
||||
{
|
||||
// Compensation didn't work, return back to previous decimator
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true);
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
|
||||
}
|
||||
|
||||
if (sloppy_ratio < 0)
|
||||
|
|
@ -2630,7 +2750,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
&& sloppy_decimator > precise_ratio
|
||||
&& sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case
|
||||
{
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true);
|
||||
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
|
||||
sloppy_decimator = sloppy_decimator / sloppy_decimation_step;
|
||||
}
|
||||
}
|
||||
|
|
@ -2650,7 +2770,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
else
|
||||
{
|
||||
// Fallback to normal method
|
||||
precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
|
||||
precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_FULL);
|
||||
}
|
||||
// <FS:Beq> Log stuff properly
|
||||
// LL_INFOS() << "Model " << target_model->getName()
|
||||
|
|
@ -2874,7 +2994,6 @@ void LLModelPreview::updateStatusMessages()
|
|||
{//check for degenerate triangles in physics mesh
|
||||
U32 lod = LLModel::LOD_PHYSICS;
|
||||
const LLVector4a scale(0.5f);
|
||||
|
||||
for (U32 i = 0; i < mModel[lod].size() && !mHasDegenerate; ++i)
|
||||
{ //for each model in the lod
|
||||
if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
|
||||
|
|
@ -3360,7 +3479,7 @@ void LLModelPreview::updateStatusMessages()
|
|||
|
||||
if (phys_tris || phys_hulls > 0)
|
||||
{
|
||||
fmp->childEnable("Decompose");
|
||||
fmp->childEnable("Decompose");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -4879,7 +4998,7 @@ bool LLModelPreview::lodQueryCallback()
|
|||
}
|
||||
|
||||
// return false to continue cycle
|
||||
return false;
|
||||
return preview->mLodsQuery.empty();
|
||||
}
|
||||
}
|
||||
// nothing to process
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public:
|
|||
{
|
||||
LOD_FROM_FILE = 0,
|
||||
MESH_OPTIMIZER_AUTO, // automatically selects method based on model or face
|
||||
MESH_OPTIMIZER_COMBINE, // combines faces into a single model, simplifies, then splits back into faces
|
||||
MESH_OPTIMIZER_PRECISE, // combines faces into a single model, simplifies, then splits back into faces
|
||||
MESH_OPTIMIZER_SLOPPY, // uses sloppy method, works per face
|
||||
GENERATE, // Use GLOD <FS:Beq/> Improved LOD generation
|
||||
USE_LOD_ABOVE,
|
||||
|
|
@ -231,13 +231,21 @@ private:
|
|||
// Count amount of original models, excluding sub-models
|
||||
static U32 countRootModels(LLModelLoader::model_list models);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MESH_OPTIMIZER_FULL,
|
||||
MESH_OPTIMIZER_NO_NORMALS,
|
||||
MESH_OPTIMIZER_NO_UVS,
|
||||
MESH_OPTIMIZER_NO_TOPOLOGY,
|
||||
} eSimplificationMode;
|
||||
|
||||
// Merges faces into single mesh, simplifies using mesh optimizer,
|
||||
// then splits back into faces.
|
||||
// Returns reached simplification ratio. -1 in case of a failure.
|
||||
F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, bool sloppy);
|
||||
F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode);
|
||||
// Simplifies specified face using mesh optimizer.
|
||||
// Returns reached simplification ratio. -1 in case of a failure.
|
||||
F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, bool sloppy);
|
||||
F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, eSimplificationMode simplification_mode);
|
||||
|
||||
protected:
|
||||
friend class LLModelLoader;
|
||||
|
|
|
|||
|
|
@ -1439,7 +1439,8 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
|
|||
gMorphView->setCameraOffset( subpart_entry->mCameraOffset );
|
||||
if (gSavedSettings.getBOOL("AppearanceCameraMovement"))
|
||||
{
|
||||
gMorphView->updateCamera();
|
||||
gAgentCamera.setFocusOnAvatar(FALSE, FALSE);
|
||||
gMorphView->updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class LLUICtrl;
|
|||
class LLViewerObject;
|
||||
class LLFloater;
|
||||
class LLMaterialID;
|
||||
class LLMenuButton;
|
||||
|
||||
// Represents an edit for use in replicating the op across one or more materials in the selection set.
|
||||
//
|
||||
|
|
@ -97,6 +98,8 @@ public:
|
|||
LLPanelFace();
|
||||
virtual ~LLPanelFace();
|
||||
|
||||
void draw();
|
||||
|
||||
void refresh();
|
||||
void setMediaURL(const std::string& url);
|
||||
void setMediaType(const std::string& mime_type);
|
||||
|
|
@ -130,6 +133,8 @@ protected:
|
|||
void sendMedia();
|
||||
void alignTestureLayer();
|
||||
|
||||
void updateCopyTexButton();
|
||||
|
||||
// this function is to return TRUE if the drag should succeed.
|
||||
static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item);
|
||||
|
||||
|
|
@ -207,11 +212,27 @@ protected:
|
|||
static void onClickAutoFix(void*);
|
||||
static void onAlignTexture(void*);
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
void onCopyFaces();
|
||||
void onPasteFaces();
|
||||
// </FS>
|
||||
|
||||
public: // needs to be accessible to selection manager
|
||||
void onCopyColor(); // records all selected faces
|
||||
void onPasteColor(); // to specific face
|
||||
void onPasteColor(LLViewerObject* objectp, S32 te); // to specific face
|
||||
void onCopyTexture();
|
||||
void onPasteTexture();
|
||||
void onPasteTexture(LLViewerObject* objectp, S32 te);
|
||||
|
||||
protected:
|
||||
// <FS> Extended copy & paste buttons
|
||||
//void menuDoToSelected(const LLSD& userdata);
|
||||
//bool menuEnableItem(const LLSD& userdata);
|
||||
// </FS>
|
||||
|
||||
static F32 valueGlow(LLViewerObject* object, S32 face);
|
||||
|
||||
// <FS> Texture params copy/paste
|
||||
static void onClickCopy(void*);
|
||||
static void onClickPaste(void*);
|
||||
// <FS:CR> Build tool enhancements
|
||||
static void onClickMapsSync(LLUICtrl* ctrl, void *userdata);
|
||||
static void alignMaterialsProperties(LLPanelFace* self);
|
||||
|
|
@ -455,7 +476,14 @@ private:
|
|||
* If agent selects texture which is not allowed to be applied for the currently selected object,
|
||||
* all controls of the floater texture picker which allow to apply the texture will be disabled.
|
||||
*/
|
||||
void onTextureSelectionChanged(LLInventoryItem* itemp);
|
||||
void onTextureSelectionChanged(LLInventoryItem* itemp);
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//LLMenuButton* mMenuClipboardColor;
|
||||
//LLMenuButton* mMenuClipboardTexture;
|
||||
LLButton* mBtnCopyFaces;
|
||||
LLButton* mBtnPasteFaces;
|
||||
// </FS>
|
||||
|
||||
bool mIsAlpha;
|
||||
|
||||
|
|
@ -470,7 +498,9 @@ private:
|
|||
* up-arrow on a spinner, and avoids running afoul of its throttle.
|
||||
*/
|
||||
bool mUpdateInFlight;
|
||||
bool mUpdatePending;
|
||||
bool mUpdatePending;
|
||||
|
||||
LLSD mClipboardParams;
|
||||
|
||||
public:
|
||||
#if defined(DEF_GET_MAT_STATE)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "llcombobox.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llmanipscale.h"
|
||||
#include "llmenubutton.h"
|
||||
#include "llpreviewscript.h"
|
||||
#include "llresmgr.h"
|
||||
#include "llselectmgr.h"
|
||||
|
|
@ -70,17 +71,6 @@
|
|||
#include "llvoavatarself.h"
|
||||
// [/RLVa:KB]
|
||||
|
||||
#include "llwindow.h" // for clipboad operations -KC
|
||||
|
||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||
#include "rlvhandler.h"
|
||||
#include "llvoavatarself.h"
|
||||
// [/RLVa:KB]
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventorymodel.h"
|
||||
|
||||
#include "lldrawpool.h"
|
||||
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
|
|
@ -146,8 +136,9 @@ BOOL LLPanelObject::postBuild()
|
|||
// Phantom checkbox
|
||||
mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl");
|
||||
childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this);
|
||||
|
||||
|
||||
// Position
|
||||
//mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn"); // <FS> Extended copy & paste buttons
|
||||
mLabelPosition = getChild<LLTextBox>("label position");
|
||||
mCtrlPosX = getChild<LLSpinCtrl>("Pos X");
|
||||
childSetCommitCallback("Pos X",onCommitPosition,this);
|
||||
|
|
@ -157,6 +148,7 @@ BOOL LLPanelObject::postBuild()
|
|||
childSetCommitCallback("Pos Z",onCommitPosition,this);
|
||||
|
||||
// Scale
|
||||
//mMenuClipboardSize = getChild<LLMenuButton>("clipboard_size_btn"); // <FS> Extended copy & paste buttons
|
||||
mLabelSize = getChild<LLTextBox>("label size");
|
||||
mCtrlScaleX = getChild<LLSpinCtrl>("Scale X");
|
||||
childSetCommitCallback("Scale X",onCommitScale,this);
|
||||
|
|
@ -170,6 +162,7 @@ BOOL LLPanelObject::postBuild()
|
|||
childSetCommitCallback("Scale Z",onCommitScale,this);
|
||||
|
||||
// Rotation
|
||||
//mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn"); // <FS> Extended copy & paste buttons
|
||||
mLabelRotation = getChild<LLTextBox>("label rotation");
|
||||
mCtrlRotX = getChild<LLSpinCtrl>("Rot X");
|
||||
childSetCommitCallback("Rot X",onCommitRotation,this);
|
||||
|
|
@ -178,35 +171,41 @@ BOOL LLPanelObject::postBuild()
|
|||
mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z");
|
||||
childSetCommitCallback("Rot Z",onCommitRotation,this);
|
||||
|
||||
// Copy/paste pos
|
||||
mBtnCopyPos = getChild<LLButton>("copypos");
|
||||
mBtnCopyPos->setCommitCallback( boost::bind(&LLPanelObject::onCopyPos, this, _2 ));
|
||||
mBtnPastePos = getChild<LLButton>("pastepos");
|
||||
mBtnPastePos->setCommitCallback( boost::bind(&LLPanelObject::onPastePos, this, _2 ));
|
||||
mBtnPastePosClip = getChild<LLButton>("pasteposclip");
|
||||
mBtnPastePosClip->setCommitCallback( boost::bind(&LLPanelObject::onPastePosClip, this, _2 ));
|
||||
// Copy/paste pos
|
||||
mBtnCopyPos = getChild<LLButton>("copy_pos_btn");
|
||||
mBtnCopyPos->setCommitCallback(boost::bind(&LLPanelObject::onCopyPos, this));
|
||||
mBtnPastePos = getChild<LLButton>("paste_pos_btn");
|
||||
mBtnPastePos->setCommitCallback(boost::bind(&LLPanelObject::onPastePos, this));
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnPastePosClip = getChild<LLButton>("paste_pos_clip_btn");
|
||||
mBtnPastePosClip->setCommitCallback(boost::bind(&LLPanelObject::onPastePosClip, this));
|
||||
// </FS>
|
||||
|
||||
// Copy/paste size
|
||||
mBtnCopySize = getChild<LLButton>("copysize");
|
||||
mBtnCopySize->setCommitCallback( boost::bind(&LLPanelObject::onCopySize, this, _2 ));
|
||||
mBtnPasteSize = getChild<LLButton>("pastesize");
|
||||
mBtnPasteSize->setCommitCallback( boost::bind(&LLPanelObject::onPasteSize, this, _2 ));
|
||||
mBtnPasteSizeClip = getChild<LLButton>("pastesizeclip");
|
||||
mBtnPasteSizeClip->setCommitCallback( boost::bind(&LLPanelObject::onPasteSizeClip, this, _2 ));
|
||||
// Copy/paste size
|
||||
mBtnCopySize = getChild<LLButton>("copy_size_btn");
|
||||
mBtnCopySize->setCommitCallback(boost::bind(&LLPanelObject::onCopySize, this));
|
||||
mBtnPasteSize = getChild<LLButton>("paste_size_btn");
|
||||
mBtnPasteSize->setCommitCallback(boost::bind(&LLPanelObject::onPasteSize, this));
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnPasteSizeClip = getChild<LLButton>("paste_size_clip_btn");
|
||||
mBtnPasteSizeClip->setCommitCallback(boost::bind(&LLPanelObject::onPasteSizeClip, this));
|
||||
// </FS>
|
||||
|
||||
// Copy/paste rot
|
||||
mBtnCopyRot = getChild<LLButton>("copyrot");
|
||||
mBtnCopyRot->setCommitCallback( boost::bind(&LLPanelObject::onCopyRot, this, _2 ));
|
||||
mBtnPasteRot = getChild<LLButton>("pasterot");
|
||||
mBtnPasteRot->setCommitCallback( boost::bind(&LLPanelObject::onPasteRot, this, _2 ));
|
||||
mBtnPasteRotClip = getChild<LLButton>("pasterotclip");
|
||||
mBtnPasteRotClip->setCommitCallback( boost::bind(&LLPanelObject::onPasteRotClip, this, _2 ));
|
||||
// Copy/paste rot
|
||||
mBtnCopyRot = getChild<LLButton>("copy_rot_btn");
|
||||
mBtnCopyRot->setCommitCallback(boost::bind(&LLPanelObject::onCopyRot, this));
|
||||
mBtnPasteRot = getChild<LLButton>("paste_rot_btn");
|
||||
mBtnPasteRot->setCommitCallback(boost::bind(&LLPanelObject::onPasteRot, this));;
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnPasteRotClip = getChild<LLButton>("paste_rot_clip_btn");
|
||||
mBtnPasteRotClip->setCommitCallback(boost::bind(&LLPanelObject::onPasteRotClip, this));
|
||||
// </FS>
|
||||
|
||||
// Copy/paste obj prams
|
||||
mBtnCopyParams = getChild<LLButton>("copyparams");
|
||||
mBtnCopyParams->setCommitCallback( boost::bind(&LLPanelObject::onCopyParams, this, _2 ));
|
||||
mBtnPasteParams = getChild<LLButton>("pasteparams");
|
||||
mBtnPasteParams->setCommitCallback( boost::bind(&LLPanelObject::onPasteParams, this, _2 ));
|
||||
// Copy/paste obj prams
|
||||
mBtnCopyParams = getChild<LLButton>("copy_params_btn");
|
||||
mBtnCopyParams->setCommitCallback(boost::bind(&LLPanelObject::onCopyParams, this));
|
||||
mBtnPasteParams = getChild<LLButton>("paste_params_btn");
|
||||
mBtnPasteParams->setCommitCallback(boost::bind(&LLPanelObject::onPasteParams, this));
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
|
|
@ -214,6 +213,8 @@ BOOL LLPanelObject::postBuild()
|
|||
mComboBaseType = getChild<LLComboBox>("comboBaseType");
|
||||
childSetCommitCallback("comboBaseType",onCommitParametric,this);
|
||||
|
||||
//mMenuClipboardParams = getChild<LLMenuButton>("clipboard_obj_params_btn"); // <FS> Extended copy & paste buttons
|
||||
|
||||
// Cut
|
||||
mLabelCut = getChild<LLTextBox>("text cut");
|
||||
mSpinCutBegin = getChild<LLSpinCtrl>("cut begin");
|
||||
|
|
@ -353,15 +354,15 @@ LLPanelObject::LLPanelObject()
|
|||
mSelectedType(MI_BOX),
|
||||
mSculptTextureRevert(LLUUID::null),
|
||||
mSculptTypeRevert(0),
|
||||
mSizeChanged(FALSE),
|
||||
mHasPosClipboard(FALSE),
|
||||
mHasSizeClipboard(FALSE),
|
||||
mHasRotClipboard(FALSE),
|
||||
mHasParamsClipboard(FALSE),
|
||||
mHasFlexiParam(FALSE),
|
||||
mHasSculptParam(FALSE),
|
||||
mHasLightParam(FALSE)
|
||||
mHasClipboardPos(false),
|
||||
mHasClipboardSize(false),
|
||||
mHasClipboardRot(false),
|
||||
mSizeChanged(FALSE)
|
||||
{
|
||||
// <FS> Extended copy & paste buttons
|
||||
//mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2));
|
||||
//mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2));
|
||||
// </FS>
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -534,11 +535,16 @@ void LLPanelObject::getState( )
|
|||
calcp->clearVar(LLCalc::Z_POS);
|
||||
}
|
||||
|
||||
|
||||
//mMenuClipboardPos->setEnabled(enable_move); // <FS> Extended copy & paste buttons
|
||||
mLabelPosition->setEnabled( enable_move );
|
||||
mCtrlPosX->setEnabled(enable_move);
|
||||
mCtrlPosY->setEnabled(enable_move);
|
||||
mCtrlPosZ->setEnabled(enable_move);
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnCopyPos->setEnabled(enable_move);
|
||||
mBtnPastePos->setEnabled(enable_move && mHasClipboardPos);
|
||||
mBtnPastePosClip->setEnabled( enable_move );
|
||||
// </FS>
|
||||
|
||||
if (enable_scale)
|
||||
{
|
||||
|
|
@ -560,10 +566,16 @@ void LLPanelObject::getState( )
|
|||
calcp->setVar(LLCalc::Z_SCALE, 0.f);
|
||||
}
|
||||
|
||||
//mMenuClipboardSize->setEnabled(enable_scale); // <FS> Extended copy & paste buttons
|
||||
mLabelSize->setEnabled( enable_scale );
|
||||
mCtrlScaleX->setEnabled( enable_scale );
|
||||
mCtrlScaleY->setEnabled( enable_scale );
|
||||
mCtrlScaleZ->setEnabled( enable_scale );
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnCopySize->setEnabled( enable_scale );
|
||||
mBtnPasteSize->setEnabled( enable_scale && mHasClipboardSize );
|
||||
mBtnPasteSizeClip->setEnabled( enable_scale );
|
||||
// </FS>
|
||||
|
||||
LLQuaternion object_rot = objectp->getRotationEdit();
|
||||
object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ]));
|
||||
|
|
@ -591,22 +603,19 @@ void LLPanelObject::getState( )
|
|||
calcp->clearVar(LLCalc::Z_ROT);
|
||||
}
|
||||
|
||||
//mMenuClipboardRot->setEnabled(enable_rotate); // <FS> Extended copy & paste buttons
|
||||
mLabelRotation->setEnabled( enable_rotate );
|
||||
mCtrlRotX->setEnabled( enable_rotate );
|
||||
mCtrlRotY->setEnabled( enable_rotate );
|
||||
mCtrlRotZ->setEnabled( enable_rotate );
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnCopyRot->setEnabled( enable_rotate );
|
||||
mBtnPasteRot->setEnabled( enable_rotate && mHasClipboardRot );
|
||||
mBtnPasteRotClip->setEnabled( enable_rotate );
|
||||
|
||||
mBtnCopyPos->setEnabled(enable_move);
|
||||
mBtnPastePos->setEnabled(enable_move);
|
||||
mBtnPastePosClip->setEnabled(enable_move);
|
||||
mBtnCopySize->setEnabled( enable_scale );
|
||||
mBtnPasteSize->setEnabled( enable_scale );
|
||||
mBtnPasteSizeClip->setEnabled( enable_scale );
|
||||
mBtnCopyRot->setEnabled( enable_rotate );
|
||||
mBtnPasteRot->setEnabled( enable_rotate );
|
||||
mBtnPasteRotClip->setEnabled( enable_rotate );
|
||||
mBtnCopyParams->setEnabled( single_volume && objectp->permModify() );
|
||||
mBtnPasteParams->setEnabled( single_volume && objectp->permModify() );
|
||||
mBtnCopyParams->setEnabled( single_volume && enable_modify );
|
||||
mBtnPasteParams->setEnabled( single_volume && enable_modify && !mClipboardParams.emptyMap() && (mClipboardParams["volume_params"] || mClipboardParams["sculpt"]));
|
||||
// </FS>
|
||||
|
||||
LLUUID owner_id;
|
||||
std::string owner_name;
|
||||
|
|
@ -830,7 +839,7 @@ void LLPanelObject::getState( )
|
|||
//Working33 -->
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL;
|
||||
selected_item = MI_BOX;
|
||||
}
|
||||
|
||||
|
|
@ -1198,6 +1207,7 @@ void LLPanelObject::getState( )
|
|||
|
||||
// Update field enablement
|
||||
mComboBaseType ->setEnabled( enabled );
|
||||
//mMenuClipboardParams->setEnabled(enabled); // <FS> Extended copy & paste buttons
|
||||
|
||||
mLabelCut ->setEnabled( enabled );
|
||||
mSpinCutBegin ->setEnabled( enabled );
|
||||
|
|
@ -1374,6 +1384,8 @@ void LLPanelObject::getState( )
|
|||
}
|
||||
|
||||
mComboBaseType->setEnabled(!isMesh);
|
||||
//mMenuClipboardParams->setEnabled(!isMesh); // <FS> Extended copy & paste buttons
|
||||
|
||||
if (mCtrlSculptType)
|
||||
{
|
||||
if (sculpt_stitching == LL_SCULPT_TYPE_NONE)
|
||||
|
|
@ -1640,11 +1652,11 @@ void LLPanelObject::sendIsPhysical()
|
|||
LLSelectMgr::getInstance()->selectionUpdatePhysics(value);
|
||||
mIsPhysical = value;
|
||||
|
||||
LL_INFOS() << "update physics sent" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "update physics not changed" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1656,11 +1668,11 @@ void LLPanelObject::sendIsTemporary()
|
|||
LLSelectMgr::getInstance()->selectionUpdateTemporary(value);
|
||||
mIsTemporary = value;
|
||||
|
||||
LL_INFOS() << "update temporary sent" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "update temporary not changed" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1673,11 +1685,11 @@ void LLPanelObject::sendIsPhantom()
|
|||
LLSelectMgr::getInstance()->selectionUpdatePhantom(value);
|
||||
mIsPhantom = value;
|
||||
|
||||
LL_INFOS() << "update phantom sent" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "update phantom not changed" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1872,7 +1884,7 @@ void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params)
|
|||
//Working33 -->
|
||||
|
||||
default:
|
||||
LL_WARNS() << "Unknown base type " << selected_type
|
||||
LL_WARNS("FloaterTools") << "Unknown base type " << selected_type
|
||||
<< " in getVolumeParams()" << LL_ENDL;
|
||||
// assume a box
|
||||
selected_type = MI_BOX;
|
||||
|
|
@ -2244,14 +2256,16 @@ void LLPanelObject::sendPosition(BOOL btn_down)
|
|||
|
||||
LLViewerRegion* regionp = mObject->getRegion();
|
||||
|
||||
// ## Zi: Building spin controls for attachments
|
||||
if (!regionp) return;
|
||||
|
||||
// <FS:Zi> Building spin controls for attachments
|
||||
LLVector3d new_pos_global;
|
||||
|
||||
if (mObject->isAttachment())
|
||||
{
|
||||
newpos.clamp(LLVector3(-MAX_ATTACHMENT_DIST,-MAX_ATTACHMENT_DIST,-MAX_ATTACHMENT_DIST),LLVector3(MAX_ATTACHMENT_DIST,MAX_ATTACHMENT_DIST,MAX_ATTACHMENT_DIST));
|
||||
}
|
||||
// ## Zi: Building spin controls for attachments
|
||||
// </FS:Zi> Building spin controls for attachments
|
||||
else
|
||||
{
|
||||
// Clamp the Z height
|
||||
|
|
@ -2670,357 +2684,389 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata)
|
|||
self->sendSculpt();
|
||||
}
|
||||
|
||||
std::string get_vector_format_string()
|
||||
{
|
||||
S32 precision = gSavedSettings.getS32("FSBuildToolDecimalPrecision");
|
||||
return llformat("<%%.%df, %%.%df, %%.%df>", precision, precision, precision);
|
||||
}
|
||||
// <FS> Extended copy & paste buttons
|
||||
//void LLPanelObject::menuDoToSelected(const LLSD& userdata)
|
||||
//{
|
||||
// std::string command = userdata.asString();
|
||||
//
|
||||
// // paste
|
||||
// if (command == "psr_paste")
|
||||
// {
|
||||
// onPastePos();
|
||||
// onPasteSize();
|
||||
// onPasteRot();
|
||||
// }
|
||||
// else if (command == "pos_paste")
|
||||
// {
|
||||
// onPastePos();
|
||||
// }
|
||||
// else if (command == "size_paste")
|
||||
// {
|
||||
// onPasteSize();
|
||||
// }
|
||||
// else if (command == "rot_paste")
|
||||
// {
|
||||
// onPasteRot();
|
||||
// }
|
||||
// else if (command == "params_paste")
|
||||
// {
|
||||
// onPasteParams();
|
||||
// }
|
||||
// // copy
|
||||
// else if (command == "psr_copy")
|
||||
// {
|
||||
// onCopyPos();
|
||||
// onCopySize();
|
||||
// onCopyRot();
|
||||
// }
|
||||
// else if (command == "pos_copy")
|
||||
// {
|
||||
// onCopyPos();
|
||||
// }
|
||||
// else if (command == "size_copy")
|
||||
// {
|
||||
// onCopySize();
|
||||
// }
|
||||
// else if (command == "rot_copy")
|
||||
// {
|
||||
// onCopyRot();
|
||||
// }
|
||||
// else if (command == "params_copy")
|
||||
// {
|
||||
// onCopyParams();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//bool LLPanelObject::menuEnableItem(const LLSD& userdata)
|
||||
//{
|
||||
// std::string command = userdata.asString();
|
||||
//
|
||||
// // paste options
|
||||
// if (command == "psr_paste")
|
||||
// {
|
||||
// S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
|
||||
// BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME))
|
||||
// && (selected_count == 1);
|
||||
//
|
||||
// if (!single_volume)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool enable_move;
|
||||
// bool enable_modify;
|
||||
//
|
||||
// LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
|
||||
//
|
||||
// return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot;
|
||||
// }
|
||||
// else if (command == "pos_paste")
|
||||
// {
|
||||
// // assumes that menu won't be active if there is no move permission
|
||||
// return mHasClipboardPos;
|
||||
// }
|
||||
// else if (command == "size_paste")
|
||||
// {
|
||||
// return mHasClipboardSize;
|
||||
// }
|
||||
// else if (command == "rot_paste")
|
||||
// {
|
||||
// return mHasClipboardRot;
|
||||
// }
|
||||
// else if (command == "params_paste")
|
||||
// {
|
||||
// return mHasClipboardParams;
|
||||
// }
|
||||
// // copy options
|
||||
// else if (command == "psr_copy")
|
||||
// {
|
||||
// S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
|
||||
// BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME))
|
||||
// && (selected_count == 1);
|
||||
//
|
||||
// if (!single_volume)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool enable_move;
|
||||
// bool enable_modify;
|
||||
//
|
||||
// LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
|
||||
//
|
||||
// // since we forbid seeing values we also should forbid copying them
|
||||
// return enable_move && enable_modify;
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
|
||||
void copy_vector_to_clipboard(const LLVector3& vec)
|
||||
{
|
||||
std::string stringVec = llformat(get_vector_format_string().c_str(), vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
|
||||
S32 precision = gSavedSettings.getS32("FSBuildToolDecimalPrecision");
|
||||
std::string format = llformat("<%%.%df, %%.%df, %%.%df>", precision, precision, precision);
|
||||
std::string stringVec = llformat(format.c_str(), vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
|
||||
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
|
||||
}
|
||||
// </FS>
|
||||
|
||||
void LLPanelObject::onCopyPos(const LLSD& data)
|
||||
void LLPanelObject::onCopyPos()
|
||||
{
|
||||
mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
|
||||
copy_vector_to_clipboard(mClipboardPos);
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = llformat(get_vector_format_string().c_str(), mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]);
|
||||
mBtnPastePos->setToolTip(getString("Paste Position", args));
|
||||
mHasPosClipboard = TRUE;
|
||||
mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
|
||||
|
||||
std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]);
|
||||
// <FS> Extended copy & paste buttons
|
||||
//LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
|
||||
copy_vector_to_clipboard(mClipboardPos);
|
||||
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = stringVec;
|
||||
mBtnPastePos->setToolTip(getString("paste_position", args));
|
||||
|
||||
mBtnPastePos->setEnabled(TRUE);
|
||||
// </FS>
|
||||
|
||||
mHasClipboardPos = true;
|
||||
}
|
||||
|
||||
void LLPanelObject::onCopySize(const LLSD& data)
|
||||
void LLPanelObject::onCopySize()
|
||||
{
|
||||
mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
|
||||
copy_vector_to_clipboard(mClipboardSize);
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = llformat(get_vector_format_string().c_str(), mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]);
|
||||
mBtnPasteSize->setToolTip(getString("Paste Size", args));
|
||||
mHasSizeClipboard = TRUE;
|
||||
mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
|
||||
|
||||
std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]);
|
||||
// <FS> Extended copy & paste buttons
|
||||
//LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
|
||||
copy_vector_to_clipboard(mClipboardSize);
|
||||
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = stringVec;
|
||||
mBtnPasteSize->setToolTip(getString("paste_size", args));
|
||||
|
||||
mBtnPasteSize->setEnabled(TRUE);
|
||||
// </FS>
|
||||
|
||||
mHasClipboardSize = true;
|
||||
}
|
||||
|
||||
void LLPanelObject::onCopyRot(const LLSD& data)
|
||||
void LLPanelObject::onCopyRot()
|
||||
{
|
||||
mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
|
||||
copy_vector_to_clipboard(mClipboardRot);
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = llformat(get_vector_format_string().c_str(), mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]);
|
||||
mBtnPasteRot->setToolTip(getString("Paste Rotation", args));
|
||||
mHasRotClipboard = TRUE;
|
||||
mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
|
||||
|
||||
std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]);
|
||||
// <FS> Extended copy & paste buttons
|
||||
//LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
|
||||
copy_vector_to_clipboard(mClipboardRot);
|
||||
|
||||
LLStringUtil::format_map_t args;
|
||||
args["VALUE"] = stringVec;
|
||||
mBtnPasteRot->setToolTip(getString("paste_rotation", args));
|
||||
|
||||
mBtnPasteRot->setEnabled(TRUE);
|
||||
// </FS>
|
||||
|
||||
mHasClipboardRot = true;
|
||||
}
|
||||
|
||||
|
||||
void LLPanelObject::onPastePos(const LLSD& data)
|
||||
void LLPanelObject::onPastePos()
|
||||
{
|
||||
if(!mHasPosClipboard) return;
|
||||
if (!mHasClipboardPos) return;
|
||||
if (mObject.isNull()) return;
|
||||
|
||||
LLViewerRegion* regionp = mObject->getRegion();
|
||||
if (!regionp) return;
|
||||
|
||||
//clamp pos on non-attachments, just keep the prims on the sim
|
||||
if (!mObject->isAttachment())
|
||||
{
|
||||
// <FS:CR> Aurora Sim
|
||||
//mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, 256.f);
|
||||
//mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, 256.f);
|
||||
mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, regionp->getWidth());
|
||||
mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, regionp->getWidth());
|
||||
// </FS:CR> Aurora Sim
|
||||
//height will get properly clammed by sendPosition
|
||||
}
|
||||
// Clamp pos on non-attachments, just keep the prims within the region
|
||||
if (!mObject->isAttachment())
|
||||
{
|
||||
F32 max_width = regionp->getWidth(); // meters
|
||||
mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, max_width);
|
||||
mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, max_width);
|
||||
//height will get properly clammed by sendPosition
|
||||
}
|
||||
|
||||
mCtrlPosX->set( mClipboardPos.mV[VX] );
|
||||
mCtrlPosY->set( mClipboardPos.mV[VY] );
|
||||
mCtrlPosZ->set( mClipboardPos.mV[VZ] );
|
||||
mCtrlPosX->set( mClipboardPos.mV[VX] );
|
||||
mCtrlPosY->set( mClipboardPos.mV[VY] );
|
||||
mCtrlPosZ->set( mClipboardPos.mV[VZ] );
|
||||
|
||||
LLCalc* calcp = LLCalc::getInstance();
|
||||
calcp->setVar(LLCalc::X_POS, mClipboardPos.mV[VX]);
|
||||
calcp->setVar(LLCalc::Y_POS, mClipboardPos.mV[VY]);
|
||||
calcp->setVar(LLCalc::Z_POS, mClipboardPos.mV[VZ]);
|
||||
|
||||
sendPosition(FALSE);
|
||||
sendPosition(FALSE);
|
||||
}
|
||||
|
||||
void LLPanelObject::onPasteSize(const LLSD& data)
|
||||
void LLPanelObject::onPasteSize()
|
||||
{
|
||||
if(!mHasSizeClipboard) return;
|
||||
// <AW: opensim-limits>
|
||||
// mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, llpanelobject_max_prim_scale());
|
||||
// mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, llpanelobject_max_prim_scale());
|
||||
// mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, llpanelobject_max_prim_scale());
|
||||
mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], mMinScale, llpanelobject_max_prim_scale());
|
||||
mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], mMinScale, llpanelobject_max_prim_scale());
|
||||
mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], mMinScale, llpanelobject_max_prim_scale());
|
||||
// </AW: opensim-limits>
|
||||
if (!mHasClipboardSize) return;
|
||||
|
||||
mCtrlScaleX->set( mClipboardSize.mV[VX] );
|
||||
mCtrlScaleY->set( mClipboardSize.mV[VY] );
|
||||
mCtrlScaleZ->set( mClipboardSize.mV[VZ] );
|
||||
// <AW: opensim-limits>
|
||||
//mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
|
||||
//mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
|
||||
//mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
|
||||
mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], mMinScale, llpanelobject_max_prim_scale());
|
||||
mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], mMinScale, llpanelobject_max_prim_scale());
|
||||
mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], mMinScale, llpanelobject_max_prim_scale());
|
||||
// </AW: opensim-limits>
|
||||
|
||||
LLCalc* calcp = LLCalc::getInstance();
|
||||
calcp->setVar(LLCalc::X_SCALE, mClipboardSize.mV[VX]);
|
||||
calcp->setVar(LLCalc::Y_SCALE, mClipboardSize.mV[VY]);
|
||||
calcp->setVar(LLCalc::Z_SCALE, mClipboardSize.mV[VZ]);
|
||||
mCtrlScaleX->set(mClipboardSize.mV[VX]);
|
||||
mCtrlScaleY->set(mClipboardSize.mV[VY]);
|
||||
mCtrlScaleZ->set(mClipboardSize.mV[VZ]);
|
||||
|
||||
sendScale(FALSE);
|
||||
sendScale(FALSE);
|
||||
}
|
||||
|
||||
void LLPanelObject::onPasteRot(const LLSD& data)
|
||||
void LLPanelObject::onPasteRot()
|
||||
{
|
||||
if(!mHasRotClipboard) return;
|
||||
|
||||
mCtrlRotX->set( mClipboardRot.mV[VX] );
|
||||
mCtrlRotY->set( mClipboardRot.mV[VY] );
|
||||
mCtrlRotZ->set( mClipboardRot.mV[VZ] );
|
||||
if (!mHasClipboardRot) return;
|
||||
|
||||
LLCalc* calcp = LLCalc::getInstance();
|
||||
calcp->setVar(LLCalc::X_ROT, mClipboardRot.mV[VX]);
|
||||
calcp->setVar(LLCalc::Y_ROT, mClipboardRot.mV[VY]);
|
||||
calcp->setVar(LLCalc::Z_ROT, mClipboardRot.mV[VZ]);
|
||||
mCtrlRotX->set(mClipboardRot.mV[VX]);
|
||||
mCtrlRotY->set(mClipboardRot.mV[VY]);
|
||||
mCtrlRotZ->set(mClipboardRot.mV[VZ]);
|
||||
|
||||
sendRotation(FALSE);
|
||||
sendRotation(FALSE);
|
||||
}
|
||||
|
||||
//Paste from clip board
|
||||
BOOL get_vector_from_clipboard(LLVector3* value)
|
||||
void LLPanelObject::onCopyParams()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp || objectp->isMesh())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mClipboardParams.clear();
|
||||
|
||||
// Parametrics
|
||||
LLVolumeParams params;
|
||||
getVolumeParams(params);
|
||||
mClipboardParams["volume_params"] = params.asLLSD();
|
||||
|
||||
// Sculpted Prim
|
||||
if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
|
||||
{
|
||||
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
|
||||
|
||||
LLUUID texture_id = sculpt_params->getSculptTexture();
|
||||
if (get_can_copy_texture(texture_id))
|
||||
{
|
||||
LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL;
|
||||
mClipboardParams["sculpt"]["id"] = texture_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE);
|
||||
}
|
||||
|
||||
mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType();
|
||||
}
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
mBtnPasteParams->setEnabled(!mClipboardParams.emptyMap() && (mClipboardParams["volume_params"] || mClipboardParams["sculpt"]));
|
||||
}
|
||||
|
||||
void LLPanelObject::onPasteParams()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Sculpted Prim
|
||||
if (mClipboardParams.has("sculpt"))
|
||||
{
|
||||
LLSculptParams sculpt_params;
|
||||
LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID();
|
||||
U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger();
|
||||
sculpt_params.setSculptTexture(sculpt_id, sculpt_type);
|
||||
objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
|
||||
if (sculpt_params)
|
||||
{
|
||||
objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// volume params
|
||||
// make sure updateVolume() won't affect flexible
|
||||
if (mClipboardParams.has("volume_params"))
|
||||
{
|
||||
LLVolumeParams params;
|
||||
params.fromLLSD(mClipboardParams["volume_params"]);
|
||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||
if (volobjp->isFlexible())
|
||||
{
|
||||
if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE)
|
||||
{
|
||||
params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE);
|
||||
}
|
||||
}
|
||||
else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
|
||||
{
|
||||
params.getPathParams().setCurveType(LL_PCODE_PATH_LINE);
|
||||
}
|
||||
|
||||
objectp->updateVolume(params);
|
||||
}
|
||||
}
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
bool get_vector_from_clipboard(LLVector3* value)
|
||||
{
|
||||
LLWString temp_string;
|
||||
LLView::getWindow()->pasteTextFromClipboard(temp_string);
|
||||
const std::string stringVec = wstring_to_utf8str(temp_string);
|
||||
|
||||
if(stringVec.empty() || value == NULL) return FALSE;
|
||||
if (stringVec.empty() || !value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVector3 vec;
|
||||
S32 count = sscanf( stringVec.c_str(), "<%f, %f, %f>", vec.mV + 0, vec.mV + 1, vec.mV + 2 );
|
||||
if( 3 == count )
|
||||
S32 count = sscanf(stringVec.c_str(), "<%f, %f, %f>", vec.mV + 0, vec.mV + 1, vec.mV + 2);
|
||||
if (count == 3)
|
||||
{
|
||||
value->setVec( vec );
|
||||
return TRUE;
|
||||
value->setVec(vec);
|
||||
return true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
void LLPanelObject::onPastePosClip(const LLSD& data)
|
||||
|
||||
void LLPanelObject::onPastePosClip()
|
||||
{
|
||||
if(get_vector_from_clipboard(&mClipboardPos))
|
||||
if (get_vector_from_clipboard(&mClipboardPos))
|
||||
{
|
||||
mHasPosClipboard = TRUE;
|
||||
onPastePos(data);
|
||||
mHasClipboardPos = true;
|
||||
onPastePos();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Couldn't get position vector from clipboard" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "Couldn't get position vector from clipboard" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
void LLPanelObject::onPasteSizeClip(const LLSD& data)
|
||||
|
||||
void LLPanelObject::onPasteSizeClip()
|
||||
{
|
||||
if(get_vector_from_clipboard(&mClipboardSize))
|
||||
if (get_vector_from_clipboard(&mClipboardSize))
|
||||
{
|
||||
mHasSizeClipboard = TRUE;
|
||||
onPasteSize(data);
|
||||
mHasClipboardSize = true;
|
||||
onPasteSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Couldn't get size vector from clipboard" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "Couldn't get size vector from clipboard" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
void LLPanelObject::onPasteRotClip(const LLSD& data)
|
||||
|
||||
void LLPanelObject::onPasteRotClip()
|
||||
{
|
||||
if(get_vector_from_clipboard(&mClipboardRot))
|
||||
if (get_vector_from_clipboard(&mClipboardRot))
|
||||
{
|
||||
mHasRotClipboard = TRUE;
|
||||
onPasteRot(data);
|
||||
mHasClipboardRot = true;
|
||||
onPasteRot();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Couldn't get rotation vector from clipboard" << LL_ENDL;
|
||||
LL_INFOS("FloaterTools") << "Couldn't get rotation vector from clipboard" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLPanelObject::onCopyParams(const LLSD& data)
|
||||
{
|
||||
getVolumeParams(mClipboardVolumeParams);
|
||||
mHasParamsClipboard = TRUE;
|
||||
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp)
|
||||
return;
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
|
||||
mHasFlexiParam = FALSE;
|
||||
if(volobjp && volobjp->isFlexible())
|
||||
{
|
||||
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
||||
if (attributes)
|
||||
{
|
||||
mParamsClipboard["lod"] = attributes->getSimulateLOD();
|
||||
mParamsClipboard["gav"] = attributes->getGravity();
|
||||
mParamsClipboard["ten"] = attributes->getTension();
|
||||
mParamsClipboard["fri"] = attributes->getAirFriction();
|
||||
mParamsClipboard["sen"] = attributes->getWindSensitivity();
|
||||
LLVector3 force = attributes->getUserForce();
|
||||
mParamsClipboard["forx"] = force.mV[0];
|
||||
mParamsClipboard["fory"] = force.mV[1];
|
||||
mParamsClipboard["forz"] = force.mV[2];
|
||||
mHasFlexiParam = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
|
||||
{
|
||||
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
|
||||
|
||||
LLUUID image_id = sculpt_params->getSculptTexture();
|
||||
BOOL allow_texture = FALSE;
|
||||
if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID())
|
||||
|| image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" ))
|
||||
|| image_id == LLUUID(gSavedSettings.getString( "UIImgWhiteUUID" ))
|
||||
|| image_id == LLUUID(gSavedSettings.getString( "UIImgInvisibleUUID" ))
|
||||
|| image_id == LLUUID(SCULPT_DEFAULT_TEXTURE)
|
||||
)
|
||||
allow_texture = TRUE;
|
||||
else
|
||||
{
|
||||
LLUUID inventory_item_id;
|
||||
LLViewerInventoryCategory::cat_array_t cats;
|
||||
LLViewerInventoryItem::item_array_t items;
|
||||
LLAssetIDMatches asset_id_matches(image_id);
|
||||
gInventory.collectDescendentsIf(LLUUID::null,
|
||||
cats,
|
||||
items,
|
||||
LLInventoryModel::INCLUDE_TRASH,
|
||||
asset_id_matches);
|
||||
|
||||
if (items.size())
|
||||
{
|
||||
// search for copyable version first
|
||||
for (S32 i = 0; i < items.size(); i++)
|
||||
{
|
||||
LLInventoryItem* itemp = items[i];
|
||||
LLPermissions item_permissions = itemp->getPermissions();
|
||||
if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
|
||||
{
|
||||
inventory_item_id = itemp->getUUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inventory_item_id.notNull())
|
||||
{
|
||||
LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
|
||||
if (itemp)
|
||||
{
|
||||
LLPermissions perm = itemp->getPermissions();
|
||||
if ( (perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED )
|
||||
allow_texture = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allow_texture)
|
||||
mParamsClipboard["sculptid"] = image_id;
|
||||
else
|
||||
mParamsClipboard["sculptid"] = LLUUID(SCULPT_DEFAULT_TEXTURE);
|
||||
|
||||
mParamsClipboard["sculpt_type"] = sculpt_params->getSculptType();
|
||||
mHasSculptParam = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mHasSculptParam = FALSE;
|
||||
}
|
||||
|
||||
if (volobjp && volobjp->getIsLight())
|
||||
{
|
||||
mParamsClipboard["Light Intensity"] = volobjp->getLightIntensity();
|
||||
mParamsClipboard["Light Radius"] = volobjp->getLightRadius();
|
||||
mParamsClipboard["Light Falloff"] = volobjp->getLightFalloff();
|
||||
LLColor3 color = volobjp->getLightSRGBColor();
|
||||
mParamsClipboard["r"] = color.mV[0];
|
||||
mParamsClipboard["g"] = color.mV[1];
|
||||
mParamsClipboard["b"] = color.mV[2];
|
||||
mHasLightParam = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mHasLightParam = FALSE;
|
||||
}
|
||||
|
||||
mParamsClipboard["physics_shape"] = objectp->getPhysicsShapeType();
|
||||
}
|
||||
|
||||
void LLPanelObject::onPasteParams(const LLSD& data)
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp)
|
||||
return;
|
||||
|
||||
if (mHasFlexiParam && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
||||
if (attributes)
|
||||
{
|
||||
LLFlexibleObjectData new_attributes;
|
||||
new_attributes = *attributes;
|
||||
|
||||
new_attributes.setSimulateLOD(mParamsClipboard["lod"].asInteger());
|
||||
new_attributes.setGravity(mParamsClipboard["gav"].asReal());
|
||||
new_attributes.setTension(mParamsClipboard["ten"].asReal());
|
||||
new_attributes.setAirFriction(mParamsClipboard["fri"].asReal());
|
||||
new_attributes.setWindSensitivity(mParamsClipboard["sen"].asReal());
|
||||
F32 fx = (F32)mParamsClipboard["forx"].asReal();
|
||||
F32 fy = (F32)mParamsClipboard["fory"].asReal();
|
||||
F32 fz = (F32)mParamsClipboard["forz"].asReal();
|
||||
LLVector3 force(fx,fy,fz);
|
||||
new_attributes.setUserForce(force);
|
||||
objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (mHasSculptParam)
|
||||
{
|
||||
LLSculptParams sculpt_params;
|
||||
|
||||
if (mParamsClipboard.has("sculptid"))
|
||||
sculpt_params.setSculptTexture(mParamsClipboard["sculptid"].asUUID(), (U8)mParamsClipboard["sculpt_type"].asInteger());
|
||||
|
||||
objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
|
||||
if (sculpt_params)
|
||||
objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE);
|
||||
}
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
|
||||
if (volobjp && mHasLightParam)
|
||||
{
|
||||
volobjp->setIsLight(TRUE);
|
||||
volobjp->setLightIntensity((F32)mParamsClipboard["Light Intensity"].asReal());
|
||||
volobjp->setLightRadius((F32)mParamsClipboard["Light Radius"].asReal());
|
||||
volobjp->setLightFalloff((F32)mParamsClipboard["Light Falloff"].asReal());
|
||||
F32 r = (F32)mParamsClipboard["r"].asReal();
|
||||
F32 g = (F32)mParamsClipboard["g"].asReal();
|
||||
F32 b = (F32)mParamsClipboard["b"].asReal();
|
||||
volobjp->setLightSRGBColor(LLColor3(r,g,b));
|
||||
}
|
||||
|
||||
if (mParamsClipboard.has("physics_shape"))
|
||||
{
|
||||
objectp->setPhysicsShapeType((U8)mParamsClipboard["physics_shape"].asInteger());
|
||||
}
|
||||
|
||||
if(mHasParamsClipboard)
|
||||
objectp->updateVolume(mClipboardVolumeParams);
|
||||
}
|
||||
// </FS>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class LLCheckBoxCtrl;
|
|||
class LLTextBox;
|
||||
class LLUICtrl;
|
||||
class LLButton;
|
||||
class LLMenuButton;
|
||||
class LLViewerObject;
|
||||
class LLComboBox;
|
||||
class LLColorSwatchCtrl;
|
||||
|
|
@ -70,17 +71,20 @@ public:
|
|||
//<FS:Beq> FIRE-21445 - Display specific LOD
|
||||
void onCommitLOD();
|
||||
//</FS:Beq>
|
||||
void onCopyPos( const LLSD& data);
|
||||
void onPastePos( const LLSD& data);
|
||||
void onPastePosClip( const LLSD& data);
|
||||
void onCopySize( const LLSD& data);
|
||||
void onPasteSize( const LLSD& data);
|
||||
void onPasteSizeClip( const LLSD& data);
|
||||
void onCopyRot( const LLSD& data);
|
||||
void onPasteRot( const LLSD& data);
|
||||
void onPasteRotClip( const LLSD& data);
|
||||
void onCopyParams( const LLSD& data);
|
||||
void onPasteParams( const LLSD& data);
|
||||
|
||||
void onCopyPos();
|
||||
void onPastePos();
|
||||
void onCopySize();
|
||||
void onPasteSize();
|
||||
void onCopyRot();
|
||||
void onPasteRot();
|
||||
void onCopyParams();
|
||||
void onPasteParams();
|
||||
// <FS> Extended copy & paste buttons
|
||||
void onPastePosClip();
|
||||
void onPasteSizeClip();
|
||||
void onPasteRotClip();
|
||||
// </FS>
|
||||
|
||||
static void onCommitParametric(LLUICtrl* ctrl, void* userdata);
|
||||
|
||||
|
|
@ -91,6 +95,11 @@ public:
|
|||
BOOL onDropSculpt(LLInventoryItem* item);
|
||||
static void onCommitSculptType( LLUICtrl *ctrl, void* userdata);
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//void menuDoToSelected(const LLSD& userdata);
|
||||
//bool menuEnableItem(const LLSD& userdata);
|
||||
// </FS>
|
||||
|
||||
protected:
|
||||
void getState();
|
||||
//<FS:Beq> FIRE-21445 + Mesh Info in object panel
|
||||
|
|
@ -111,28 +120,15 @@ protected:
|
|||
void getVolumeParams(LLVolumeParams& volume_params);
|
||||
|
||||
protected:
|
||||
|
||||
LLVector3 mClipboardPos;
|
||||
LLVector3 mClipboardSize;
|
||||
LLVector3 mClipboardRot;
|
||||
|
||||
BOOL mHasPosClipboard;
|
||||
BOOL mHasSizeClipboard;
|
||||
BOOL mHasRotClipboard;
|
||||
|
||||
LLSD mParamsClipboard;
|
||||
LLVolumeParams mClipboardVolumeParams;
|
||||
BOOL mHasParamsClipboard;
|
||||
BOOL mHasFlexiParam;
|
||||
BOOL mHasSculptParam;
|
||||
BOOL mHasLightParam;
|
||||
|
||||
S32 mComboMaterialItemCount;
|
||||
|
||||
LLComboBox* mComboMaterial;
|
||||
|
||||
// Per-object options
|
||||
LLComboBox* mComboBaseType;
|
||||
|
||||
//LLMenuButton* mMenuClipboardParams; // <FS> Extended copy & paste buttons
|
||||
|
||||
LLComboBox* mComboLOD;
|
||||
|
||||
LLTextBox* mLabelCut;
|
||||
|
|
@ -181,36 +177,39 @@ protected:
|
|||
LLTextBox* mLabelRevolutions;
|
||||
LLSpinCtrl* mSpinRevolutions;
|
||||
|
||||
//LLMenuButton* mMenuClipboardPos; // <FS> Extended copy & paste buttons
|
||||
LLTextBox* mLabelPosition;
|
||||
LLSpinCtrl* mCtrlPosX;
|
||||
LLSpinCtrl* mCtrlPosY;
|
||||
LLSpinCtrl* mCtrlPosZ;
|
||||
|
||||
//LLMenuButton* mMenuClipboardSize; // <FS> Extended copy & paste buttons
|
||||
LLTextBox* mLabelSize;
|
||||
LLSpinCtrl* mCtrlScaleX;
|
||||
LLSpinCtrl* mCtrlScaleY;
|
||||
LLSpinCtrl* mCtrlScaleZ;
|
||||
BOOL mSizeChanged;
|
||||
|
||||
//LLMenuButton* mMenuClipboardRot; // <FS> Extended copy & paste buttons
|
||||
LLTextBox* mLabelRotation;
|
||||
LLSpinCtrl* mCtrlRotX;
|
||||
LLSpinCtrl* mCtrlRotY;
|
||||
LLSpinCtrl* mCtrlRotZ;
|
||||
|
||||
LLButton *mBtnCopyPos;
|
||||
LLButton *mBtnPastePos;
|
||||
LLButton *mBtnPastePosClip;
|
||||
|
||||
LLButton *mBtnCopySize;
|
||||
LLButton *mBtnPasteSize;
|
||||
LLButton *mBtnPasteSizeClip;
|
||||
|
||||
LLButton *mBtnCopyRot;
|
||||
LLButton *mBtnPasteRot;
|
||||
LLButton *mBtnPasteRotClip;
|
||||
LLButton *mBtnCopyPos;
|
||||
LLButton *mBtnPastePos;
|
||||
LLButton *mBtnCopySize;
|
||||
LLButton *mBtnPasteSize;
|
||||
LLButton *mBtnCopyRot;
|
||||
LLButton *mBtnPasteRot;
|
||||
LLButton *mBtnCopyParams;
|
||||
LLButton *mBtnPasteParams;
|
||||
|
||||
LLButton* mBtnCopyParams;
|
||||
LLButton* mBtnPasteParams;
|
||||
// <FS> Extended copy & paste buttons
|
||||
LLButton *mBtnPastePosClip;
|
||||
LLButton *mBtnPasteSizeClip;
|
||||
LLButton *mBtnPasteRotClip;
|
||||
// </FS>
|
||||
|
||||
LLCheckBoxCtrl *mCheckLock;
|
||||
LLCheckBoxCtrl *mCheckPhysics;
|
||||
|
|
@ -222,7 +221,7 @@ protected:
|
|||
LLComboBox *mCtrlSculptType;
|
||||
LLCheckBoxCtrl *mCtrlSculptMirror;
|
||||
LLCheckBoxCtrl *mCtrlSculptInvert;
|
||||
|
||||
|
||||
LLVector3 mCurEulerDegrees; // to avoid sending rotation when not changed
|
||||
BOOL mIsPhysical; // to avoid sending "physical" when not changed
|
||||
BOOL mIsTemporary; // to avoid sending "temporary" when not changed
|
||||
|
|
@ -232,6 +231,15 @@ protected:
|
|||
LLUUID mSculptTextureRevert; // so we can revert the sculpt texture on cancel
|
||||
U8 mSculptTypeRevert; // so we can revert the sculpt type on cancel
|
||||
|
||||
LLVector3 mClipboardPos;
|
||||
LLVector3 mClipboardSize;
|
||||
LLVector3 mClipboardRot;
|
||||
LLSD mClipboardParams;
|
||||
|
||||
bool mHasClipboardPos;
|
||||
bool mHasClipboardSize;
|
||||
bool mHasClipboardRot;
|
||||
|
||||
LLPointer<LLViewerObject> mObject;
|
||||
LLPointer<LLViewerObject> mRootObject;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -710,7 +710,18 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const
|
|||
if (cat)
|
||||
{
|
||||
// <FS:Zi> FIRE-24142 - Show number of elements in object inventory
|
||||
//mDisplayName.assign(cat->getName());
|
||||
//std::string name = cat->getName();
|
||||
//if (mChildren.size() > 0)
|
||||
//{
|
||||
// // Add item count
|
||||
// // Normally we would be using getLabelSuffix for this
|
||||
// // but object's inventory just uses displaynames
|
||||
// LLStringUtil::format_map_t args;
|
||||
// args["[ITEMS_COUNT]"] = llformat("%d", mChildren.size());
|
||||
|
||||
// name.append(" " + LLTrans::getString("InventoryItemsCount", args));
|
||||
//}
|
||||
//mDisplayName.assign(name);
|
||||
if (cat->getParentUUID().isNull() && cat->getName() == "Contents")
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
|
||||
|
|
@ -1706,6 +1717,8 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root
|
|||
{
|
||||
createViewsForCategory(&contents, inventory_root, new_folder);
|
||||
}
|
||||
// Refresh for label to add item count
|
||||
new_folder->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#include "llfocusmgr.h"
|
||||
#include "llmanipscale.h"
|
||||
#include "llinventorymodel.h"
|
||||
//#include "llmenubutton.h" // <FS> Extended copy & paste buttons
|
||||
#include "llpreviewscript.h"
|
||||
#include "llresmgr.h"
|
||||
#include "llselectmgr.h"
|
||||
|
|
@ -168,6 +169,15 @@ BOOL LLPanelVolume::postBuild()
|
|||
mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution));
|
||||
}
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//mMenuClipboardFeatures = getChild<LLMenuButton>("clipboard_features_params_btn");
|
||||
//mMenuClipboardLight = getChild<LLMenuButton>("clipboard_light_params_btn");
|
||||
mBtnCopyFeatures = getChild<LLButton>("copy_features_btn");
|
||||
mBtnCopyFeatures->setCommitCallback(boost::bind(&LLPanelVolume::onFSCopyFeatures, this));
|
||||
mBtnPasteFeatures = getChild<LLButton>("paste_features_btn");
|
||||
mBtnPasteFeatures->setCommitCallback(boost::bind(&LLPanelVolume::onFSPasteFeatures, this));
|
||||
// </FS>
|
||||
|
||||
std::map<std::string, std::string> material_name_map;
|
||||
material_name_map["Stone"]= LLTrans::getString("Stone");
|
||||
material_name_map["Metal"]= LLTrans::getString("Metal");
|
||||
|
|
@ -409,7 +419,6 @@ void LLPanelVolume::getState( )
|
|||
gAgentAvatarp->updateMeshVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Flexible properties
|
||||
BOOL is_flexible = volobjp && volobjp->isFlexible();
|
||||
|
|
@ -564,6 +573,13 @@ void LLPanelVolume::getState( )
|
|||
|
||||
mObject = objectp;
|
||||
mRootObject = root_objectp;
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//mMenuClipboardFeatures->setEnabled(editable && single_volume && volobjp); // Note: physics doesn't need to be limited by single volume
|
||||
//mMenuClipboardLight->setEnabled(editable && single_volume && volobjp);
|
||||
mBtnCopyFeatures->setEnabled(editable && single_volume && volobjp);
|
||||
mBtnPasteFeatures->setEnabled(editable && single_volume && volobjp && !mClipboardParams.emptyMap() && (mClipboardParams.has("features") || mClipboardParams.has("light")));
|
||||
// </FS>
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -667,6 +683,13 @@ void LLPanelVolume::clearCtrls()
|
|||
getChildView("PhysicsViewToggle")->setEnabled(true);
|
||||
//</FS:Beq>
|
||||
mComboMaterial->setEnabled( FALSE );
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//mMenuClipboardFeatures->setEnabled(false);
|
||||
//mMenuClipboardLight->setEnabled(false);
|
||||
mBtnCopyFeatures->setEnabled(FALSE);
|
||||
mBtnPasteFeatures->setEnabled(FALSE);
|
||||
// </FS>
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -834,6 +857,304 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data)
|
|||
}
|
||||
}
|
||||
|
||||
void LLPanelVolume::onCopyFeatures()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD clipboard;
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
}
|
||||
|
||||
// Flexi Prim
|
||||
if (volobjp && volobjp->isFlexible())
|
||||
{
|
||||
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
||||
if (attributes)
|
||||
{
|
||||
clipboard["flex"]["lod"] = attributes->getSimulateLOD();
|
||||
clipboard["flex"]["gav"] = attributes->getGravity();
|
||||
clipboard["flex"]["ten"] = attributes->getTension();
|
||||
clipboard["flex"]["fri"] = attributes->getAirFriction();
|
||||
clipboard["flex"]["sen"] = attributes->getWindSensitivity();
|
||||
LLVector3 force = attributes->getUserForce();
|
||||
clipboard["flex"]["forx"] = force.mV[0];
|
||||
clipboard["flex"]["fory"] = force.mV[1];
|
||||
clipboard["flex"]["forz"] = force.mV[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Physics
|
||||
{
|
||||
clipboard["physics"]["shape"] = objectp->getPhysicsShapeType();
|
||||
clipboard["physics"]["gravity"] = objectp->getPhysicsGravity();
|
||||
clipboard["physics"]["friction"] = objectp->getPhysicsFriction();
|
||||
clipboard["physics"]["density"] = objectp->getPhysicsDensity();
|
||||
clipboard["physics"]["restitution"] = objectp->getPhysicsRestitution();
|
||||
|
||||
U8 material_code = 0;
|
||||
struct f : public LLSelectedTEGetFunctor<U8>
|
||||
{
|
||||
U8 get(LLViewerObject* object, S32 te)
|
||||
{
|
||||
return object->getMaterial();
|
||||
}
|
||||
} func;
|
||||
bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, material_code);
|
||||
// This should always be true since material should be per object.
|
||||
if (material_same)
|
||||
{
|
||||
clipboard["physics"]["material"] = material_code;
|
||||
}
|
||||
}
|
||||
|
||||
mClipboardParams["features"] = clipboard;
|
||||
}
|
||||
|
||||
void LLPanelVolume::onPasteFeatures()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp && mClipboardParams.has("features"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD &clipboard = mClipboardParams["features"];
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
}
|
||||
|
||||
// Physics
|
||||
bool is_root = objectp->isRoot();
|
||||
|
||||
// Not sure if phantom should go under physics, but doesn't fit elsewhere
|
||||
BOOL is_phantom = clipboard["is_phantom"].asBoolean() && is_root;
|
||||
LLSelectMgr::getInstance()->selectionUpdatePhantom(is_phantom);
|
||||
|
||||
BOOL is_physical = clipboard["is_physical"].asBoolean() && is_root;
|
||||
LLSelectMgr::getInstance()->selectionUpdatePhysics(is_physical);
|
||||
|
||||
if (clipboard.has("physics"))
|
||||
{
|
||||
objectp->setPhysicsShapeType((U8)clipboard["physics"]["shape"].asInteger());
|
||||
U8 cur_material = objectp->getMaterial();
|
||||
U8 material = (U8)clipboard["physics"]["material"].asInteger() | (cur_material & ~LL_MCODE_MASK);
|
||||
|
||||
objectp->setMaterial(material);
|
||||
objectp->sendMaterialUpdate();
|
||||
objectp->setPhysicsGravity(clipboard["physics"]["gravity"].asReal());
|
||||
objectp->setPhysicsFriction(clipboard["physics"]["friction"].asReal());
|
||||
objectp->setPhysicsDensity(clipboard["physics"]["density"].asReal());
|
||||
objectp->setPhysicsRestitution(clipboard["physics"]["restitution"].asReal());
|
||||
objectp->updateFlags(TRUE);
|
||||
}
|
||||
|
||||
// Flexible
|
||||
bool is_flexible = clipboard.has("flex");
|
||||
if (is_flexible && volobjp->canBeFlexible())
|
||||
{
|
||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||
BOOL update_shape = FALSE;
|
||||
|
||||
// do before setParameterEntry or it will think that it is already flexi
|
||||
update_shape = volobjp->setIsFlexible(is_flexible);
|
||||
|
||||
if (objectp->getClickAction() == CLICK_ACTION_SIT)
|
||||
{
|
||||
objectp->setClickAction(CLICK_ACTION_NONE);
|
||||
}
|
||||
|
||||
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
||||
if (attributes)
|
||||
{
|
||||
LLFlexibleObjectData new_attributes;
|
||||
new_attributes = *attributes;
|
||||
new_attributes.setSimulateLOD(clipboard["flex"]["lod"].asInteger());
|
||||
new_attributes.setGravity(clipboard["flex"]["gav"].asReal());
|
||||
new_attributes.setTension(clipboard["flex"]["ten"].asReal());
|
||||
new_attributes.setAirFriction(clipboard["flex"]["fri"].asReal());
|
||||
new_attributes.setWindSensitivity(clipboard["flex"]["sen"].asReal());
|
||||
F32 fx = (F32)clipboard["flex"]["forx"].asReal();
|
||||
F32 fy = (F32)clipboard["flex"]["fory"].asReal();
|
||||
F32 fz = (F32)clipboard["flex"]["forz"].asReal();
|
||||
LLVector3 force(fx, fy, fz);
|
||||
new_attributes.setUserForce(force);
|
||||
objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true);
|
||||
}
|
||||
|
||||
if (update_shape)
|
||||
{
|
||||
mObject->sendShapeUpdate();
|
||||
LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||
if (volobjp->setIsFlexible(false))
|
||||
{
|
||||
mObject->sendShapeUpdate();
|
||||
LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelVolume::onCopyLight()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD clipboard;
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
}
|
||||
|
||||
// Light Source
|
||||
if (volobjp && volobjp->getIsLight())
|
||||
{
|
||||
clipboard["light"]["intensity"] = volobjp->getLightIntensity();
|
||||
clipboard["light"]["radius"] = volobjp->getLightRadius();
|
||||
clipboard["light"]["falloff"] = volobjp->getLightFalloff();
|
||||
LLColor3 color = volobjp->getLightSRGBColor();
|
||||
clipboard["light"]["r"] = color.mV[0];
|
||||
clipboard["light"]["g"] = color.mV[1];
|
||||
clipboard["light"]["b"] = color.mV[2];
|
||||
|
||||
// Spotlight
|
||||
if (volobjp->isLightSpotlight())
|
||||
{
|
||||
LLUUID id = volobjp->getLightTextureID();
|
||||
if (id.notNull() && get_can_copy_texture(id))
|
||||
{
|
||||
clipboard["spot"]["id"] = id;
|
||||
LLVector3 spot_params = volobjp->getSpotLightParams();
|
||||
clipboard["spot"]["fov"] = spot_params.mV[0];
|
||||
clipboard["spot"]["focus"] = spot_params.mV[1];
|
||||
clipboard["spot"]["ambiance"] = spot_params.mV[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mClipboardParams["light"] = clipboard;
|
||||
}
|
||||
|
||||
void LLPanelVolume::onPasteLight()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp && mClipboardParams.has("light"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD &clipboard = mClipboardParams["light"];
|
||||
|
||||
LLVOVolume *volobjp = NULL;
|
||||
if (objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
|
||||
{
|
||||
volobjp = (LLVOVolume *)objectp;
|
||||
}
|
||||
|
||||
// Light Source
|
||||
if (volobjp)
|
||||
{
|
||||
if (clipboard.has("light"))
|
||||
{
|
||||
volobjp->setIsLight(TRUE);
|
||||
volobjp->setLightIntensity((F32)clipboard["light"]["intensity"].asReal());
|
||||
volobjp->setLightRadius((F32)clipboard["light"]["radius"].asReal());
|
||||
volobjp->setLightFalloff((F32)clipboard["light"]["falloff"].asReal());
|
||||
F32 r = (F32)clipboard["light"]["r"].asReal();
|
||||
F32 g = (F32)clipboard["light"]["g"].asReal();
|
||||
F32 b = (F32)clipboard["light"]["b"].asReal();
|
||||
volobjp->setLightSRGBColor(LLColor3(r, g, b));
|
||||
}
|
||||
else
|
||||
{
|
||||
volobjp->setIsLight(FALSE);
|
||||
}
|
||||
|
||||
if (clipboard.has("spot"))
|
||||
{
|
||||
volobjp->setLightTextureID(clipboard["spot"]["id"].asUUID());
|
||||
LLVector3 spot_params;
|
||||
spot_params.mV[0] = (F32)clipboard["spot"]["fov"].asReal();
|
||||
spot_params.mV[1] = (F32)clipboard["spot"]["focus"].asReal();
|
||||
spot_params.mV[2] = (F32)clipboard["spot"]["ambiance"].asReal();
|
||||
volobjp->setSpotLightParams(spot_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//void LLPanelVolume::menuDoToSelected(const LLSD& userdata)
|
||||
//{
|
||||
// std::string command = userdata.asString();
|
||||
//
|
||||
// // paste
|
||||
// if (command == "features_paste")
|
||||
// {
|
||||
// onPasteFeatures();
|
||||
// }
|
||||
// else if (command == "light_paste")
|
||||
// {
|
||||
// onPasteLight();
|
||||
// }
|
||||
// // copy
|
||||
// else if (command == "features_copy")
|
||||
// {
|
||||
// onCopyFeatures();
|
||||
// }
|
||||
// else if (command == "light_copy")
|
||||
// {
|
||||
// onCopyLight();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//bool LLPanelVolume::menuEnableItem(const LLSD& userdata)
|
||||
//{
|
||||
// std::string command = userdata.asString();
|
||||
//
|
||||
// // paste options
|
||||
// if (command == "features_paste")
|
||||
// {
|
||||
// return mClipboardParams.has("features");
|
||||
// }
|
||||
// else if (command == "light_paste")
|
||||
// {
|
||||
// return mClipboardParams.has("light");
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
void LLPanelVolume::onFSCopyFeatures()
|
||||
{
|
||||
onCopyFeatures();
|
||||
onCopyLight();
|
||||
mBtnPasteFeatures->setEnabled(!mClipboardParams.emptyMap() && (mClipboardParams.has("features") || mClipboardParams.has("light")));
|
||||
}
|
||||
|
||||
void LLPanelVolume::onFSPasteFeatures()
|
||||
{
|
||||
onPasteFeatures();
|
||||
onPasteLight();
|
||||
}
|
||||
// </FS>
|
||||
|
||||
// static
|
||||
void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class LLCheckBoxCtrl;
|
|||
class LLTextBox;
|
||||
class LLUICtrl;
|
||||
class LLButton;
|
||||
//class LLMenuButton; // <FS> Extended copy & paste buttons
|
||||
class LLViewerObject;
|
||||
class LLComboBox;
|
||||
class LLColorSwatchCtrl;
|
||||
|
|
@ -74,8 +75,19 @@ public:
|
|||
void onLightCancelTexture(const LLSD& data);
|
||||
void onLightSelectTexture(const LLSD& data);
|
||||
|
||||
static void setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp);
|
||||
void onCopyFeatures();
|
||||
void onPasteFeatures();
|
||||
void onCopyLight();
|
||||
void onPasteLight();
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//void menuDoToSelected(const LLSD& userdata);
|
||||
//bool menuEnableItem(const LLSD& userdata);
|
||||
void onFSCopyFeatures();
|
||||
void onFSPasteFeatures();
|
||||
// </FS>
|
||||
|
||||
static void setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp);
|
||||
|
||||
protected:
|
||||
void getState();
|
||||
|
|
@ -123,6 +135,15 @@ protected:
|
|||
LLSpinCtrl* mSpinPhysicsFriction;
|
||||
LLSpinCtrl* mSpinPhysicsDensity;
|
||||
LLSpinCtrl* mSpinPhysicsRestitution;
|
||||
|
||||
// <FS> Extended copy & paste buttons
|
||||
//LLMenuButton* mMenuClipboardFeatures;
|
||||
//LLMenuButton* mMenuClipboardLight;
|
||||
LLButton* mBtnCopyFeatures;
|
||||
LLButton* mBtnPasteFeatures;
|
||||
// </FS>
|
||||
|
||||
LLSD mClipboardParams;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@
|
|||
# include "llaudioengine_fmodstudio.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_SDL2
|
||||
#include "llaudioengine_sdl2.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_OPENAL
|
||||
#include "llaudioengine_openal.h"
|
||||
#endif
|
||||
|
|
@ -1008,11 +1004,6 @@ bool idle_startup()
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef LL_SDL2
|
||||
if( !gAudiop )
|
||||
gAudiop = new LLAudioEngineSDL2();
|
||||
#endif
|
||||
|
||||
#ifdef LL_OPENAL
|
||||
#if !LL_WINDOWS
|
||||
// if (NULL == getenv("LL_BAD_OPENAL_DRIVER"))
|
||||
|
|
|
|||
|
|
@ -82,6 +82,67 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
|
|||
//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
|
||||
//static const char NO_IMAGE_NAME[] = "None";
|
||||
|
||||
|
||||
|
||||
//static
|
||||
bool get_is_predefined_texture(LLUUID asset_id)
|
||||
{
|
||||
if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture"))
|
||||
|| asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID"))
|
||||
|| asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID"))
|
||||
|| asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm)
|
||||
{
|
||||
LLViewerInventoryCategory::cat_array_t cats;
|
||||
LLViewerInventoryItem::item_array_t items;
|
||||
LLAssetIDMatches asset_id_matches(asset_id);
|
||||
gInventory.collectDescendentsIf(LLUUID::null,
|
||||
cats,
|
||||
items,
|
||||
LLInventoryModel::INCLUDE_TRASH,
|
||||
asset_id_matches);
|
||||
|
||||
LLUUID res;
|
||||
if (items.size())
|
||||
{
|
||||
for (S32 i = 0; i < items.size(); i++)
|
||||
{
|
||||
LLViewerInventoryItem* itemp = items[i];
|
||||
if (itemp)
|
||||
{
|
||||
LLPermissions item_permissions = itemp->getPermissions();
|
||||
if (item_permissions.allowOperationBy(PERM_COPY,
|
||||
gAgent.getID(),
|
||||
gAgent.getGroupID()))
|
||||
{
|
||||
bool allow_trans = item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID());
|
||||
if (allow_trans != no_trans_perm)
|
||||
{
|
||||
return itemp->getUUID();
|
||||
}
|
||||
res = itemp->getUUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool get_can_copy_texture(LLUUID asset_id)
|
||||
{
|
||||
// User is allowed to copy a texture if:
|
||||
// library asset or default texture,
|
||||
// or copy perm asset exists in user's inventory
|
||||
|
||||
return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull();
|
||||
}
|
||||
|
||||
LLFloaterTexturePicker::LLFloaterTexturePicker(
|
||||
LLView* owner,
|
||||
LLUUID image_asset_id,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,16 @@ class LLViewerFetchedTexture;
|
|||
typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback;
|
||||
typedef boost::function<void (LLInventoryItem*)> texture_selected_callback;
|
||||
|
||||
// Helper functions for UI that work with picker
|
||||
bool get_is_predefined_texture(LLUUID asset_id);
|
||||
|
||||
// texture picker works by asset ids since objects normaly do
|
||||
// not retain inventory ids as result these functions are looking
|
||||
// for textures in inventory by asset ids
|
||||
// This search can be performance unfriendly and doesn't warranty
|
||||
// that the texture is original source of asset
|
||||
LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false);
|
||||
bool get_can_copy_texture(LLUUID image_id);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LLTextureCtrl
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
|
|||
mLineEditor->setText(edit_text_contents);
|
||||
|
||||
std::string notif_name = mNotification->getName();
|
||||
if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name))
|
||||
if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name) || ("CreateSubfolder" == notif_name))
|
||||
{
|
||||
mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1109,7 +1109,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
|
|||
S32 hit_face,
|
||||
LLInventoryItem* item,
|
||||
LLToolDragAndDrop::ESource source,
|
||||
const LLUUID& src_id)
|
||||
const LLUUID& src_id,
|
||||
S32 tex_channel)
|
||||
{
|
||||
if (hit_face == -1) return;
|
||||
if (!item)
|
||||
|
|
@ -1133,7 +1134,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
|
|||
|
||||
if (gFloaterTools->getVisible() && panel_face)
|
||||
{
|
||||
switch (LLSelectMgr::getInstance()->getTextureChannel())
|
||||
tex_channel = (tex_channel > -1) ? tex_channel : LLSelectMgr::getInstance()->getTextureChannel();
|
||||
switch (tex_channel)
|
||||
{
|
||||
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -244,7 +244,8 @@ public:
|
|||
static void dropTextureOneFace(LLViewerObject* hit_obj, S32 hit_face,
|
||||
LLInventoryItem* item,
|
||||
ESource source,
|
||||
const LLUUID& src_id);
|
||||
const LLUUID& src_id,
|
||||
S32 tex_channel = -1);
|
||||
static void dropTextureAllFaces(LLViewerObject* hit_obj,
|
||||
LLInventoryItem* item,
|
||||
ESource source,
|
||||
|
|
|
|||
|
|
@ -3374,6 +3374,39 @@ void handle_object_touch()
|
|||
send_ObjectDeGrab_message(object, pick);
|
||||
}
|
||||
|
||||
void handle_object_show_original()
|
||||
{
|
||||
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
|
||||
if (!object)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLViewerObject *parent = (LLViewerObject*)object->getParent();
|
||||
while (parent)
|
||||
{
|
||||
if(parent->isAvatar())
|
||||
{
|
||||
break;
|
||||
}
|
||||
object = parent;
|
||||
parent = (LLViewerObject*)parent->getParent();
|
||||
}
|
||||
|
||||
if (!object || object->isAvatar())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
show_item_original(object->getAttachmentItemID());
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Disable if prevented by RLVa
|
||||
bool enable_object_show_original()
|
||||
{
|
||||
return !RlvActions::hasBehaviour(RLV_BHVR_SHOWINV);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
static void init_default_item_label(const std::string& item_name)
|
||||
{
|
||||
|
|
@ -12309,6 +12342,7 @@ void initialize_menus()
|
|||
// Object pie menu
|
||||
view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
|
||||
commit.add("Object.Touch", boost::bind(&handle_object_touch));
|
||||
commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original));
|
||||
commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
|
||||
commit.add("Object.Delete", boost::bind(&handle_object_delete));
|
||||
view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
|
||||
|
|
@ -12350,6 +12384,8 @@ void initialize_menus()
|
|||
enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
|
||||
commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
|
||||
enable.add("Object.EnableScriptInfo", boost::bind(&enable_script_info)); // <FS:CR>
|
||||
enable.add("Object.EnableShowOriginal", boost::bind(&enable_object_show_original)); // <FS:Ansariel> Disable if prevented by RLVa
|
||||
|
||||
|
||||
// Attachment pie menu
|
||||
enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@
|
|||
#include "llfilepicker.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llfloater.h"
|
||||
#include "llfloaterbuildoptions.h"
|
||||
#include "llfloaterbuyland.h"
|
||||
#include "llfloatercamera.h"
|
||||
#include "llfloaterland.h"
|
||||
|
|
|
|||
|
|
@ -6364,7 +6364,7 @@ void LLVivoxVoiceClient::clearSessionHandle(const sessionStatePtr_t &session)
|
|||
{
|
||||
if (session)
|
||||
{
|
||||
if (session->mHandle.empty())
|
||||
if (!session->mHandle.empty())
|
||||
{
|
||||
sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle);
|
||||
if (iter != mSessionsByHandle.end())
|
||||
|
|
|
|||
|
|
@ -4157,7 +4157,7 @@ void LLPipeline::postSort(LLCamera& camera)
|
|||
}
|
||||
LL_PUSH_CALLSTACKS();
|
||||
// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
|
||||
if (LLFloaterTelehub::renderBeacons())
|
||||
if (LLFloaterTelehub::renderBeacons() && !sShadowRender)
|
||||
{
|
||||
LLFloaterTelehub::addBeacons();
|
||||
}
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 231 B |
|
After Width: | Height: | Size: 231 B |
|
After Width: | Height: | Size: 224 B |
|
After Width: | Height: | Size: 218 B |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 215 B |
|
After Width: | Height: | Size: 530 B |
|
After Width: | Height: | Size: 300 B |
|
After Width: | Height: | Size: 284 B |
|
|
@ -208,6 +208,8 @@ with the same filename but different name
|
|||
<texture name="Copy" file_name="icons/Copy.png" preload="false" />
|
||||
<texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" />
|
||||
|
||||
<texture name="Paste" file_name="icons/Paste.png" preload="false" />
|
||||
|
||||
<texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" />
|
||||
|
||||
<texture name="ChatBarHandle" file_name="bottomtray/ChatBarHandle.png" preload="false" />
|
||||
|
|
@ -520,6 +522,13 @@ with the same filename but different name
|
|||
<texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
|
||||
<texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
|
||||
|
||||
<texture name="ClipboardSmallMenu_Disabled" file_name="icons/ClipboardSmallMenu_Disabled.png" preload="false" />
|
||||
<texture name="ClipboardSmallMenu_Off" file_name="icons/ClipboardSmallMenu_Off.png" preload="false" />
|
||||
<texture name="ClipboardSmallMenu_Press" file_name="icons/ClipboardSmallMenu_Press.png" preload="false" />
|
||||
<texture name="ClipboardMenu_Disabled" file_name="icons/ClipboardMenu_Disabled.png" preload="false" />
|
||||
<texture name="ClipboardMenu_Off" file_name="icons/ClipboardMenu_Off.png" preload="false" />
|
||||
<texture name="ClipboardMenu_Press" file_name="icons/ClipboardMenu_Press.png" preload="false" />
|
||||
|
||||
<texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" />
|
||||
<texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" />
|
||||
<texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" />
|
||||
|
|
@ -989,6 +998,8 @@ with the same filename but different name
|
|||
<texture name="map_infohub.tga" />
|
||||
<texture name="map_telehub.tga" />
|
||||
<texture name="map_track_16.tga" />
|
||||
<texture name="map_ui_collapse_icon.png" />
|
||||
<texture name="map_ui_expand_icon.png" />
|
||||
|
||||
<texture name="notify_caution_icon.tga" />
|
||||
|
||||
|
|
|
|||
|
|
@ -91,10 +91,10 @@
|
|||
<text name="RenderingCost" tool_tip="Zeigt die errechneten Wiedergabekosten für dieses Objekt">
|
||||
þ: [COUNT]
|
||||
</text>
|
||||
<check_box initial_value="true" label="Texturen dehnen" name="checkbox stretch textures"/>
|
||||
<check_box initial_value="true" label="Einrasten" name="checkbox snap to grid"/>
|
||||
<check_box initial_value="false" label="Achse an Wurzel edit." name="checkbox actual root"/>
|
||||
<check_box initial_value="true" label="Aktiviere Hervorhebung" name="checkbox show highlight"/>
|
||||
<check_box label="Texturen dehnen" name="checkbox stretch textures"/>
|
||||
<check_box label="Einrasten" name="checkbox snap to grid"/>
|
||||
<check_box label="Achse an Wurzel edit." name="checkbox actual root"/>
|
||||
<check_box label="Aktiviere Hervorhebung" name="checkbox show highlight"/>
|
||||
<combo_box name="combobox grid mode" tool_tip="Wählen Sie das gewünschte Rasterlineal zum Positionieren des Objekts aus." left_pad="20">
|
||||
<combo_box.item label="Welt" name="World"/>
|
||||
<combo_box.item label="Lokal" name="Local"/>
|
||||
|
|
@ -142,8 +142,11 @@
|
|||
<text name="selection_empty">
|
||||
Nichts ausgewählt.
|
||||
</text>
|
||||
<text name="remaining_capacity">
|
||||
[CAPACITY_STRING] [secondlife:///app/openfloater/object_weights Mehr Infos]
|
||||
<text name="selection_faces">
|
||||
Flächen ausgewählt: [FACES_STRING]
|
||||
</text>
|
||||
<text name="more info label">
|
||||
[secondlife:///app/openfloater/object_weights Mehr Infos]
|
||||
</text>
|
||||
<text name="selection_weight">
|
||||
Physikgewicht [PHYS_WEIGHT], Darstellungskosten [DISP_WEIGHT].
|
||||
|
|
@ -282,15 +285,15 @@
|
|||
</panel>
|
||||
</panel>
|
||||
<panel label="Objekt" name="Object">
|
||||
<panel.string name="Paste Position">
|
||||
<panel.string name="paste_position">
|
||||
Position einfügen
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
<panel.string name="paste_size">
|
||||
Größe einfügen
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
<panel.string name="paste_rotation">
|
||||
Rotation einfügen
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
|
|
@ -302,34 +305,31 @@
|
|||
Position (Meter)
|
||||
</text>
|
||||
<spinner label="X" name="Pos X"/>
|
||||
<button label="K" name="copypos" tool_tip="Position kopieren"/>
|
||||
<button name="copy_pos_btn" label="K" tool_tip="Position kopieren"/>
|
||||
<spinner label="Y" name="Pos Y"/>
|
||||
<button label="E" name="pastepos" tool_tip="Position einfügen"/>
|
||||
<button name="paste_pos_btn" label="E" tool_tip="Position einfügen"/>
|
||||
<spinner label="Z" name="Pos Z"/>
|
||||
<button label="e" name="pasteposclip" tool_tip="Position aus Zwischenablage einfügen"/>
|
||||
<button name="paste_pos_clip_btn" label="e" tool_tip="Position versuchen aus Zwischenablage einzufügen"/>
|
||||
<text name="label size">
|
||||
Größe (Meter)
|
||||
</text>
|
||||
<spinner label="X" name="Scale X"/>
|
||||
<button label="K" name="copysize" tool_tip="Größe kopieren"/>
|
||||
<button name="copy_size_btn" label="K" tool_tip="Größe kopieren"/>
|
||||
<spinner label="Y" name="Scale Y"/>
|
||||
<button label="E" name="pastesize" tool_tip="Größe einfügen"/>
|
||||
<button name="paste_size_btn" label="E" tool_tip="Größe einfügen"/>
|
||||
<spinner label="Z" name="Scale Z"/>
|
||||
<button label="e" name="pastesizeclip" tool_tip="Größe aus Zwischenablage einfügen"/>
|
||||
<button name="paste_size_clip_btn" label="e" tool_tip="Größe versuchen aus Zwischenablage einzufügen"/>
|
||||
<text name="label rotation">
|
||||
Rotation (Grad)
|
||||
</text>
|
||||
<spinner label="X" name="Rot X"/>
|
||||
<button label="K" name="copyrot" tool_tip="Rotation kopieren"/>
|
||||
<button name="copy_rot_btn" label="K" tool_tip="Rotation kopieren"/>
|
||||
<spinner label="Y" name="Rot Y"/>
|
||||
<button label="E" name="pasterot" tool_tip="Rotation einfügen"/>
|
||||
<button name="paste_rot_btn" label="E" tool_tip="Rotation einfügen"/>
|
||||
<spinner label="Z" name="Rot Z"/>
|
||||
<button label="e" name="pasterotclip" tool_tip="Rotation aus Zwischenablage einfügen"/>
|
||||
<text name="edit_object">
|
||||
Objekt-Parameter:
|
||||
</text>
|
||||
<button label="Kop." name="copyparams" tool_tip="Objekt-Parameter in Zwischenablage kopieren"/>
|
||||
<button label="Einf." name="pasteparams" tool_tip="Objekt-Parameters aus Zwischenablage einfügen"/>
|
||||
<button name="paste_rot_clip_btn" label="e" tool_tip="Rotation versuchen aus Zwischenablage einzufügen"/>
|
||||
<button name="copy_params_btn" tool_tip="Objekt-Parameter in Zwischenablage kopieren"/>
|
||||
<button name="paste_params_btn" tool_tip="Objekt-Parameter aus Zwischenablage einfügen"/>
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="Quader" name="Box"/>
|
||||
<combo_box.item label="Zylinder" name="Cylinder"/>
|
||||
|
|
@ -470,6 +470,8 @@ Ndrg ↔ Nst
|
|||
</text>
|
||||
<check_box label="Animiertes Netz" name="Animated Mesh Checkbox Ctrl" tool_tip="Ermöglicht die unabhängige Animation geriggter Netzobjekte"/>
|
||||
<check_box label="Flexibler Pfad" name="Flexible1D Checkbox Ctrl" tool_tip="Bewirkt, dass sich das Objekt um die Z-Achse biegen kann. (Nur Client-Seite)"/>
|
||||
<button name="copy_features_btn" tool_tip="Eigenschaften-Parameter in Zwischenablage kopieren"/>
|
||||
<button name="paste_features_btn" tool_tip="Eigenschaften-Parameter aus Zwischenablage einfügen"/>
|
||||
<spinner label="Weichheit" name="FlexNumSections"/>
|
||||
<spinner label="Schwerkraft" name="FlexGravity"/>
|
||||
<spinner label="Ziehen" name="FlexFriction"/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Attachment Pie">
|
||||
<menu_item_call label="Berühren" name="Attachment Object Touch"/>
|
||||
<menu_item_call label="In Inventar anzeigen" name="Show original"/>
|
||||
<menu_item_call label="Bearbeiten" name="Edit..."/>
|
||||
<menu_item_call label="Abnehmen" name="Detach"/>
|
||||
<context_menu label="Speichern als" name="Export Menu">
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@
|
|||
<menu_item_call label="Ausziehen" name="Take Off"/>
|
||||
<menu_item_call label="Nur auf mich anwenden" name="Settings Apply Local"/>
|
||||
<menu_item_call label="Auf Parzelle anwenden" name="Settings Apply Parcel"/>
|
||||
<menu_item_call label="Neuen Ordner aus Auswahl erstellen" name="New folder from selected"/>
|
||||
<menu_item_call label="Gruppierung durch den Ordner aufheben" name="Ungroup folder items"/>
|
||||
<menu_item_call label="In Marktplatz-Auflistungen kopieren" name="Marketplace Copy"/>
|
||||
<menu_item_call label="In Marktplatz-Auflistungen verschieben" name="Marketplace Move"/>
|
||||
<menu_item_call label="--keine Optionen--" name="--no options--"/>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<pie_slice label="Collada" name="Collada"/>
|
||||
</pie_menu>
|
||||
<pie_slice label="Untersuchen" name="Avatar Inspect"/>
|
||||
<pie_slice label="In Inv. zeigen" name="Show original"/>
|
||||
<pie_slice label="Texturen" name="Debug..."/>
|
||||
</pie_menu>
|
||||
<pie_slice label="Hinsetzen" name="Sit Down Here"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu name="Conversation Gear Menu">
|
||||
<menu_item_check label="Farbe" name="Color"/>
|
||||
<menu_item_check label="Transparenz" name="Transparency"/>
|
||||
<menu_item_check label="Leuchten" name="Glow"/>
|
||||
<menu_item_check label="Textur" name="Diffuse"/>
|
||||
<menu_item_check label="Holprigkeit" name="Normal"/>
|
||||
<menu_item_check label="Glanz" name="Specular"/>
|
||||
<menu_item_check label="Mapping" name="Mapping"/>
|
||||
<menu_item_check label="Medien" name="Media"/>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -3771,6 +3771,15 @@ Sie haben lokal eine [RESOLUTION]-gebackene Textur für „[BODYREGION]“ nach
|
|||
Wir können keine Vorschau dieser Textur anzeigen, da sie nicht kopier- und/oder übertragungsfähig ist.
|
||||
<usetemplate ignoretext="Hinweis anzeigen, wenn bei nicht kopier- und/oder übertragungsfähigen Texturen keine Live-Vorschau möglich ist" name="okignore" yestext="OK"/>
|
||||
</notification>
|
||||
<notification name="FacePasteFailed">
|
||||
Einfügen fehlgeschlagen. [REASON]
|
||||
<usetemplate name="okbutton" yestext="OK"/>
|
||||
</notification>
|
||||
<notification name="FacePasteTexturePermissions">
|
||||
Sie haben eine Texture mit eingeschränkten Berechtigungen hinzugefügt. Das Objekt wird die Berechtigungen der Textur erben.
|
||||
<usetemplate ignoretext="Einfügen: Sie haben eine Texture mit eingeschränkten Berechtigungen hinzugefügt." name="notifyignore"/>
|
||||
<usetemplate name="okbutton" yestext="OK"/>
|
||||
</notification>
|
||||
<notification name="ConfirmLeaveCall">
|
||||
Möchten Sie dieses Gespräch wirklich verlassen ?
|
||||
<usetemplate ignoretext="Bestätigen, bevor ich den Anruf verlasse." name="okcancelignore" notext="Nein" yestext="Ja"/>
|
||||
|
|
@ -4868,6 +4877,17 @@ Entpacken: [UNPACK_TIME]s [USIZE]KB
|
|||
<button name="cancel" text="Abbrechen"/>
|
||||
</form>
|
||||
</notification>
|
||||
<notification label="Unterordner erstellen" name="CreateSubfolder">
|
||||
Name des neuen Ordners:
|
||||
<form name="form">
|
||||
<button default="true" name="OK" text="OK"/>
|
||||
<button name="Cancel" text="Abbrechen"/>
|
||||
</form>
|
||||
</notification>
|
||||
<notification name="SameFolderRequired">
|
||||
Ausgewählte Objekte müssen sich im selben Ordner befinden.
|
||||
<usetemplate name="okbutton" yestext="OK"/>
|
||||
</notification>
|
||||
<notification name="NoValidEnvSettingFound">
|
||||
Keine gültige Einstellung für die Umgebung ausgewählt.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,18 @@
|
|||
<panel.string name="string repeats per face">
|
||||
Wiederholungen pro Fläche
|
||||
</panel.string>
|
||||
<panel.string name="paste_error_face_selection_mismatch">
|
||||
Falls mehrere Flächen kopiert werden, müssen auf dem Zielobjekt dieselbe Anzahl an Flächen selektiert sein.
|
||||
</panel.string>
|
||||
<panel.string name="paste_error_object_face_count_mismatch">
|
||||
Falls alle Flächen eines Objekts kopiert werden, muss das Zielobjekt dieselbe Anzahl an Flächen besitzen.
|
||||
</panel.string>
|
||||
<panel.string name="paste_error_inventory_not_found">
|
||||
Eine oder mehrere Texturen wurden nicht im Inventar gefunden.
|
||||
</panel.string>
|
||||
<panel.string name="paste_options">
|
||||
Textur-Parameter in Zwischenablage kopieren
|
||||
</panel.string>
|
||||
<text name="color label">
|
||||
Farbe
|
||||
</text>
|
||||
|
|
@ -17,6 +29,9 @@
|
|||
Leuchten
|
||||
</text>
|
||||
<check_box label="Ganz hell" name="checkbox fullbright"/>
|
||||
<button name="copy_face_btn" tool_tip="Textur-Parameter in Zwischenablage kopieren"/>
|
||||
<button name="paste_face_btn" tool_tip="Textur-Parameter aus Zwischenablage einfügen"/>
|
||||
<menu_button name="paste_face_gear_btn" tool_tip="Einfüge-Optionen"/>
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="Material" name="Materials"/>
|
||||
<combo_box.item label="Medien" name="Media"/>
|
||||
|
|
@ -119,6 +134,4 @@
|
|||
<check_box label="Planare Oberflächen ausrichten" name="checkbox planar align" tool_tip="Richtet Texturen auf allen ausgewählten Flächen wie die zuletzt ausgewählte Fläche aus. Erfordert planares Textur-Mapping."/>
|
||||
<check_box label="Materialien synchronisieren" name="checkbox_sync_settings" tool_tip="Synchronisiere Texture-Mapping-Parameter"/>
|
||||
<button name="button align textures" label="Ausrichten" tool_tip="Aktuelle Textur-Schicht ausrichten"/>
|
||||
<button name="copytextures" label="Kop."/>
|
||||
<button name="pastetextures" label="Einf."/>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -832,6 +832,22 @@
|
|||
width="100">
|
||||
Nothing selected.
|
||||
</text>
|
||||
<!--
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
height="16"
|
||||
follows="left|top"
|
||||
font="SansSerifSmall"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="selection_faces"
|
||||
top_delta="0"
|
||||
visible="false"
|
||||
width="280">
|
||||
Faces selected: [FACES_STRING]
|
||||
</text>
|
||||
-->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -853,11 +869,11 @@
|
|||
font="SansSerifSmall"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="remaining_capacity"
|
||||
name="more info label"
|
||||
top_pad="-5"
|
||||
visible="false"
|
||||
width="280">
|
||||
[CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info]
|
||||
[secondlife:///app/openfloater/object_weights More info]
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
|
|
@ -1498,16 +1514,16 @@ even though the user gets a free copy.
|
|||
name="Object"
|
||||
top="16"
|
||||
width="295">
|
||||
<panel.string name="Paste Position">
|
||||
Paste Position
|
||||
<panel.string name="paste_position">
|
||||
Paste Position
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
Paste Size
|
||||
<panel.string name="paste_size">
|
||||
Paste Size
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
Paste Rotation
|
||||
<panel.string name="paste_rotation">
|
||||
Paste Rotation
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<check_box
|
||||
|
|
@ -1603,38 +1619,33 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copypos"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_pos_btn"
|
||||
tool_tip="Copy Position"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastepos"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_pos_btn"
|
||||
tool_tip="Paste Position"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasteposclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Position from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_pos_clip_btn"
|
||||
tool_tip="Try pasting Position from Clipboard"
|
||||
width="20" />
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -1697,38 +1708,32 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copysize"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_size_btn"
|
||||
tool_tip="Copy Size"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastesize"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_size_btn"
|
||||
tool_tip="Paste Size"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastesizeclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Size from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_size_clip_btn"
|
||||
tool_tip="Try pasting Size from Clipboard"
|
||||
width="20" />
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -1791,38 +1796,32 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copyrot"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_rot_btn"
|
||||
tool_tip="Copy Rotation"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasterot"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_rot_btn"
|
||||
tool_tip="Paste Rotation"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasterotclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Rotation from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_rot_clip_btn"
|
||||
tool_tip="Try pasting Rotation from Clipboard"
|
||||
width="20" />
|
||||
|
||||
<!-- <text
|
||||
|
|
@ -1837,46 +1836,41 @@ even though the user gets a free copy.
|
|||
width="150">
|
||||
Prim Type
|
||||
</text>-->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
bottom="-15"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="edit_object"
|
||||
top_pad="8"
|
||||
width="121">
|
||||
Object Parameters:
|
||||
</text>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="16"
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="copyparams"
|
||||
tool_tip="Copy Parameters to Clipboard"
|
||||
width="52">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="16"
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="pasteparams"
|
||||
tool_tip="Paste Parameters from Clipboard"
|
||||
width="52">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Copy"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-53"
|
||||
name="copy_params_btn"
|
||||
tool_tip="Copy Object Parameters to Clipboard"
|
||||
top="6"
|
||||
width="25">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Paste"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-23"
|
||||
name="paste_params_btn"
|
||||
top_delta="0"
|
||||
tool_tip="Paste Object Parameters from Clipboard"
|
||||
width="25">
|
||||
</button>
|
||||
<combo_box
|
||||
height="19"
|
||||
layout="topleft"
|
||||
name="comboBaseType"
|
||||
top="6"
|
||||
top_pad="5"
|
||||
left="125"
|
||||
width="150">
|
||||
width="149">
|
||||
<combo_box.item
|
||||
label="Box"
|
||||
name="Box"
|
||||
|
|
@ -2466,7 +2460,7 @@ even though the user gets a free copy.
|
|||
layout="topleft"
|
||||
left="125"
|
||||
name="mesh_info_label"
|
||||
top="6"
|
||||
top="30"
|
||||
width="100"
|
||||
visible="false">
|
||||
Mesh Information:
|
||||
|
|
@ -2646,7 +2640,7 @@ Lowest:
|
|||
value="LL"
|
||||
visible="false"
|
||||
width="30" />
|
||||
<string name="fs_lod_tooltip_msg">[APPNAME] Viewer default ([FACTOR])</string>
|
||||
<string name="fs_lod_tooltip_msg">[APP_NAME] Viewer default ([FACTOR])</string>
|
||||
<text
|
||||
follows="left|top"
|
||||
height="16"
|
||||
|
|
@ -2797,6 +2791,34 @@ Low ↔ Lwst
|
|||
tool_tip="Allows object to flex about the Z axis (Client-side only)"
|
||||
top_pad="5"
|
||||
width="121" />
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Copy"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-48"
|
||||
name="copy_features_btn"
|
||||
tool_tip="Copy Feature Parameters to Clipboard"
|
||||
top="20"
|
||||
width="25">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Paste"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
name="paste_features_btn"
|
||||
right="-18"
|
||||
tool_tip="Paste Feature Parameters from Clipboard"
|
||||
top_delta="0"
|
||||
width="25">
|
||||
</button>
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -2805,10 +2827,10 @@ Low ↔ Lwst
|
|||
label="Softness"
|
||||
label_width="70"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
left="10"
|
||||
max_val="3"
|
||||
name="FlexNumSections"
|
||||
top_pad="4"
|
||||
top_pad="9"
|
||||
width="128" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
|
|
@ -3023,7 +3045,7 @@ Low ↔ Lwst
|
|||
height="10"
|
||||
layout="topleft"
|
||||
name="label physicsshapetype"
|
||||
top="38"
|
||||
top="50"
|
||||
width="130">
|
||||
Physics Shape Type:
|
||||
</text>
|
||||
|
|
@ -3053,7 +3075,7 @@ Low ↔ Lwst
|
|||
layout="topleft"
|
||||
name="material"
|
||||
top_pad="5"
|
||||
width="150"
|
||||
width="134"
|
||||
left="144">
|
||||
<combo_box.item
|
||||
label="Stone"
|
||||
|
|
|
|||
|
|
@ -13,16 +13,15 @@
|
|||
function="Object.EnableTouch"
|
||||
name="EnableTouch"/>
|
||||
</menu_item_call>
|
||||
<!--menu_item_call
|
||||
label="Stand Up"
|
||||
<menu_item_call
|
||||
label="Show in inventory"
|
||||
layout="topleft"
|
||||
name="Stand Up">
|
||||
<menu_item_call.on_click
|
||||
function="Self.StandUp"
|
||||
parameter="" />
|
||||
<menu_item_call.on_enable
|
||||
function="Self.EnableStandUp" />
|
||||
</menu_item_call-->
|
||||
name="Show original">
|
||||
<menu_item_call.on_click
|
||||
function="Object.ShowOriginal" />
|
||||
<menu_item_call.on_enable
|
||||
function="Object.EnableShowOriginal" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
enabled="false"
|
||||
label="Edit"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Color Menu">
|
||||
<menu_item_call
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
name="params_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelFace.menuDoToSelected" parameter="color_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
name="params_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelFace.menuDoToSelected" parameter="color_paste" />
|
||||
<on_enable function="PanelFace.menuEnable" parameter="color_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Features Menu">
|
||||
<menu_item_call
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
name="params_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelVolume.menuDoToSelected" parameter="features_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
name="params_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelVolume.menuDoToSelected" parameter="features_paste" />
|
||||
<on_enable function="PanelVolume.menuEnable" parameter="features_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Light Menu">
|
||||
<menu_item_call
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
name="params_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelVolume.menuDoToSelected" parameter="light_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
name="params_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelVolume.menuDoToSelected" parameter="light_paste" />
|
||||
<on_enable function="PanelVolume.menuEnable" parameter="light_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Object Menu">
|
||||
<menu_item_call
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
name="params_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="params_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
name="params_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="params_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="params_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Position Menu">
|
||||
<menu_item_call
|
||||
label="Copy all"
|
||||
layout="topleft"
|
||||
name="psr_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="psr_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Copy position"
|
||||
layout="topleft"
|
||||
name="pos_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="pos_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste all"
|
||||
layout="topleft"
|
||||
name="psr_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="psr_paste" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste position"
|
||||
layout="topleft"
|
||||
name="pos_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="pos_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="pos_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Rotation Menu">
|
||||
<menu_item_call
|
||||
label="Copy all"
|
||||
layout="topleft"
|
||||
name="psr_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="rot_paste" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Copy rotation"
|
||||
layout="topleft"
|
||||
name="rot_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="rot_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste all"
|
||||
layout="topleft"
|
||||
name="psr_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="psr_paste" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste rotation"
|
||||
layout="topleft"
|
||||
name="rot_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="rot_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="rot_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Size Menu">
|
||||
<menu_item_call
|
||||
label="Copy all"
|
||||
layout="topleft"
|
||||
name="psr_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_copy" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="psr_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Copy size"
|
||||
layout="topleft"
|
||||
name="size_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="size_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste all"
|
||||
layout="topleft"
|
||||
name="psr_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="psr_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="psr_paste" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste size"
|
||||
layout="topleft"
|
||||
name="size_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelObject.menuDoToSelected" parameter="size_paste" />
|
||||
<on_enable function="PanelObject.menuEnable" parameter="size_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Copy Paste Texture Menu">
|
||||
<menu_item_call
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
name="params_copy"
|
||||
visible="true">
|
||||
<on_click function="PanelFace.menuDoToSelected" parameter="texture_copy" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
name="params_paste"
|
||||
visible="true">
|
||||
<on_click function="PanelFace.menuDoToSelected" parameter="texture_paste" />
|
||||
<on_enable function="PanelFace.menuEnable" parameter="texture_paste" />
|
||||
</menu_item_call>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -973,6 +973,25 @@
|
|||
function="Inventory.DoToSelected"
|
||||
parameter="apply_settings_parcel" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
layout="topleft"
|
||||
name="Subfolder Separator" />
|
||||
<menu_item_call
|
||||
label="Create folder from selected"
|
||||
layout="topleft"
|
||||
name="New folder from selected">
|
||||
<menu_item_call.on_click
|
||||
function="Inventory.DoToSelected"
|
||||
parameter="new_folder_from_selected" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Ungroup folder items"
|
||||
layout="topleft"
|
||||
name="Ungroup folder items">
|
||||
<menu_item_call.on_click
|
||||
function="Inventory.DoToSelected"
|
||||
parameter="ungroup_folder_items" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
layout="topleft"
|
||||
name="Marketplace Separator" />
|
||||
|
|
|
|||
|
|
@ -95,7 +95,14 @@
|
|||
function="Object.EnableExport" />
|
||||
</pie_slice>
|
||||
</pie_menu>
|
||||
<pie_separator/>
|
||||
<pie_slice
|
||||
label="Show in Inv."
|
||||
name="Show original">
|
||||
<pie_slice.on_click
|
||||
function="Object.ShowOriginal" />
|
||||
<pie_slice.on_enable
|
||||
function="Object.EnableShowOriginal" />
|
||||
</pie_slice>
|
||||
<pie_slice
|
||||
label="Inspect"
|
||||
name="Avatar Inspect">
|
||||
|
|
|
|||
|
|
@ -9762,6 +9762,29 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran
|
|||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="FacePasteFailed"
|
||||
type="alertmodal">
|
||||
Paste failed. [REASON]
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="FacePasteTexturePermissions"
|
||||
type="alertmodal">
|
||||
You applied a texture with limited permissions, object will inherit permissions from texture.
|
||||
<usetemplate
|
||||
ignoretext="Paste: You applied a texture with limited permissions"
|
||||
name="notifyignore"/>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="ConfirmLeaveCall"
|
||||
|
|
@ -13783,6 +13806,40 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
|
|||
</form>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
label="Create subfolder"
|
||||
name="CreateSubfolder"
|
||||
type="alertmodal">
|
||||
<unique/>
|
||||
Name the new folder:
|
||||
<tag>confirm</tag>
|
||||
<form name="form">
|
||||
<input name="message" type="text">
|
||||
[DESC]
|
||||
</input>
|
||||
<button
|
||||
default="true"
|
||||
index="0"
|
||||
name="OK"
|
||||
text="OK"/>
|
||||
<button
|
||||
index="1"
|
||||
name="Cancel"
|
||||
text="Cancel"/>
|
||||
</form>
|
||||
</notification>
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="SameFolderRequired"
|
||||
type="alert">
|
||||
Selected items must be in the same folder.
|
||||
<tag>fail</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="NoValidEnvSettingFound"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,22 @@
|
|||
name="Texture"
|
||||
top="0"
|
||||
width="295">
|
||||
<panel.string
|
||||
name="paste_error_face_selection_mismatch">
|
||||
When multiple faces are copied, the target object must have the same number of faces selected.
|
||||
</panel.string>
|
||||
<panel.string
|
||||
name="paste_error_object_face_count_mismatch">
|
||||
When all faces of an object are copied, the target object must have the same number of faces.
|
||||
</panel.string>
|
||||
<panel.string
|
||||
name="paste_error_inventory_not_found">
|
||||
One or more texture not found in inventory.
|
||||
</panel.string>
|
||||
<panel.string
|
||||
name="paste_options">
|
||||
Copy Texture Parameters to Clipboard
|
||||
</panel.string>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -84,7 +100,7 @@
|
|||
left_delta="0"
|
||||
name="glow"
|
||||
top_pad="4"
|
||||
width="80" />
|
||||
width="70" />
|
||||
<check_box
|
||||
height="19"
|
||||
label="Full Bright"
|
||||
|
|
@ -93,13 +109,40 @@
|
|||
name="checkbox fullbright"
|
||||
top_pad="4"
|
||||
width="81" />
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Copy"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
left="265"
|
||||
name="copy_face_btn"
|
||||
tool_tip="Copy Texture Parameters to Clipboard"
|
||||
top="6"
|
||||
width="25">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Paste"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
name="paste_face_btn"
|
||||
tool_tip="Paste Texture Parameters from Clipboard"
|
||||
top_pad="5"
|
||||
width="25">
|
||||
</button>
|
||||
<combo_box
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="combobox matmedia"
|
||||
top_pad="5"
|
||||
width="100">
|
||||
top="65"
|
||||
width="90">
|
||||
<combo_box.item
|
||||
label="Materials"
|
||||
name="Materials"
|
||||
|
|
@ -572,12 +615,15 @@
|
|||
width="265" />
|
||||
<button
|
||||
follows="top|left"
|
||||
height="19"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left_pad="0"
|
||||
image_overlay="Edit_Flip_X"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="flipTextureScaleU"
|
||||
label=""
|
||||
top_delta="1"
|
||||
tool_tip="Flip"
|
||||
width="16">
|
||||
<button.commit_callback
|
||||
|
|
@ -599,12 +645,15 @@
|
|||
width="265" />
|
||||
<button
|
||||
follows="top|left"
|
||||
height="19"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left_pad="0"
|
||||
image_overlay="Edit_Flip_X"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="flipTextureScaleV"
|
||||
label=""
|
||||
top_delta="1"
|
||||
tool_tip="Flip"
|
||||
width="16">
|
||||
<button.commit_callback
|
||||
|
|
@ -826,30 +875,13 @@
|
|||
<button
|
||||
layout="topleft"
|
||||
follows="right|top"
|
||||
height="14"
|
||||
height="23"
|
||||
left_pad="0"
|
||||
top_delta="-15"
|
||||
top_delta="-10"
|
||||
label="Align"
|
||||
name="button align textures"
|
||||
tool_tip="Align current texture layers"
|
||||
width="84" />
|
||||
<button
|
||||
layout="topleft"
|
||||
follows="right|top"
|
||||
top_pad="0"
|
||||
label="Copy"
|
||||
name="copytextures"
|
||||
height="14"
|
||||
width="40" />
|
||||
<button
|
||||
layout="topleft"
|
||||
follows="right|top"
|
||||
height="14"
|
||||
left_pad="4"
|
||||
top_delta="0"
|
||||
label="Paste"
|
||||
name="pastetextures"
|
||||
width="40" />
|
||||
<web_browser
|
||||
visible="false"
|
||||
enabled="false"
|
||||
|
|
|
|||
|
|
@ -279,34 +279,31 @@
|
|||
Posición (metros)
|
||||
</text>
|
||||
<spinner label="X" name="Pos X"/>
|
||||
<button label="C" name="copypos" tool_tip="Copiar posición."/>
|
||||
<button name="copy_pos_btn" label="C" tool_tip="Copiar posición."/>
|
||||
<spinner label="Y" name="Pos Y"/>
|
||||
<button label="P" name="pastepos" tool_tip="Copiar posición."/>
|
||||
<button name="paste_pos_btn" label="P" tool_tip="Copiar posición."/>
|
||||
<spinner label="Z" name="Pos Z"/>
|
||||
<button label="p" name="pasteposclip" tool_tip="Pegar posición desde el portapapeles."/>
|
||||
<button name="paste_pos_clip_btn" label="p" tool_tip="Pegar posición desde el portapapeles."/>
|
||||
<text name="label size">
|
||||
Tamaño (metros)
|
||||
</text>
|
||||
<spinner label="X" name="Scale X"/>
|
||||
<button label="C" name="copysize" tool_tip="Copiar tamaño."/>
|
||||
<button name="copy_size_btn" label="C" tool_tip="Copiar tamaño."/>
|
||||
<spinner label="Y" name="Scale Y"/>
|
||||
<button label="P" name="pastesize" tool_tip="Pegar tamaño."/>
|
||||
<button name="paste_size_btn" label="P" tool_tip="Pegar tamaño."/>
|
||||
<spinner label="Z" name="Scale Z"/>
|
||||
<button label="p" name="pastesizeclip" tool_tip="Pegar tamaño desde el portapapeles."/>
|
||||
<button name="paste_size_clip_btn" label="p" tool_tip="Pegar tamaño desde el portapapeles."/>
|
||||
<text name="label rotation">
|
||||
Rotación (grados)
|
||||
</text>
|
||||
<spinner label="X" name="Rot X"/>
|
||||
<button label="C" name="copyrot" tool_tip="Copiar rotación."/>
|
||||
<button name="copy_rot_btn" label="C" tool_tip="Copiar rotación."/>
|
||||
<spinner label="Y" name="Rot Y"/>
|
||||
<button label="P" name="pasterot" tool_tip="Pegar rotación."/>
|
||||
<button name="paste_rot_btn" label="P" tool_tip="Pegar rotación."/>
|
||||
<spinner label="Z" name="Rot Z"/>
|
||||
<button label="p" name="pasterotclip" tool_tip="Pegar rotación desde el portapapeles."/>
|
||||
<text name="edit_object">
|
||||
Paráms. del objeto:
|
||||
</text>
|
||||
<button label="Copiar" name="copyparams" tool_tip="Copiar parámetros al portapapeles."/>
|
||||
<button label="Pegar" name="pasteparams" tool_tip="Pegar parámetros desde el portapapeles."/>
|
||||
<button label="p" name="paste_rot_clip_btn" tool_tip="Pegar rotación desde el portapapeles."/>
|
||||
<button label="Copiar" name="copy_params_btn" tool_tip="Copiar parámetros al portapapeles."/>
|
||||
<button label="Pegar" name="paste_params_btn" tool_tip="Pegar parámetros desde el portapapeles."/>
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="Cubo" name="Box"/>
|
||||
<combo_box.item label="Cilindro" name="Cylinder"/>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
Brillo
|
||||
</text>
|
||||
<check_box label="Brillo completo" name="checkbox fullbright"/>
|
||||
<button tool_tip="Copiar" name="copy_face_btn"/>
|
||||
<button tool_tip="Pegar" name="paste_face_btn"/>
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="Materiales" name="Materials"/>
|
||||
<combo_box.item label="Medios" name="Media"/>
|
||||
|
|
@ -118,6 +120,4 @@
|
|||
<spinner label="Despl. vertical" name="shinyOffsetV"/>
|
||||
<check_box label="Alinear caras planas" name="checkbox planar align" tool_tip="Alinea las texturas en todas las caras seleccionadas con la última en seleccionarse. Requiere mapeado de textura plano."/>
|
||||
<check_box label="Sincronizar materiales" name="checkbox_sync_settings" tool_tip="Sincroniza los parámetros del mapa de texturas"/>
|
||||
<button label="Copiar" name="copytextures"/>
|
||||
<button label="Pegar" name="pastetextures"/>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@
|
|||
Bande passante
|
||||
</panel.string>
|
||||
<panel.string name="time">
|
||||
[hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
|
||||
</panel.string>
|
||||
<panel.string name="timeTooltip">
|
||||
[weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]
|
||||
[hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt] [timezone,datetime, slt]
|
||||
</panel.string>
|
||||
<panel.string name="buycurrencylabel">
|
||||
[AMT] L$
|
||||
|
|
@ -18,10 +15,9 @@
|
|||
<panel name="menu_search_panel">
|
||||
<search_editor label="Menus de recherche" name="search_menu_edit" tool_tip="Tapez le terme de recherche qui vous intéresse ici. Les résultats seront affichés pour les correspondances partielles en texte intégral dans le menu."/>
|
||||
</panel>
|
||||
<panel left="-426" name="balance_bg" width="100">
|
||||
<panel name="balance_bg">
|
||||
<text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="L$ ??"/>
|
||||
<button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
|
||||
<button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/>
|
||||
<button label="Ach. L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/>
|
||||
</panel>
|
||||
<text name="TimeText" tool_tip="Heure actuelle (Pacifique)">
|
||||
00h00 PST
|
||||
|
|
|
|||
|
|
@ -271,15 +271,15 @@
|
|||
</panel>
|
||||
</panel>
|
||||
<panel label="Oggetto" name="Object">
|
||||
<panel.string name="Paste Position">
|
||||
<panel.string name="paste_position">
|
||||
Posiz. incolla
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
<panel.string name="paste_size">
|
||||
Dimens. incolla
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
<panel.string name="paste_rotation">
|
||||
Rotaz. incolla
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
|
|
@ -290,23 +290,24 @@
|
|||
<text name="label position">
|
||||
Posizione (metri)
|
||||
</text>
|
||||
<button name="copypos" tool_tip="Copia posizione"/>
|
||||
<button name="pastepos" tool_tip="Incolla posizione"/>
|
||||
<button name="pasteposclip" tool_tip="Incolla pos da appunti"/>
|
||||
<button name="copy_pos_btn" tool_tip="Copia posizione"/>
|
||||
<button name="paste_pos_btn" tool_tip="Incolla posizione"/>
|
||||
<button name="paste_pos_clip_btn" tool_tip="Incolla pos da appunti"/>
|
||||
<text name="label size">
|
||||
Dimensioni (metri)
|
||||
</text>
|
||||
<button name="copysize" tool_tip="Copia dimensioni"/>
|
||||
<button name="pastesize" tool_tip="Incolla dimensioni"/>
|
||||
<button name="pastesizeclip" tool_tip="Incolla dim da appunti"/>
|
||||
<button name="copy_rot_btn" tool_tip="Copia dimensioni"/>
|
||||
<button name="paste_rot_btn" tool_tip="Incolla dimensioni"/>
|
||||
<button name="paste_rot_clip_btn" tool_tip="Incolla dim da appunti"/>
|
||||
<text name="label rotation">
|
||||
Rotazione (gradi)
|
||||
</text>
|
||||
<text name="edit_object">
|
||||
Parametri oggetto:
|
||||
</text>
|
||||
<button label="Copia" name="copyparams" tool_tip="Copia i parametri dell''oggetto negli appunti"/>
|
||||
<button label="Incolla" name="pasteparams" tool_tip="Incolla i parametri dagli appunti"/>
|
||||
<button name="copy_size_btn" tool_tip="Copia rotazione"/>
|
||||
<button name="paste_size_btn" tool_tip="Incolla rotazione"/>
|
||||
<button name="paste_size_clip_btn" tool_tip="Incolla dim da appunti"/>
|
||||
<text name="label rotation">
|
||||
<button label="Copia" name="copy_params_btn" tool_tip="Copia i parametri dell''oggetto negli appunti"/>
|
||||
<button label="Incolla" name="paste_params_btn" tool_tip="Incolla i parametri dagli appunti"/>
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="Cubo" name="Box"/>
|
||||
<combo_box.item label="Cilindro" name="Cylinder"/>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
Bagliore
|
||||
</text>
|
||||
<check_box label="Luminosità max" name="checkbox fullbright"/>
|
||||
<button tool_tip="Copia" name="copy_face_btn"/>
|
||||
<button tool_tip="Incolla" name="paste_face_btn"/>
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="Materiali" name="Materials"/>
|
||||
<combo_box.item label="Media" name="Media"/>
|
||||
|
|
@ -110,6 +112,4 @@
|
|||
<spinner label="Spostamento verticale" name="shinyOffsetV"/>
|
||||
<check_box label="Allinea facce planari" name="checkbox planar align" tool_tip="Allinea le texture su tutte le facce selezionate con l'ultima faccia selezionata. È richiesta la mappatura planare delle texture."/>
|
||||
<check_box label="Sincronizza materiali" name="checkbox_sync_settings" tool_tip="Sincronizza i parametri delle texture"/>
|
||||
<button label="Copia" name="copytextures"/>
|
||||
<button label="Incolla" name="pastetextures"/>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -293,8 +293,8 @@
|
|||
<text name="edit_object">
|
||||
オブジェクトのパラメータ:
|
||||
</text>
|
||||
<button label="コピー" name="copyparams" tool_tip="パラメータをクリップボードにコピーします。" />
|
||||
<button label="貼り付け" name="pasteparams" tool_tip="パラメータをクリップボードから貼り付けます。" />
|
||||
<button label="コピー" name="copy_params_btn" tool_tip="パラメータをクリップボードにコピーします。" />
|
||||
<button label="貼り付け" name="paste_params_btn" tool_tip="パラメータをクリップボードから貼り付けます。" />
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="ボックス" name="Box"/>
|
||||
<combo_box.item label="シリンダー" name="Cylinder"/>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
グロー
|
||||
</text>
|
||||
<check_box label="明るさ全開" name="checkbox fullbright"/>
|
||||
<button tool_tip="コピー" name="copy_face_btn" />
|
||||
<button tool_tip="貼り付け" name="paste_face_btn" />
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="材質" name="Materials"/>
|
||||
<combo_box.item label="メディア" name="Media"/>
|
||||
|
|
@ -106,9 +108,7 @@
|
|||
<spinner label="回転度" name="shinyRot"/>
|
||||
<spinner label="水平オフセット" name="shinyOffsetU"/>
|
||||
<spinner label="垂直オフセット" name="shinyOffsetV"/>
|
||||
<check_box initial_value="false" label="平面を揃える" name="checkbox planar align" tool_tip="選択面全てのテクスチャを、最後に選択された面に揃えます。平面テクスチャのマッピングが必要です。"/>
|
||||
<check_box label="平面を揃える" name="checkbox planar align" tool_tip="選択面全てのテクスチャを、最後に選択された面に揃えます。平面テクスチャのマッピングが必要です。"/>
|
||||
<check_box label="素材を同期" name="checkbox_sync_settings" tool_tip="テクスチャ・マップのパラメータを同期します" />
|
||||
<button label="揃える" name="button align textures" tool_tip="現在のテクスチャ・レイヤーを揃えます" />
|
||||
<button label="コピー" name="copytextures" />
|
||||
<button label="貼り付け" name="pastetextures" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -254,15 +254,15 @@
|
|||
</panel>
|
||||
</panel>
|
||||
<panel label="Obiekt" name="Object">
|
||||
<panel.string name="Paste Position">
|
||||
<panel.string name="paste_position">
|
||||
Wklej pozycję
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
<panel.string name="paste_size">
|
||||
Wklej rozmiar
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
<panel.string name="paste_rotation">
|
||||
Wklej obrót
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
|
|
@ -273,26 +273,23 @@
|
|||
<text name="label position">
|
||||
Pozycja (metry)
|
||||
</text>
|
||||
<button label="K" name="copypos" tool_tip="Kopiuj pozycję"/>
|
||||
<button label="W" name="pastepos" tool_tip="Wklej pozycję"/>
|
||||
<button label="w" name="pasteposclip" tool_tip="Wklej pozycję ze schowka"/>
|
||||
<button name="copy_pos_btn" label="K" tool_tip="Kopiuj pozycję"/>
|
||||
<button name="paste_pos_btn" label="W" tool_tip="Wklej pozycję"/>
|
||||
<button name="paste_pos_clip_btn" label="w" tool_tip="Wklej pozycję ze schowka"/>
|
||||
<text name="label size">
|
||||
Rozmiar (metry)
|
||||
</text>
|
||||
<button label="K" name="copysize" tool_tip="Kopiuj rozmiar"/>
|
||||
<button label="W" name="pastesize" tool_tip="Wklej rozmiar"/>
|
||||
<button label="w" name="pastesizeclip" tool_tip="Wklej rozmiar ze schowka"/>
|
||||
<button name="copy_size_btn" label="K" tool_tip="Kopiuj rozmiar"/>
|
||||
<button name="paste_size_btn" label="W" tool_tip="Wklej rozmiar"/>
|
||||
<button name="paste_size_clip_btn" label="w" tool_tip="Wklej rozmiar ze schowka"/>
|
||||
<text name="label rotation">
|
||||
Obrót (stopnie)
|
||||
</text>
|
||||
<button label="K" name="copyrot" tool_tip="Kopiuj obrót"/>
|
||||
<button label="W" name="pasterot" tool_tip="Wklej obrót"/>
|
||||
<button label="w" name="pasterotclip" tool_tip="Wklej obrót ze schowka"/>
|
||||
<text name="edit_object">
|
||||
Parametry obiektu:
|
||||
</text>
|
||||
<button label="Kopiuj" name="copyparams" tool_tip="Kopiuj parametry do schowka"/>
|
||||
<button label="Wklej" name="pasteparams" tool_tip="Wklej parametry ze schowka"/>
|
||||
<button name="copy_rot_btn" label="K" tool_tip="Kopiuj obrót"/>
|
||||
<button name="paste_rot_btn" label="W" tool_tip="Wklej obrót"/>
|
||||
<button name="paste_rot_clip_btn" label="w" tool_tip="Wklej obrót ze schowka"/>
|
||||
<button label="Kopiuj" name="copy_params_btn" tool_tip="Kopiuj parametry do schowka"/>
|
||||
<button label="Wklej" name="paste_params_btn" tool_tip="Wklej parametry ze schowka"/>
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="Klocek" name="Box"/>
|
||||
<combo_box.item label="Walec" name="Cylinder"/>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
Blask
|
||||
</text>
|
||||
<check_box label="Pełna jasność" name="checkbox fullbright" />
|
||||
<button tool_tip="Kopia" name="copy_face_btn" />
|
||||
<button tool_tip="Wklej" name="paste_face_btn" />
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="Materiały" name="Materials" />
|
||||
<combo_box.item label="Media" name="Media" />
|
||||
|
|
@ -113,6 +115,4 @@
|
|||
<check_box label="Równaj powierzchnie planarne" name="checkbox planar align" tool_tip="Wyrównuj tekstury na wszystkich wybranych powierzchniach z powierzchnią wybraną jako ostatnia. Wymaga planarnego mapowania tekstur." />
|
||||
<check_box label="Synchronizuj materiały" name="checkbox_sync_settings" tool_tip="Synchronizuj parametry map tekstur" />
|
||||
<button label="Wyrównaj" name="button align textures" tool_tip="Wyrównaj bieżące warstwy tekstury" />
|
||||
<button label="Kopia" name="copytextures" />
|
||||
<button label="Wklej" name="pastetextures" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -258,15 +258,15 @@
|
|||
</panel>
|
||||
</panel>
|
||||
<panel label="Объект" name="Object">
|
||||
<panel.string name="Paste Position">
|
||||
<panel.string name="paste_position">
|
||||
Вставить позицию
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
<panel.string name="paste_size">
|
||||
Вставить размер
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
<panel.string name="paste_rotation">
|
||||
Вставить поворот
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
|
|
@ -277,26 +277,23 @@
|
|||
<text name="label position">
|
||||
Позиция (метры)
|
||||
</text>
|
||||
<button label="К" name="copypos" tool_tip="Копировать позицию"/>
|
||||
<button label="В" name="pastepos" tool_tip="Вставить позицию"/>
|
||||
<button label="в" name="pasteposclip" tool_tip="Вставить позицию из буфера"/>
|
||||
<button name="copy_pos_btn" label="К" tool_tip="Копировать позицию"/>
|
||||
<button name="paste_pos_btn" label="В" tool_tip="Вставить позицию"/>
|
||||
<button name="paste_pos_clip_btn" label="в" tool_tip="Вставить позицию из буфера"/>
|
||||
<text name="label size">
|
||||
Размер (метры)
|
||||
</text>
|
||||
<button label="К" name="copysize" tool_tip="Копировать размер"/>
|
||||
<button label="В" name="pastesize" tool_tip="Вставить размер"/>
|
||||
<button label="в" name="pastesizeclip" tool_tip="Вставить размер из буфера"/>
|
||||
<button name="copy_size_btn" label="К" tool_tip="Копировать размер"/>
|
||||
<button name="paste_size_btn" label="В" tool_tip="Вставить размер"/>
|
||||
<button name="paste_size_clip_btn" label="в" tool_tip="Вставить размер из буфера"/>
|
||||
<text name="label rotation">
|
||||
Поворот (градусы)
|
||||
</text>
|
||||
<button label="К" name="copyrot" tool_tip="Копировать поворот"/>
|
||||
<button label="В" name="pasterot" tool_tip="Вставить поворот"/>
|
||||
<button label="в" name="pasterotclip" tool_tip="Вставить поворот из буфера"/>
|
||||
<text name="edit_object" top_pad="20" bottom="-10" >
|
||||
Параметры объекта:
|
||||
</text>
|
||||
<button label="Копировать" name="copyparams" tool_tip="Копировать параметры в буфер" width="80"/>
|
||||
<button label="Вставить" name="pasteparams" tool_tip="Вставить параметры из буфера" width="70"/>
|
||||
<button name="copy_rot_btn" label="К" tool_tip="Копировать поворот"/>
|
||||
<button name="paste_rot_btn" label="В" tool_tip="Вставить поворот"/>
|
||||
<button name="paste_rot_clip_btn" label="в" tool_tip="Вставить поворот из буфера"/>
|
||||
<button label="Копировать" name="copy_params_btn" tool_tip="Копировать параметры в буфер"/>
|
||||
<button label="Вставить" name="paste_params_btn" tool_tip="Вставить параметры из буфера"/>
|
||||
<combo_box name="comboBaseType">
|
||||
<combo_box.item label="Коробка" name="Box"/>
|
||||
<combo_box.item label="Цилиндр" name="Cylinder"/>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
Свечение
|
||||
</text>
|
||||
<check_box label="Собств. яркость" name="checkbox fullbright"/>
|
||||
<button tool_tip="Копировать" name="copy_face_btn" />
|
||||
<button tool_tip="Вставить" name="paste_face_btn" />
|
||||
<combo_box name="combobox matmedia">
|
||||
<combo_box.item label="Материалы" name="Materials"/>
|
||||
<combo_box.item label="Медиа" name="Media"/>
|
||||
|
|
@ -115,6 +117,4 @@
|
|||
<check_box initial_value="false" label="Согласование" name="checkbox planar align" tool_tip="Согласование текстур на всех выбранных гранях по последней выбранной грани. Должно быть выбрано наложение по плоскостям."/>
|
||||
<check_box label="Синхронизировать материалы" name="checkbox_sync_settings" tool_tip="Синхронизация параметров карты текстур" />
|
||||
<button label="Выровнять" name="button align textures" tool_tip="Выровнять текущие слои текстуры" width="84" />
|
||||
<button label="Копировать" name="copytextures" />
|
||||
<button label="Вставить" name="pastetextures" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -831,6 +831,22 @@
|
|||
width="100">
|
||||
Nothing selected.
|
||||
</text>
|
||||
<!--
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
height="16"
|
||||
follows="left|top"
|
||||
font="SansSerifSmall"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="selection_faces"
|
||||
top_delta="0"
|
||||
visible="false"
|
||||
width="280">
|
||||
Faces selected: [FACES_STRING]
|
||||
</text>
|
||||
-->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -852,11 +868,11 @@
|
|||
font="SansSerifSmall"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="remaining_capacity"
|
||||
name="more info label"
|
||||
top_pad="-5"
|
||||
visible="false"
|
||||
width="280">
|
||||
[CAPACITY_STRING] [secondlife:///app/openfloater/object_weights More info]
|
||||
[secondlife:///app/openfloater/object_weights More info]
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
|
|
@ -1497,16 +1513,16 @@ even though the user gets a free copy.
|
|||
name="Object"
|
||||
top="16"
|
||||
width="295">
|
||||
<panel.string name="Paste Position">
|
||||
Paste Position
|
||||
<panel.string name="paste_position">
|
||||
Paste Position
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Size">
|
||||
Paste Size
|
||||
<panel.string name="paste_size">
|
||||
Paste Size
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<panel.string name="Paste Rotation">
|
||||
Paste Rotation
|
||||
<panel.string name="paste_rotation">
|
||||
Paste Rotation
|
||||
[VALUE]
|
||||
</panel.string>
|
||||
<check_box
|
||||
|
|
@ -1602,38 +1618,33 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copypos"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_pos_btn"
|
||||
tool_tip="Copy Position"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastepos"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_pos_btn"
|
||||
tool_tip="Paste Position"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasteposclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Position from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_pos_clip_btn"
|
||||
tool_tip="Try pasting Position from Clipboard"
|
||||
width="20" />
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -1696,38 +1707,32 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copysize"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_size_btn"
|
||||
tool_tip="Copy Size"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastesize"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_size_btn"
|
||||
tool_tip="Paste Size"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pastesizeclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Size from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_size_clip_btn"
|
||||
tool_tip="Try pasting Size from Clipboard"
|
||||
width="20" />
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -1790,38 +1795,32 @@ even though the user gets a free copy.
|
|||
top_pad="3"
|
||||
width="87" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="C"
|
||||
top_delta="-43"
|
||||
left_pad="5"
|
||||
mouse_opaque="true"
|
||||
name="copyrot"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="C"
|
||||
name="copy_rot_btn"
|
||||
tool_tip="Copy Rotation"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="P"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasterot"
|
||||
enabled="true"
|
||||
tab_stop="false"
|
||||
label="P"
|
||||
name="paste_rot_btn"
|
||||
tool_tip="Paste Rotation"
|
||||
width="20" />
|
||||
<button
|
||||
tab_stop="false"
|
||||
follows="top|right"
|
||||
height="19"
|
||||
label="p"
|
||||
top_pad="3"
|
||||
mouse_opaque="true"
|
||||
name="pasterotclip"
|
||||
enabled="true"
|
||||
tool_tip="Paste Rotation from Clipboard"
|
||||
tab_stop="false"
|
||||
label="p"
|
||||
name="paste_rot_clip_btn"
|
||||
tool_tip="Try pasting Rotation from Clipboard"
|
||||
width="20" />
|
||||
|
||||
<!-- <text
|
||||
|
|
@ -1836,46 +1835,41 @@ even though the user gets a free copy.
|
|||
width="150">
|
||||
Prim Type
|
||||
</text>-->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
bottom="-15"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="edit_object"
|
||||
top_pad="8"
|
||||
width="121">
|
||||
Object Parameters:
|
||||
</text>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="16"
|
||||
label="Copy"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="copyparams"
|
||||
tool_tip="Copy Parameters to Clipboard"
|
||||
width="52">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="16"
|
||||
label="Paste"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="pasteparams"
|
||||
tool_tip="Paste Parameters from Clipboard"
|
||||
width="52">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Copy"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-53"
|
||||
name="copy_params_btn"
|
||||
tool_tip="Copy Object Parameters to Clipboard"
|
||||
top="6"
|
||||
width="25">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Paste"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-23"
|
||||
name="paste_params_btn"
|
||||
top_delta="0"
|
||||
tool_tip="Paste Object Parameters from Clipboard"
|
||||
width="25">
|
||||
</button>
|
||||
<combo_box
|
||||
height="19"
|
||||
layout="topleft"
|
||||
name="comboBaseType"
|
||||
top="6"
|
||||
top_pad="5"
|
||||
left="125"
|
||||
width="150">
|
||||
width="149">
|
||||
<combo_box.item
|
||||
label="Box"
|
||||
name="Box"
|
||||
|
|
@ -2465,10 +2459,10 @@ even though the user gets a free copy.
|
|||
layout="topleft"
|
||||
left="125"
|
||||
name="mesh_info_label"
|
||||
top="6"
|
||||
top="30"
|
||||
width="100"
|
||||
visible="false">
|
||||
Mesh Information:
|
||||
Mesh Information:
|
||||
</text>
|
||||
<text
|
||||
follows="left|top"
|
||||
|
|
@ -2629,7 +2623,7 @@ Lowest:
|
|||
left="125"
|
||||
halign="left"
|
||||
name="LOD_swap_label"
|
||||
top_pad="3"
|
||||
top_pad="3"
|
||||
value="LOD Swap"
|
||||
visible="false"
|
||||
width="60" />
|
||||
|
|
@ -2655,7 +2649,7 @@ Lowest:
|
|||
name="LOD_swap_fs_default"
|
||||
top_delta="0"
|
||||
visible="false"
|
||||
width="30">
|
||||
width="30" >
|
||||
[APP_NAME_ABBR]
|
||||
</text>
|
||||
<string name="user_lod_label_string">[FACTOR]</string>
|
||||
|
|
@ -2683,7 +2677,7 @@ Lowest:
|
|||
width="65" >
|
||||
High ↔ Med
|
||||
Med ↔ Low
|
||||
Low ↔ Lwst
|
||||
Low ↔ Lwst
|
||||
</text>
|
||||
<string
|
||||
name="LODSwapFormatString"
|
||||
|
|
@ -2724,21 +2718,20 @@ Low ↔ Lwst
|
|||
value="--"
|
||||
visible="false"
|
||||
width="30" />
|
||||
<text
|
||||
name="LODSwapTableDscriptionsText"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
left="125"
|
||||
right="-1"
|
||||
word_wrap="true"
|
||||
top_pad="15"
|
||||
tool_tip="Best practice: Creators should ensure good LOD behaviour for Default settings across all viewers."
|
||||
height="100">
|
||||
<text
|
||||
name="LODSwapTableDscriptionsText"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
left="125"
|
||||
right="-1"
|
||||
word_wrap="true"
|
||||
top_pad="15"
|
||||
tool_tip="Best practice: Creators should ensure good LOD behaviour for Default settings across all viewers."
|
||||
height="100">
|
||||
This table shows the LOD change boundaries in metres from the camera.
|
||||
</text>
|
||||
<!-- /FS:Beq end of Mesh info section-->
|
||||
|
||||
</panel>
|
||||
</panel>
|
||||
<panel
|
||||
border="false"
|
||||
follows="all"
|
||||
|
|
@ -2797,6 +2790,34 @@ Low ↔ Lwst
|
|||
tool_tip="Allows object to flex about the Z axis (Client-side only)"
|
||||
top_pad="5"
|
||||
width="121" />
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Copy"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
right="-48"
|
||||
name="copy_features_btn"
|
||||
tool_tip="Copy Feature Parameters to Clipboard"
|
||||
top="20"
|
||||
width="25">
|
||||
</button>
|
||||
<button
|
||||
follows="top|right"
|
||||
height="23"
|
||||
image_overlay="Paste"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
name="paste_features_btn"
|
||||
right="-18"
|
||||
tool_tip="Paste Feature Parameters from Clipboard"
|
||||
top_delta="0"
|
||||
width="25">
|
||||
</button>
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -2805,10 +2826,10 @@ Low ↔ Lwst
|
|||
label="Softness"
|
||||
label_width="70"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
left="10"
|
||||
max_val="3"
|
||||
name="FlexNumSections"
|
||||
top_pad="4"
|
||||
top_pad="9"
|
||||
width="128" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
|
|
@ -3016,14 +3037,14 @@ Low ↔ Lwst
|
|||
mouse_opaque="true"
|
||||
name="Light Ambiance"
|
||||
width="120" />
|
||||
<text
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
name="label physicsshapetype"
|
||||
top="38"
|
||||
top="50"
|
||||
width="130">
|
||||
Physics Shape Type:
|
||||
</text>
|
||||
|
|
@ -3036,25 +3057,25 @@ Low ↔ Lwst
|
|||
tool_tip="Choose the physics shape type"
|
||||
width="108"/>
|
||||
<button
|
||||
follows="left|top"
|
||||
height="19"
|
||||
is_toggle="true"
|
||||
control_name="ShowPhysicsShapeInEdit"
|
||||
image_disabled="PhysicsView_Off"
|
||||
image_disabled_selected="PhysicsView_Off"
|
||||
image_selected="PhysicsView_On"
|
||||
image_unselected="PhysicsView_Off"
|
||||
layout="topleft"
|
||||
left_delta="117"
|
||||
name="PhysicsViewToggle"
|
||||
tool_tip="Toggle the physics view on in edit mode"
|
||||
width="19"/>
|
||||
<combo_box
|
||||
follows="left|top"
|
||||
height="19"
|
||||
is_toggle="true"
|
||||
control_name="ShowPhysicsShapeInEdit"
|
||||
image_disabled="PhysicsView_Off"
|
||||
image_disabled_selected="PhysicsView_Off"
|
||||
image_selected="PhysicsView_On"
|
||||
image_unselected="PhysicsView_Off"
|
||||
layout="topleft"
|
||||
left_delta="117"
|
||||
name="PhysicsViewToggle"
|
||||
tool_tip="Toggle the physics view on in edit mode"
|
||||
width="19"/>
|
||||
<combo_box
|
||||
height="19"
|
||||
layout="topleft"
|
||||
name="material"
|
||||
top_pad="5"
|
||||
width="150"
|
||||
width="134"
|
||||
left="144">
|
||||
<combo_box.item
|
||||
label="Stone"
|
||||
|
|
|
|||