Merge branch 'release/2025.05' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/newview/skins/default/xui/en/panel_preferences_sound.xml
master
Ansariel 2025-07-27 12:54:37 +02:00
commit f37e2785d5
22 changed files with 184 additions and 54 deletions

View File

@ -103,13 +103,11 @@ Perform the testing procedure on both sets of cubes.
Ensure that debug setting `MediaFirstClickInteract` is set to `4`
This test case requires two pairs of cubes, and the second pair must be deeded or set to a group that your testing account is a member of, but does not have set as active at the beginning of the test. As long as the second set of cubes is set to a group that your primary test account is a member of, the avatar that owns them does not matter.
This test case requires two cubes, and the second cube must be deeded or set to a group that your testing account is a member of. As long as the second set of cubes is set to a group that your test account is a member of, the avatar that owns them does not matter.
1. Perform the testing procedure on both sets of cubes.
2. Activate the group that the second set of cubes is set / deeded to
3. Perform the testing procedure on both sets of cubes once more.
Perform the testing procedure on both sets of cubes.
**Expected observations:** Both cubes owned by your primary testing account will not react to mouse cursor hover events and clicks without needing a focus click. Cube A set to group will react to mouse cursor hover events and clicks without needing a focus click, but Cube B will not.
**Expected observations:** The cube owned by your primary account will not react to mouse cursor hover events and clicks without needing a focus click. The cube set to group will react to mouse cursor hover events and clicks without needing a focus click.
### Case 5 (MEDIA_FIRST_CLICK_FRIEND)
@ -144,16 +142,16 @@ Note: This requires the avatar that is performing the tests to physically be in
### Case 7 (MEDIA_FIRST_CLICK_ANY) (optional)
Ensure that debug setting `MediaFirstClickInteract` is set to `31`
Ensure that debug setting `MediaFirstClickInteract` is set to `32767`
Repeat test cases 1-6.
1. Test case 1 should fail
2. Test cases 2-6 should pass
### Case 8 (MEDIA_FIRST_CLICK_ALL) (optional)
### Case 8 (MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG) (optional)
Ensure that debug setting `MediaFirstClickInteract` is set to `1073741824`
Ensure that debug setting `MediaFirstClickInteract` is set to `65535`
Repeat test cases 1-6, there is no pass/fail for this run.

View File

@ -182,14 +182,22 @@ void LL::WorkQueueBase::callWork(const Work& work)
}
catch (...)
{
// Stash any other kind of uncaught exception to be rethrown by main thread.
LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
<< getKey() << LL_ENDL;
if (getKey() != "mainloop")
{
// Stash any other kind of uncaught exception to be rethrown by main thread.
LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
<< getKey() << LL_ENDL;
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
main_queue->post(
// Bind the current exception, rethrow it in main loop.
[exc = std::current_exception()]() { std::rethrow_exception(exc); });
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
main_queue->post(
// Bind the current exception, rethrow it in main loop.
[exc = std::current_exception()]() { std::rethrow_exception(exc); });
}
else
{
// let main loop crash
throw;
}
}
#endif // else LL_WINDOWS
}

View File

@ -241,12 +241,15 @@ LLModel::EModelStatus load_face_from_dom_triangles(
if (idx_stride <= 0
|| (pos_source && pos_offset >= idx_stride)
|| (pos_source && pos_offset < 0)
|| (tc_source && tc_offset >= idx_stride)
|| (norm_source && norm_offset >= idx_stride))
|| (tc_source && tc_offset < 0)
|| (norm_source && norm_offset >= idx_stride)
|| (norm_source && norm_offset < 0))
{
// Looks like these offsets should fit inside idx_stride
// Might be good idea to also check idx.getCount()%idx_stride != 0
LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
LL_WARNS() << "Invalid idx_stride " << idx_stride << ", pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
return LLModel::BAD_ELEMENT;
}

View File

