summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llmessage/llxfer.cpp2
-rw-r--r--indra/llmessage/llxfermanager.cpp40
-rw-r--r--indra/llmessage/llxfermanager.h3
-rw-r--r--indra/newview/app_settings/settings.xml4
-rw-r--r--indra/newview/llagent.cpp18
-rw-r--r--indra/newview/llagent.h8
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/lltool.cpp21
-rw-r--r--indra/newview/lltoolcomp.cpp26
-rw-r--r--indra/newview/lltoolgrab.cpp2
-rw-r--r--indra/newview/llviewercontrol.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp39
-rw-r--r--indra/newview/llviewerobject.h13
-rw-r--r--indra/newview/llvoavatar.cpp1
-rw-r--r--indra/newview/llvovolume.cpp35
-rw-r--r--indra/newview/llvovolume.h2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml16
17 files changed, 177 insertions, 59 deletions
diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp
index 4aba5cae72..e0590dfdff 100644
--- a/indra/llmessage/llxfer.cpp
+++ b/indra/llmessage/llxfer.cpp
@@ -294,7 +294,7 @@ S32 LLXfer::processEOF()
}
else
{
- LL_INFOS() << "xfer from " << mRemoteHost << " failed, code "
+ LL_INFOS() << "xfer from " << mRemoteHost << " failed or aborted, code "
<< mCallbackResult << ": " << getFileName() << LL_ENDL;
}
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 0232a6e802..2ceb64ce8f 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -401,7 +401,7 @@ U64 LLXferManager::registerXfer(const void *datap, const S32 length)
///////////////////////////////////////////////////////////
-void LLXferManager::requestFile(const std::string& local_filename,
+U64 LLXferManager::requestFile(const std::string& local_filename,
const std::string& remote_filename,
ELLPath remote_path,
const LLHost& remote_host,
@@ -424,10 +424,12 @@ void LLXferManager::requestFile(const std::string& local_filename,
{
// cout << "requested a xfer already in progress" << endl;
- return;
+ return xferp->mID;
}
}
+ U64 xfer_id = 0;
+
S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1;
xferp = (LLXfer *) new LLXfer_File(chunk_size);
if (xferp)
@@ -438,13 +440,15 @@ void LLXferManager::requestFile(const std::string& local_filename,
// around.
// Note: according to AaronB, this is here to deal with locks on files that were
// in transit during a crash,
- if(delete_remote_on_completion &&
- (remote_filename.substr(remote_filename.length()-4) == ".tmp"))
+ if( delete_remote_on_completion
+ && (remote_filename.substr(remote_filename.length()-4) == ".tmp")
+ && gDirUtilp->fileExists(local_filename))
{
LLFile::remove(local_filename, ENOENT);
}
+ xfer_id = getNextID();
((LLXfer_File *)xferp)->initializeRequest(
- getNextID(),
+ xfer_id,
local_filename,
remote_filename,
remote_path,
@@ -457,6 +461,7 @@ void LLXferManager::requestFile(const std::string& local_filename,
{
LL_ERRS() << "Xfer allocation error" << LL_ENDL;
}
+ return xfer_id;
}
void LLXferManager::requestFile(const std::string& remote_filename,
@@ -616,7 +621,7 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user
if (!xferp)
{
char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_WARNS() << "received xfer data from " << mesgsys->getSender()
+ LL_INFOS() << "received xfer data from " << mesgsys->getSender()
<< " for non-existent xfer id: "
<< U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << LL_ENDL;
return;
@@ -1103,6 +1108,29 @@ void LLXferManager::retransmitUnackedPackets ()
}
}
+///////////////////////////////////////////////////////////
+
+void LLXferManager::abortRequestById(U64 xfer_id, S32 result_code)
+{
+ LLXfer * xferp = findXfer(xfer_id, mReceiveList);
+ if (xferp)
+ {
+ if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ // causes processAbort();
+ xferp->abort(result_code);
+ }
+ else
+ {
+ xferp->mCallbackResult = result_code;
+ xferp->processEOF(); //should notify requester
+ removeXfer(xferp, &mReceiveList);
+ }
+ // Since already removed or marked as aborted no need
+ // to wait for processAbort() to start new download
+ startPendingDownloads();
+ }
+}
///////////////////////////////////////////////////////////
diff --git a/indra/llmessage/llxfermanager.h b/indra/llmessage/llxfermanager.h
index b3d110e7a1..d258f0a5ce 100644
--- a/indra/llmessage/llxfermanager.h
+++ b/indra/llmessage/llxfermanager.h
@@ -140,7 +140,7 @@ class LLXferManager
// file requesting routines
// .. to file
- virtual void requestFile(const std::string& local_filename,
+ virtual U64 requestFile(const std::string& local_filename,
const std::string& remote_filename,
ELLPath remote_path,
const LLHost& remote_host,
@@ -202,6 +202,7 @@ class LLXferManager
virtual void retransmitUnackedPackets ();
// error handling
+ void abortRequestById(U64 xfer_id, S32 result_code);
virtual void processAbort (LLMessageSystem *mesgsys, void **user_data);
};
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a8bd5c7183..8836ed0e5e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10284,10 +10284,10 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>RenderRiggedFactorMultiplier</key>
+ <key>RenderRiggedLodCompensation</key>
<map>
<key>Comment</key>
- <string>Affects level of detail for worn rigged meshes</string>
+ <string>Affects visibility range of worn rigged meshes to compensate for missing LODs (limited by avatars own visibility)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 6a1215c3af..d8b0787852 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3191,7 +3191,7 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
}
BOOL LLAgent::leftButtonGrabbed() const
-{
+{
const BOOL camera_mouse_look = gAgentCamera.cameraMouselook();
return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
|| (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)
@@ -3199,6 +3199,13 @@ BOOL LLAgent::leftButtonGrabbed() const
|| (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
}
+BOOL LLAgent::leftButtonBlocked() const
+{
+ const BOOL camera_mouse_look = gAgentCamera.cameraMouselook();
+ return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
+ || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
+}
+
BOOL LLAgent::rotateGrabbed() const
{
return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0)
@@ -3656,7 +3663,14 @@ BOOL LLAgent::anyControlGrabbed() const
BOOL LLAgent::isControlGrabbed(S32 control_index) const
{
- return mControlsTakenCount[control_index] > 0;
+ if (gAgent.mControlsTakenCount[control_index] > 0)
+ return TRUE;
+ return gAgent.mControlsTakenPassedOnCount[control_index] > 0;
+}
+
+BOOL LLAgent::isControlBlocked(S32 control_index) const
+{
+ return mControlsTakenCount[control_index] > 0;
}
void LLAgent::forceReleaseControls()
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index b5da5e9062..d82ff7a67f 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -444,7 +444,8 @@ private:
// Grab
//--------------------------------------------------------------------
public:
- BOOL leftButtonGrabbed() const;
+ BOOL leftButtonGrabbed() const;
+ BOOL leftButtonBlocked() const;
BOOL rotateGrabbed() const;
BOOL forwardGrabbed() const;
BOOL backwardGrabbed() const;
@@ -461,8 +462,9 @@ public:
BOOL controlFlagsDirty() const;
void enableControlFlagReset();
void resetControlFlags();
- BOOL anyControlGrabbed() const; // True iff a script has taken over a control
- BOOL isControlGrabbed(S32 control_index) const;
+ BOOL anyControlGrabbed() const; // True if a script has taken over any control
+ BOOL isControlGrabbed(S32 control_index) const; // True if a script has taken over a control
+ BOOL isControlBlocked(S32 control_index) const; // Control should be ignored or won't be passed
// Send message to simulator to force grabbed controls to be
// released, in case of a poorly written script.
void forceReleaseControls();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b0829a3da1..bf7e643d0b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -592,7 +592,7 @@ static void settings_to_globals()
LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures");
LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor");
- LLVOVolume::sRiggedFactorMultiplier = gSavedSettings.getF32("RenderRiggedFactorMultiplier");
+ LLVOVolume::sRiggedLODCompensation = llmax(0.25f, gSavedSettings.getF32("RenderRiggedLodCompensation"));
LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 4aad650b68..5e703933ca 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -38,6 +38,7 @@
#include "lltoolfocus.h"
#include "llfocusmgr.h"
#include "llagent.h"
+#include "llagentcamera.h"
#include "llviewerjoystick.h"
extern BOOL gDebugClicks;
@@ -84,7 +85,14 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
}
// by default, didn't handle it
// LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL;
- gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+ }
return TRUE;
}
@@ -95,8 +103,15 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse up" << LL_ENDL;
}
// by default, didn't handle it
- // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
- gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ }
return TRUE;
}
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 76a791c6e9..2b4fa757f6 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -742,12 +742,13 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
{
- // if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
- {
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
- return FALSE;
- }
+ // if the left button is blocked, don't put up the pie menu
+ if (gAgent.leftButtonBlocked())
+ {
+ // in case of "grabbed" control flag will be set later
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ return FALSE;
+ }
// On mousedown, start grabbing
gGrabTransientTool = this;
@@ -759,12 +760,13 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- // if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
- {
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
- return FALSE;
- }
+ // if the left button is blocked, don't put up the pie menu
+ if (gAgent.leftButtonBlocked())
+ {
+ // in case of "grabbed" control flag will be set later
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ return FALSE;
+ }
// On mousedown, start grabbing
gGrabTransientTool = this;
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 92e8af985b..c0ca4d7a9a 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -143,7 +143,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
// call the base class to propogate info to sim
LLTool::handleMouseDown(x, y, mask);
- if (!gAgent.leftButtonGrabbed())
+ if (!gAgent.leftButtonBlocked())
{
// can grab transparent objects (how touch event propagates, scripters rely on this)
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 5e74e9f019..bdd79b0da1 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -209,7 +209,7 @@ static bool handleVolumeLODChanged(const LLSD& newvalue)
static bool handleRiggedLODChanged(const LLSD& newvalue)
{
- LLVOVolume::sRiggedFactorMultiplier = (F32)newvalue.asReal();
+ LLVOVolume::sRiggedLODCompensation = llmax(0.25f, (F32)newvalue.asReal());
return true;
}
@@ -625,7 +625,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
- gSavedSettings.getControl("RenderRiggedFactorMultiplier")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2));
+ gSavedSettings.getControl("RenderRiggedLodCompensation")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2));
gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2));
gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2));
gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2));
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 5f4eeaa37b..7964bf1848 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -133,7 +133,6 @@ std::map<std::string, U32> LLViewerObject::sObjectDataMap;
// JC 3/18/2003
const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
-const F64 INV_REQUEST_EXPIRE_TIME_SEC = 60.f;
static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object");
@@ -245,9 +244,10 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
- mRegionp( regionp ),
- mInvRequestExpireTime(0.f),
+ mInvRequestState(INVENTORY_REQUEST_STOPPED),
+ mInvRequestXFerId(0),
mInventoryDirty(FALSE),
+ mRegionp(regionp),
mDead(FALSE),
mOrphaned(FALSE),
mUserSelected(FALSE),
@@ -2843,11 +2843,7 @@ void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener)
BOOL LLViewerObject::isInventoryPending()
{
- if (mInvRequestExpireTime == 0.f || mInvRequestExpireTime < LLFrameTimer::getTotalSeconds())
- {
- return FALSE;
- }
- return TRUE;
+ return mInvRequestState != INVENTORY_REQUEST_STOPPED;
}
void LLViewerObject::clearInventoryListeners()
@@ -2888,7 +2884,7 @@ void LLViewerObject::requestInventory()
void LLViewerObject::fetchInventoryFromServer()
{
- if (mInvRequestExpireTime == 0.f || mInvRequestExpireTime < LLFrameTimer::getTotalSeconds())
+ if (!isInventoryPending())
{
delete mInventory;
LLMessageSystem* msg = gMessageSystem;
@@ -2901,7 +2897,7 @@ void LLViewerObject::fetchInventoryFromServer()
msg->sendReliable(mRegionp->getHost());
// this will get reset by dirtyInventory or doInventoryCallback
- mInvRequestExpireTime = LLFrameTimer::getTotalSeconds() + INV_REQUEST_EXPIRE_TIME_SEC;
+ mInvRequestState = INVENTORY_REQUEST_PENDING;
}
}
@@ -2962,7 +2958,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
std::string unclean_filename;
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
-
+
if(ft->mFilename.empty())
{
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
@@ -2984,13 +2980,27 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
delete ft;
return;
}
- gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+ U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
ft->mFilename, LL_PATH_CACHE,
object->mRegionp->getHost(),
TRUE,
&LLViewerObject::processTaskInvFile,
(void**)ft,
LLXferManager::HIGH_PRIORITY);
+ if (object->mInvRequestState == INVENTORY_XFER)
+ {
+ if (new_id > 0 && new_id != object->mInvRequestXFerId)
+ {
+ // we started new download.
+ gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+ object->mInvRequestXFerId = new_id;
+ }
+ }
+ else
+ {
+ object->mInvRequestState = INVENTORY_XFER;
+ object->mInvRequestXFerId = new_id;
+ }
}
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3117,7 +3127,10 @@ void LLViewerObject::doInventoryCallback()
mInventoryCallbacks.erase(curiter);
}
}
- mInvRequestExpireTime = 0.f;
+
+ // release inventory loading state
+ mInvRequestXFerId = 0;
+ mInvRequestState = INVENTORY_REQUEST_STOPPED;
}
void LLViewerObject::removeInventory(const LLUUID& item_id)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 804b6c147b..1e8f3f4ec2 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -720,6 +720,7 @@ private:
void deleteTEImages(); // correctly deletes list of images
protected:
+
typedef std::map<char *, LLNameValue *> name_value_map_t;
name_value_map_t mNameValuePairs; // Any name-value pairs stored by script
@@ -756,9 +757,17 @@ protected:
callback_list_t mInventoryCallbacks;
S16 mInventorySerialNum;
+ enum EInventoryRequestState
+ {
+ INVENTORY_REQUEST_STOPPED,
+ INVENTORY_REQUEST_PENDING,
+ INVENTORY_XFER
+ };
+ EInventoryRequestState mInvRequestState;
+ U64 mInvRequestXFerId;
+ BOOL mInventoryDirty;
+
LLViewerRegion *mRegionp; // Region that this object belongs to.
- F64 mInvRequestExpireTime;
- BOOL mInventoryDirty;
BOOL mDead;
BOOL mOrphaned; // This is an orphaned child
BOOL mUserSelected; // Cached user select information
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index fe8f54b900..1425b3d42e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8434,6 +8434,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
if (isSelf()
&& attached_object
&& attached_object->isHUDAttachment()
+ && !attached_object->isTempAttachment()
&& attached_object->mDrawable)
{
textures.clear();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 4aef6480cb..8d86623665 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -80,13 +80,14 @@
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
+static const F32 MINIMUM_RIGGED_RADIUS = 0.05f;
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
BOOL gAnimateTextures = TRUE;
//extern BOOL gHideSelectedObjects;
F32 LLVOVolume::sLODFactor = 1.f;
-F32 LLVOVolume::sRiggedFactorMultiplier = 6.f;
+F32 LLVOVolume::sRiggedLODCompensation = 6.5f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
@@ -1254,23 +1255,39 @@ BOOL LLVOVolume::calcLOD()
}
// Note: when changing, take note that a lot of rigged meshes have only one LOD.
- lod_factor *= LLVOVolume::sRiggedFactorMultiplier;
distance = avatar->mDrawable->mDistanceWRTCamera;
F32 avatar_radius = avatar->getBinRadius();
- F32 object_radius;
- if (mDrawable.notNull() && !mDrawable->isDead())
+ F32 object_radius = 0;
+
+ LLDrawable* drawablep = mDrawable.get();
+ while (!drawablep->isRoot())
{
- const LLVector4a* ext = mDrawable->getSpatialExtents();
+ drawablep = drawablep->getParent();
+ }
+
+ // Mesh can consist of multiple objects that have to be treated as one item or we will
+ // get strange deformations or partially missing meshes (smallest elements will disappear)
+ LLSpatialBridge* bridge = drawablep->getSpatialBridge();
+ if (bridge)
+ {
+ const LLVector4a* ext = bridge->getSpatialExtents();
LLVector4a diff;
diff.setSub(ext[1], ext[0]);
object_radius = diff.getLength3().getF32();
}
- else
+
+ if (object_radius <= 0)
{
- object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length();
+ // bridge missing or somehow not updated
+ const LLVector4a* ext = mDrawable->getSpatialExtents();
+ LLVector4a diff;
+ diff.setSub(ext[1], ext[0]);
+ object_radius = diff.getLength3().getF32();
}
- radius = object_radius * LLVOVolume::sRiggedFactorMultiplier;
- radius = llmin(radius, avatar_radius);
+
+ // sRiggedLODCompensation is made to compensate for missing lower lods
+ radius = object_radius * LLVOVolume::sRiggedLODCompensation;
+ radius = llclamp(radius, MINIMUM_RIGGED_RADIUS, avatar_radius);
}
else
{
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index ca9917069b..ff005f8dc5 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -379,7 +379,7 @@ private:
public:
static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop
static F32 sLODFactor; // LOD scale factor
- static F32 sRiggedFactorMultiplier; // Worn rigged LOD scale factor multiplier
+ static F32 sRiggedLODCompensation; // HACK: worn rigged LODs often have only high lod, so we are bumping them up withing avatar's visibility
static F32 sDistanceFactor; // LOD distance factor
static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index bc8166fcce..65ab3f001f 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10275,6 +10275,22 @@ You have been teleported by the object '[OBJECT_NAME]' owned by an unknown user.
<notification
icon="alertmodal.tga"
+ name="StandDeniedByObject"
+ type="notify">
+ <tag>fail</tag>
+'[OBJECT_NAME]' will not allow you to stand at this time.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ResitDeniedByObject"
+ type="notify">
+ <tag>fail</tag>
+'[OBJECT_NAME]' will not allow you to change your seat at this time.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantCreateObjectRegionFull"
type="notify">
<tag>fail</tag>