Ansariel 2022-08-04 14:18:46 +02:00
commit 9f3cbadd29
96 changed files with 3574 additions and 1648 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -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

View File

@ -2721,7 +2721,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
if (!mNoOptimize)
{
ret->optimizeVolumeFaces();
ret->remapVolumeFaces();
}
volume_faces = remainder.size();

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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
{

View File

@ -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);

View File

@ -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})

View File

@ -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;
// ?

View File

@ -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;
}

View File

@ -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}
)

View File

@ -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
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -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}

View File

@ -1 +1 @@
6.6.2
6.6.3

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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()
{

View File

@ -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();

View File

@ -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)

View File

@ -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
{

View File

@ -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
** **

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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>

View File

@ -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;
};

View File

@ -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();
}
}

View File

@ -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 )
{

View File

@ -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

View File

@ -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"))

View File

@ -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,

View File

@ -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

View File

@ -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);
}

View File

@ -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:

View File

@ -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,

View File

@ -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));

View File

@ -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"

View File

@ -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())

View File

@ -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();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

View File

@ -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" />

View File

@ -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"/>

View File

@ -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">

View File

@ -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--"/>

View File

@ -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"/>

View File

@ -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>

View File

@ -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.

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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" />

View File

@ -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">

View File

@ -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"

View File

@ -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"

View File

@ -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"/>

View File

@ -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>

View File

@ -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

View File

@ -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'&apos;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'&apos;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"/>

View File

@ -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&apos;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>

View File

@ -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"/>

View File

@ -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>

View File

@ -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"/>

View File

@ -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>

View File

@ -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"/>

View File

@ -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>

View File

@ -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"