@ -33,6 +33,7 @@
#include "llmatrix4a.h"
#include <boost/bind.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include "../llxml/llcontrol.h"
@ -125,7 +126,6 @@ LLModelLoader::LLModelLoader(
, mLod(lod)
, mTrySLM(false)
, mFirstTransform(true)
, mNumOfFetchingTextures(0)
, mLoadCallback(load_cb)
, mJointLookupFunc(joint_lookup_func)
, mTextureLoadFunc(texture_load_func)
@ -136,6 +136,7 @@ LLModelLoader::LLModelLoader(
, mNoNormalize(false)
, mNoOptimize(false)
, mCacheOnlyHitIfRigged(false)
, mTexturesNeedScaling(false)
, mMaxJointsPerMesh(maxJointsPerMesh)
, mGeneratedModelLimit(modelLimit)
, mDebugMode(debugMode)
@ -186,7 +187,7 @@ void LLModelLoader::run()
LLSD args;
args["Message"] = "UnknownException";
args["FILENAME"] = mFilename;
args["EXCEPTION"] = "Unknown exception";
args["EXCEPTION"] = boost::current_exception_diagnostic_information();
mWarningsArray.append(args);
setLoadState(ERROR_PARSING);
}
@ -674,7 +675,7 @@ void LLModelLoader::loadTextures()
if(!material.mDiffuseMapFilename.empty())
{
mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData);
mTextureLoadFunc(material, mOpaqueData);
}
}
}

View File

@ -111,6 +111,7 @@ public:
bool mTrySLM;
bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
bool mTexturesNeedScaling;
model_list mModelList;
// The scene is pretty much what ends up getting loaded for upload. Basically assign things to this guy if you want something uploaded.
@ -172,9 +173,6 @@ public:
void stretch_extents(const LLModel* model, const LLMatrix4& mat);
S32 mNumOfFetchingTextures ; // updated in the main thread
bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.
bool verifyCount( int expected, int result );
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)

View File

@ -23455,7 +23455,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>MediaFirstClickInteract</key>
<map>
<key>Comment</key>
<string>This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. This setting is a bitfield, precomputed values are as follows: Disabled=0; Worn HUDs only=1; Owned objects=3; Friend objects=7; Group objects=15; Landowner objects=31; Any object=31; All MOAP=1073741824. For complete details see lltoolpie.h enum MediaFirstClickTypes.</string>
<string>This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. This setting is a bitfield, precomputed values are as follows: Disabled=0; Worn HUDs only=1; Owned objects=2; Friend objects=4; Group objects=8; Landowner objects=16; Any object=32767; All MOAP=32768. For complete details see lltoolpie.h enum MediaFirstClickTypes.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>

View File

@ -59,6 +59,7 @@
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <fstream>
static const std::string lod_suffix[LLModel::NUM_LODS] =
@ -154,7 +155,7 @@ bool LLGLTFLoader::OpenFile(const std::string &filename)
LLSD args;
args["Message"] = "ParsingErrorException";
args["FILENAME"] = filename;
args["EXCEPTION"] = "Unknown exception";
args["EXCEPTION"] = boost::current_exception_diagnostic_information();
mWarningsArray.append(args);
setLoadState(ERROR_PARSING);
return false;
@ -611,6 +612,7 @@ LLGLTFLoader::LLGLTFImportMaterial LLGLTFLoader::processMaterial(S32 material_in
LL::GLTF::Image& image = mGLTFAsset.mImages[sourceIndex];
if (image.mTexture.notNull())
{
mTexturesNeedScaling |= image.mHeight > LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT || image.mWidth > LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT;
impMat.setDiffuseMap(image.mTexture->getID());
LL_INFOS("GLTF_IMPORT") << "Using existing texture ID: " << image.mTexture->getID().asString() << LL_ENDL;
}

View File

@ -6637,7 +6637,8 @@ void LLAppViewer::forceExceptionThreadCrash()
void run()
{
throw std::exception();
const std::string exception_text = "This is a deliberate exception in a thread";
throw std::runtime_error(exception_text);
}
};

View File

@ -191,7 +191,7 @@ bool LLFloaterModelPreview::postBuild()
for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
{
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
lod_source_combo->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLoDSourceCommit, this, lod));
lod_source_combo->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLoDSourceCommit, this, lod, true));
lod_source_combo->setCurrentByIndex(mLODMode[lod]);
getChild<LLButton>("lod_browse_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onBrowseLOD, this, lod));
@ -858,7 +858,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[i]);
if (lod_source_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE)
{
onLoDSourceCommit(i);
onLoDSourceCommit(i, false);
}
else
{
@ -1523,26 +1523,26 @@ void LLFloaterModelPreview::addStringToLog(const std::string& message, const LLS
{
std::string str;
switch (lod)
{
{
case LLModel::LOD_IMPOSTOR: str = "LOD0 "; break;
case LLModel::LOD_LOW: str = "LOD1 "; break;
case LLModel::LOD_MEDIUM: str = "LOD2 "; break;
case LLModel::LOD_PHYSICS: str = "PHYS "; break;
case LLModel::LOD_HIGH: str = "LOD3 "; break;
default: break;
}
}
LLStringUtil::format_map_t args_msg;
LLSD::map_const_iterator iter = args.beginMap();
LLSD::map_const_iterator end = args.endMap();
for (; iter != end; ++iter)
{
{
args_msg[iter->first] = iter->second.asString();
}
str += sInstance->getString(message, args_msg);
sInstance->addStringToLogTab(str, flash);
}
}
}
// static
void LLFloaterModelPreview::addStringToLog(const std::string& str, bool flash)
@ -1943,7 +1943,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
}
}
void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
void LLFloaterModelPreview::onLoDSourceCommit(S32 lod, bool refresh_ui)
{
mModelPreview->updateLodControls(lod);
@ -1965,9 +1965,17 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
|| index == LLModelPreview::GENERATE // <FS:Beq/> Improved LOD generation
|| index == LLModelPreview::MESH_OPTIMIZER_SLOPPY
|| index == LLModelPreview::MESH_OPTIMIZER_PRECISE)
{ //rebuild LoD to update triangle counts
{
// rebuild LoD to update triangle counts
onLODParamCommit(lod, true);
}
else if (refresh_ui && index == LLModelPreview::USE_LOD_ABOVE)
{
// Update mUploadData for updateStatusMessages
mModelPreview->rebuildUploadData();
// Update UI with new triangle values
mModelPreview->updateStatusMessages();
}
}
void LLFloaterModelPreview::resetDisplayOptions()

View File

@ -210,7 +210,7 @@ private:
void onClickCalculateBtn();
void onJointListSelection();
void onLoDSourceCommit(S32 lod);
void onLoDSourceCommit(S32 lod, bool refresh_ui);
void modelUpdated(bool calculate_visible);

View File

@ -6431,7 +6431,7 @@ void FSPanelPreferenceSounds::updateMoapInteractionSetting()
{
if (mMoapInteractionAll->get())
{
gSavedSettings.setS32("MediaFirstClickInteract", std::numeric_limits<S32>::max());
gSavedSettings.setS32("MediaFirstClickInteract", LLToolPie::MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG | LLToolPie::MEDIA_FIRST_CLICK_ANY);
}
else if (mMoapInteractionAny->get())
{

View File

@ -2920,6 +2920,7 @@ bool LLInventoryModel::loadSkeleton(
LL_DEBUGS(LOG_INV) << "importing inventory skeleton for " << owner_id << LL_ENDL;
LLTimer timer;
typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
cat_set_t temp_cats;
bool rv = true;
@ -3204,7 +3205,8 @@ bool LLInventoryModel::loadSkeleton(
}
LL_INFOS(LOG_INV) << "Successfully loaded " << cached_category_count
<< " categories and " << cached_item_count << " items from cache."
<< " categories and " << cached_item_count << " items from cache"
<< " after " << timer.getElapsedTimeF32() << " seconds."
<< LL_ENDL;
return rv;

View File

@ -401,9 +401,28 @@ void LLInventoryPanel::initializeViewBuilding()
if (mInventory->isInventoryUsable()
&& LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT)
{
LLTimer timer;
// Usually this happens on login, so we have less time constraits, but too long and we can cause a disconnect
const F64 max_time = 20.f;
initializeViews(max_time);
if (mViewsInitialized == VIEWS_INITIALIZED)
{
LL_INFOS("Inventory")
<< "Fully initialized inventory panel " << getName()
<< " with " << (S32)mItemMap.size()
<< " views in " << timer.getElapsedTimeF32() << " seconds."
<< LL_ENDL;
}
else
{
LL_INFOS("Inventory")
<< "Partially initialized inventory panel " << getName()
<< " with " << (S32)mItemMap.size()
<< " views in " << timer.getElapsedTimeF32()
<< " seconds. Pending known views: " << (S32)mBuildViewsQueue.size()
<< LL_ENDL;
}
}
else
{

View File

@ -2489,6 +2489,42 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::
pack_textures(base_color_img, normal_img, mr_img, emissive_img, occlusion_img,
mBaseColorJ2C, mNormalJ2C, mMetallicRoughnessJ2C, mEmissiveJ2C);
if (open_floater)
{
bool textures_scaled = false;
if (mBaseColorFetched && mBaseColorJ2C
&& (mBaseColorFetched->getWidth() != mBaseColorJ2C->getWidth()
|| mBaseColorFetched->getHeight() != mBaseColorJ2C->getHeight()))
{
textures_scaled = true;
}
else if (mNormalFetched && mNormalJ2C
&& (mNormalFetched->getWidth() != mNormalJ2C->getWidth()
|| mNormalFetched->getHeight() != mNormalJ2C->getHeight()))
{
textures_scaled = true;
}
else if (mMetallicRoughnessFetched && mMetallicRoughnessJ2C
&& (mMetallicRoughnessFetched->getWidth() != mMetallicRoughnessJ2C->getWidth()
|| mMetallicRoughnessFetched->getHeight() != mMetallicRoughnessJ2C->getHeight()))
{
textures_scaled = true;
}
else if (mEmissiveFetched && mEmissiveJ2C
&& (mEmissiveFetched->getWidth() != mEmissiveJ2C->getWidth()
|| mEmissiveFetched->getHeight() != mEmissiveJ2C->getHeight()))
{
textures_scaled = true;
}
if (textures_scaled)
{
LLSD args;
args["MAX_SIZE"] = LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT;
LLNotificationsUtil::add("MaterialImagesWereScaled", args);
}
}
LLUUID base_color_id;
if (mBaseColorFetched.notNull())
{

View File

@ -224,6 +224,8 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
, mLastJointUpdate(false)
, mFirstSkinUpdate(true)
, mHasDegenerate(false)
, mNumOfFetchingTextures(0)
, mTexturesNeedScaling(false)
, mImporterDebug(LLCachedControl<bool>(gSavedSettings, "ImporterDebugVerboseLogging", false))
{
mNeedsUpdate = true;
@ -780,10 +782,7 @@ void LLModelPreview::rebuildUploadData()
texture->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, new LLHandle<LLModelPreview>(getHandle()), &mCallbackTextureList, false);
texture->forceToSaveRawImage(0, F32_MAX);
texture->updateFetch();
if (mModelLoader)
{
mModelLoader->mNumOfFetchingTextures++;
}
mNumOfFetchingTextures++;
}
}
}
@ -1298,7 +1297,9 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
setLegacyRigFlags(mModelLoader->getLegacyRigFlags());
mTexturesNeedScaling |= mModelLoader->mTexturesNeedScaling;
mModelLoader->loadTextures();
warnTextureScaling();
if (loaded_lod == -1)
{ //populate all LoDs from model loader scene
@ -3482,7 +3483,7 @@ void LLModelPreview::updateStatusMessages()
LLMutexLock lock(this);
if (mModelLoader)
{
if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
if (!areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
{
// Some textures are still loading, prevent upload until they are done
mModelNoErrors = false;
@ -4117,9 +4118,12 @@ void LLModelPreview::loadedCallback(
S32 lod,
void* opaque)
{
if(LLModelPreview::sIgnoreLoadedCallback)
return;
LLModelPreview* pPreview = static_cast<LLModelPreview*>(opaque);
LLMutexLock lock(pPreview);
if (pPreview && pPreview->mModelLoader && !LLModelPreview::sIgnoreLoadedCallback)
if (pPreview && pPreview->mModelLoader)
{
// Load loader's warnings into floater's log tab
const LLSD out = pPreview->mModelLoader->logOut();
@ -4250,6 +4254,7 @@ U32 LLModelPreview::loadTextures(LLImportMaterial& material, LLHandle<LLModelPre
tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, new LLHandle<LLModelPreview>(handle), &preview->mCallbackTextureList, false);
tex->forceToSaveRawImage(0, F32_MAX);
material.setDiffuseMap(tex->getID()); // record tex ID
preview->mNumOfFetchingTextures++;
return 1;
}
@ -5183,6 +5188,18 @@ void LLModelPreview::setPreviewLOD(S32 lod)
updateStatusMessages();
}
void LLModelPreview::warnTextureScaling()
{
if (areTexturesReady() && mTexturesNeedScaling)
{
std::ostringstream out;
out << "One or more textures in this model were scaled to be within the allowed limits.";
LL_INFOS() << out.str() << LL_ENDL;
LLSD args;
LLFloaterModelPreview::addStringToLog("ModelTextureScaling", args, true, -1);
}
}
//static
void LLModelPreview::textureLoadedCallback(
bool success,
@ -5203,11 +5220,19 @@ void LLModelPreview::textureLoadedCallback(
LLModelPreview* preview = static_cast<LLModelPreview*>(handle->get());
preview->refresh();
if (final && preview->mModelLoader)
if (final)
{
if (preview->mModelLoader->mNumOfFetchingTextures > 0)
if (src_vi
&& (src_vi->getOriginalWidth() > LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT
|| src_vi->getOriginalHeight() > LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT))
{
preview->mModelLoader->mNumOfFetchingTextures--;
preview->mTexturesNeedScaling = true;
}
if (preview->mNumOfFetchingTextures > 0)
{
preview->mNumOfFetchingTextures--;
preview->warnTextureScaling();
}
}
}

View File

@ -210,6 +210,7 @@ public:
std::vector<S32> mLodsQuery;
std::vector<S32> mLodsWithParsingError;
bool mHasDegenerate;
bool areTexturesReady() { return !mNumOfFetchingTextures; }
protected:
bool matchMaterialOrder(LLModel* lod, LLModel* ref, int& refFaceCnt, int& modelFaceCnt ); // <FS:Beq/> FIRE-30965 Cleanup mesh material parsing
@ -219,6 +220,7 @@ protected:
static LLJoint* lookupJointByName(const std::string&, void* opaque);
static U32 loadTextures(LLImportMaterial& material, LLHandle<LLModelPreview> handle);
void warnTextureScaling();
void lookupLODModelFiles(S32 lod);
private:
@ -248,6 +250,9 @@ private:
/// Not read unless mWarnOfUnmatchedPhyicsMeshes is true.
LLPointer<LLModel> mDefaultPhysicsShapeP{nullptr};
S32 mNumOfFetchingTextures;
bool mTexturesNeedScaling;
typedef enum
{
MESH_OPTIMIZER_FULL,

View File

@ -1977,12 +1977,6 @@ bool LLToolPie::shouldAllowFirstMediaInteraction(const LLPickInfo& pick, bool mo
return false;
}
// Own objects
if((FirstClickPref & MEDIA_FIRST_CLICK_OWN) && object->permYouOwner())
{
LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_OWN" << LL_ENDL;
return true;
}
// HUD attachments
if((FirstClickPref & MEDIA_FIRST_CLICK_HUD) && object->isHUDAttachment())
{
@ -2005,6 +1999,13 @@ bool LLToolPie::shouldAllowFirstMediaInteraction(const LLPickInfo& pick, bool mo
return false;
}
// Own objects
if((FirstClickPref & MEDIA_FIRST_CLICK_OWN) && owner_id == gAgent.getID())
{
LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_OWN" << LL_ENDL;
return true;
}
// Check if the object is owned by a friend of the agent
if(FirstClickPref & MEDIA_FIRST_CLICK_FRIEND)
{

View File

@ -103,10 +103,10 @@ public:
MEDIA_FIRST_CLICK_LAND = 1 << 4, // 0b00010000 (16)
// Covers any object with PRIM_MEDIA_FIRST_CLICK_INTERACT (combines all previous flags)
MEDIA_FIRST_CLICK_ANY = ~(3<<30), // 0b00111111111111111111111111111111
MEDIA_FIRST_CLICK_ANY = (1 << 15) - 1, // 0b0111111111111111 (32767)
// Covers all media regardless of other rules or PRIM_MEDIA_FIRST_CLICK_INTERACT
MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG = 1 << 30 // 0b01000000000000000000000000000000 (1073741824)
MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG = 1 << 15 // 0b1000000000000000 (32768)
};
private:
bool shouldAllowFirstMediaInteraction(const LLPickInfo& info, bool moap_flag);

View File

@ -94,6 +94,9 @@
<string name="tbd">
folgt
</string>
<string name="ModelTextureScaling">
Eine oder mehrere Texturen in diesem Modell wurde(n) skaliert, um innerhalb der erlaubten Limits zu bleiben.
</string>
<string name="TooManyJoint">
Skinning wurde wegen zu vieler Gelenke deaktiviert: [JOINTS], Maximum: [MAX]
</string>

View File

@ -2911,6 +2911,11 @@ Dies kann die Eingabe Ihres Passworts beeinflussen.
<notification name="MaterialNoPermissions">
Ihnen fehlt die Berechtigung zur Anzeige dieses Materials.
</notification>
<notification name="MaterialImagesWereScaled">
Eine oder mehrere Texturen in diesem Modell wurde(n) skaliert, um innerhalb der erlaubten Limits zu bleiben.
Texturen müssen Dimensionen aus 2er-Potenzen haben und dürfen [MAX_SIZE]x[MAX_SIZE] Pixel nicht überschreiten.
<usetemplate ignoretext="Warnen, wenn Texturen beim Upload skaliert werden." name="okignore" yestext="OK"/>
</notification>
<notification name="RezItemNoPermissions">
Keine Berechtigung zum Rezzen von Objekten.
</notification>

View File

@ -44,6 +44,7 @@
<string name="decomposing">Analyzing...</string>
<string name="simplifying">Simplifying...</string>
<string name="tbd">TBD</string>
<string name="ModelTextureScaling">One or more textures in this model were scaled to be within the allowed limits.</string>
<!-- Warnings and info from model loader-->
<string name="TooManyJoint">Skinning disabled due to too many joints: [JOINTS], maximum: [MAX]</string>

View File

@ -7631,6 +7631,20 @@ You do not have permission to view this notecard.
<tag>fail</tag>
</notification>
<notification
icon="alertmodal.tga"
name="MaterialImagesWereScaled"
type="alertmodal">
One or more textures in this material were scaled to be within the allowed limits.
Textures must have power of two dimensions and must not exceed [MAX_SIZE]x[MAX_SIZE] pixels.
<unique/>
<tag>confirm</tag>
<usetemplate
ignoretext="Warn if textures will be scaled during upload."
name="okignore"
yestext="OK"/>
</notification>
<notification
icon="notifytip.tga"
name="RezItemNoPermissions"