summaryrefslogtreecommitdiff
path: root/indra/newview/llselectmgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llselectmgr.cpp')
-rw-r--r--indra/newview/llselectmgr.cpp629
1 files changed, 420 insertions, 209 deletions
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ed7c7dce12..fb60b1ece7 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2,37 +2,32 @@
* @file llselectmgr.cpp
* @brief A manager for selected objects and faces.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
// file include
+#define LLSELECTMGR_CPP
#include "llselectmgr.h"
// library includes
@@ -40,9 +35,12 @@
#include "lldbstrings.h"
#include "lleconomy.h"
#include "llgl.h"
+#include "llmediaentry.h"
#include "llrender.h"
+#include "llnotifications.h"
#include "llpermissions.h"
#include "llpermissionsflags.h"
+#include "lltrans.h"
#include "llundo.h"
#include "lluuid.h"
#include "llvolume.h"
@@ -52,18 +50,23 @@
// viewer includes
#include "llagent.h"
+#include "llagentcamera.h"
#include "llviewerwindow.h"
#include "lldrawable.h"
#include "llfloaterinspect.h"
#include "llfloaterproperties.h"
#include "llfloaterreporter.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llframetimer.h"
+#include "llfocusmgr.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llinventorymodel.h"
#include "llmenugl.h"
#include "llmutelist.h"
+#include "llsidepaneltaskinfo.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "lltool.h"
@@ -73,7 +76,9 @@
#include "llui.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
#include "llviewermenu.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
@@ -95,6 +100,7 @@ const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f;
const S32 MAX_ACTION_QUEUE_SIZE = 20;
const S32 MAX_SILS_PER_FRAME = 50;
const S32 MAX_OBJECTS_PER_PACKET = 254;
+const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF;
//
// Globals
@@ -167,6 +173,8 @@ LLObjectSelection *get_null_object_selection()
return sNullSelection;
}
+// Build time optimization, generate this function once here
+template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance();
//-----------------------------------------------------------------------------
// LLSelectMgr()
@@ -187,12 +195,12 @@ LLSelectMgr::LLSelectMgr()
sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim");
sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim");
- sSilhouetteParentColor =gSavedSkinSettings.getColor("SilhouetteParentColor");
- sSilhouetteChildColor = gSavedSkinSettings.getColor("SilhouetteChildColor");
- sHighlightParentColor = gSavedSkinSettings.getColor("HighlightParentColor");
- sHighlightChildColor = gSavedSkinSettings.getColor("HighlightChildColor");
- sHighlightInspectColor = gSavedSkinSettings.getColor("HighlightInspectColor");
- sContextSilhouetteColor = gSavedSkinSettings.getColor("ContextSilhouetteColor")*0.5f;
+ sSilhouetteParentColor =LLUIColorTable::instance().getColor("SilhouetteParentColor");
+ sSilhouetteChildColor = LLUIColorTable::instance().getColor("SilhouetteChildColor");
+ sHighlightParentColor = LLUIColorTable::instance().getColor("HighlightParentColor");
+ sHighlightChildColor = LLUIColorTable::instance().getColor("HighlightChildColor");
+ sHighlightInspectColor = LLUIColorTable::instance().getColor("HighlightInspectColor");
+ sContextSilhouetteColor = LLUIColorTable::instance().getColor("ContextSilhouetteColor")*0.5f;
sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
@@ -206,7 +214,8 @@ LLSelectMgr::LLSelectMgr()
mHoverObjects = new LLObjectSelection();
mHighlightedObjects = new LLObjectSelection();
-
+ mForceSelection = FALSE;
+ mShowSelection = FALSE;
}
@@ -389,7 +398,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj,
}
// Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
root->addThisAndNonJointChildren(objects);
addAsFamily(objects, add_to_end);
@@ -435,7 +444,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV
BOOL send_to_sim)
{
// Collect all of the objects, children included
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
//clear primary object (no primary object)
mSelectedObjects->mPrimaryObject = NULL;
@@ -539,7 +548,7 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
object_found = TRUE;
break; // must break here, may have removed multiple objects from list
}
- else if (object->isAvatar())
+ else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id)
{
// It's possible the item being removed has an avatar sitting on it
// So remove the avatar that is sitting on the object.
@@ -559,7 +568,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s
if(!object->isSelected()) return;
// Collect all of the objects, and remove them
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
if (include_entire_object)
{
@@ -773,48 +782,66 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
}
-LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp)
+LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face)
{
- // Always blitz hover list when setting
- mHoverObjects->deleteAllNodes();
-
if (!objectp)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select yourself
if (objectp->mID == gAgentID)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select land
if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
- // Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
+ mHoverObjects->mPrimaryObject = objectp;
+
objectp = objectp->getRootEdit();
- objectp->addThisAndNonJointChildren(objects);
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
+ // is the requested object the same as the existing hover object root?
+ // NOTE: there is only ever one linked set in mHoverObjects
+ if (mHoverObjects->getFirstRootObject() != objectp)
{
- LLViewerObject* cur_objectp = *iter;
- LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
- mHoverObjects->addNodeAtEnd(nodep);
+
+ // Collect all of the objects
+ std::vector<LLViewerObject*> objects;
+ objectp = objectp->getRootEdit();
+ objectp->addThisAndNonJointChildren(objects);
+
+ mHoverObjects->deleteAllNodes();
+ for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
+ iter != objects.end(); ++iter)
+ {
+ LLViewerObject* cur_objectp = *iter;
+ LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
+ nodep->selectTE(face, TRUE);
+ mHoverObjects->addNodeAtEnd(nodep);
+ }
+
+ requestObjectPropertiesFamily(objectp);
}
- requestObjectPropertiesFamily(objectp);
return mHoverObjects;
}
LLSelectNode *LLSelectMgr::getHoverNode()
{
- return getHoverObjects()->getFirstRootNode();
+ return mHoverObjects->getFirstRootNode();
+}
+
+LLSelectNode *LLSelectMgr::getPrimaryHoverNode()
+{
+ return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject];
}
void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
@@ -829,8 +856,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) ||
- (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
{
// only select my own objects
return;
@@ -1281,7 +1308,7 @@ void LLSelectMgr::promoteSelectionToRoot()
//-----------------------------------------------------------------------------
void LLSelectMgr::demoteSelectionToIndividuals()
{
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
iter != getSelection()->root_end(); iter++)
@@ -1290,7 +1317,7 @@ void LLSelectMgr::demoteSelectionToIndividuals()
object->addThisAndNonJointChildren(objects);
}
- if (objects.getLength())
+ if (!objects.empty())
{
deselectAll();
for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
@@ -1424,7 +1451,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
// Texture picker defaults aren't inventory items
// * Don't need to worry about permissions for them
// * Can just apply the texture and be done with it.
- objectp->setTEImage(te, gImageList.getImage(mImageID, TRUE, FALSE));
+ objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
return true;
}
@@ -1442,7 +1469,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
object->sendTEUpdate();
// 1 particle effect per object
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
- effectp->setSourceObject(gAgent.getAvatarObject());
+ effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject(object);
effectp->setDuration(LL_HUD_DUR_SHORT);
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
@@ -1580,7 +1607,7 @@ BOOL LLSelectMgr::selectionRevertTextures()
}
else
{
- object->setTEImage(te, gImageList.getImage(id));
+ object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
}
@@ -1708,47 +1735,79 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
getSelection()->applyToObjects(&sendfunc);
}
-void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url)
-{
- U8 media_flags = LLTextureEntry::MF_NONE;
- if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE)
- {
- media_flags = LLTextureEntry::MF_WEB_PAGE;
- }
-
+// This function expects media_data to be a map containing relevant
+// media data name/value pairs (e.g. home_url, etc.)
+void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data)
+{
struct f : public LLSelectedTEFunctor
{
U8 mMediaFlags;
- f(const U8& t) : mMediaFlags(t) {}
+ const LLSD &mMediaData;
+ f(const U8& t, const LLSD& d) : mMediaFlags(t), mMediaData(d) {}
bool apply(LLViewerObject* object, S32 te)
{
if (object->permModify())
{
- // update viewer side color in anticipation of update from simulator
- object->setTEMediaFlags(te, mMediaFlags);
+ // If we are adding media, then check the current state of the
+ // media data on this face.
+ // - If it does not have media, AND we are NOT setting the HOME URL, then do NOT add media to this
+ // face.
+ // - If it does not have media, and we ARE setting the HOME URL, add media to this face.
+ // - If it does already have media, add/update media to/on this face
+ // If we are removing media, just do it (ignore the passed-in LLSD).
+ if (mMediaFlags & LLTextureEntry::MF_HAS_MEDIA)
+ {
+ llassert(mMediaData.isMap());
+ const LLTextureEntry *texture_entry = object->getTE(te);
+ if (!mMediaData.isMap() ||
+ (NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY))
+ {
+ // skip adding/updating media
+ }
+ else {
+ // Add/update media
+ object->setTEMediaFlags(te, mMediaFlags);
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+ llassert(NULL != vo);
+ if (NULL != vo)
+ {
+ vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/);
+ }
+ }
+ }
+ else
+ {
+ // delete media (or just set the flags)
+ object->setTEMediaFlags(te, mMediaFlags);
+ }
}
return true;
}
- } setfunc(media_flags);
+ } setfunc(media_type, media_data);
getSelection()->applyToTEs(&setfunc);
-
- struct g : public LLSelectedObjectFunctor
+
+ struct f2 : public LLSelectedObjectFunctor
{
- U8 media_type;
- const std::string& media_url ;
- g(U8 a, const std::string& b) : media_type(a), media_url(b) {}
virtual bool apply(LLViewerObject* object)
{
if (object->permModify())
{
object->sendTEUpdate();
- object->setMediaType(media_type);
- object->setMediaURL(media_url);
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+ llassert(NULL != vo);
+ // It's okay to skip this object if hasMedia() is false...
+ // the sendTEUpdate() above would remove all media data if it were
+ // there.
+ if (NULL != vo && vo->hasMedia())
+ {
+ // Send updated media data FOR THE ENTIRE OBJECT
+ vo->sendMediaDataUpdate();
+ }
}
return true;
}
- } sendfunc(media_type, media_url);
- getSelection()->applyToObjects(&sendfunc);
+ } func2;
+ mSelectedObjects->applyToObjects( &func2 );
}
void LLSelectMgr::selectionSetGlow(F32 glow)
@@ -2213,6 +2272,26 @@ BOOL LLSelectMgr::selectGetAllValid()
return TRUE;
}
+//-----------------------------------------------------------------------------
+// selectGetAllValidAndObjectsFound() - return TRUE if selections are
+// valid and objects are found.
+//
+// For EXT-3114 - same as selectGetModify() without the modify check.
+//-----------------------------------------------------------------------------
+BOOL LLSelectMgr::selectGetAllValidAndObjectsFound()
+{
+ for (LLObjectSelection::iterator iter = getSelection()->begin();
+ iter != getSelection()->end(); iter++ )
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ if( !object || !node->mValid )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
//-----------------------------------------------------------------------------
// selectGetModify() - return TRUE if current agent can modify all
@@ -2342,6 +2421,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
}
if (first_id.isNull())
{
+ name = LLTrans::getString("AvatarNameNobody");
return FALSE;
}
@@ -2349,11 +2429,11 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
if (identical)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL("agent", first_id, "inspect").getSLURLString();
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2408,20 +2488,20 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull() && !first_group_owned);
if (first_group_owned)
{
- name.assign( "(Group Owned)");
+ name = LLSLURL("group", first_id, "inspect").getSLURLString();
}
else if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL("agent", first_id, "inspect").getSLURLString();
}
else
{
- name.assign("Public");
+ name = LLTrans::getString("AvatarNameNobody");
}
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2472,7 +2552,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull());
if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL("agent", first_id, "inspect").getSLURLString();
}
else
{
@@ -2768,7 +2848,7 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response,
case 0:
{
// TODO: Make sure you have delete permissions on all of them.
- LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
// attempt to derez into the trash.
LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id);
LLSelectMgr::getInstance()->sendListToRegions("DeRezObject",
@@ -2787,7 +2867,7 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response,
effectp->setDuration(duration);
}
- gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
+ gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
// Keep track of how many objects have been deleted.
F64 obj_delete_count = LLViewerStats::getInstance()->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT);
@@ -3347,7 +3427,7 @@ void LLSelectMgr::deselectAll()
{
return;
}
-
+
// Zap the angular velocity, as the sim will set it to zero
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
iter != mSelectedObjects->end(); iter++ )
@@ -3429,7 +3509,7 @@ void LLSelectMgr::deselectAllIfTooFar()
// HACK: Don't deselect when we're navigating to rate an object's
// owner or creator. JC
- if (gPieObject->getVisible() || gPieRate->getVisible() )
+ if (gMenuObject->getVisible())
{
return;
}
@@ -3437,6 +3517,7 @@ void LLSelectMgr::deselectAllIfTooFar()
LLVector3d selectionCenter = getSelectionCenterGlobal();
if (gSavedSettings.getBOOL("LimitSelectDistance")
&& (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar())
+ && (mSelectedObjects->getPrimaryObject() != LLViewerMediaFocus::getInstance()->getFocusedObject())
&& !mSelectedObjects->isAttachment()
&& !selectionCenter.isExactlyZero())
{
@@ -3528,11 +3609,11 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
// Attachments
//----------------------------------------------------------------------
-void LLSelectMgr::sendAttach(U8 attachment_point)
+void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
{
LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
- if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
+ if (!attach_object || !isAgentAvatarValid() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
{
return;
}
@@ -3540,8 +3621,15 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
BOOL build_mode = LLToolMgr::getInstance()->inEdit();
// Special case: Attach to default location for this object.
if (0 == attachment_point ||
- get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))
+ get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))
{
+ if (!replace || attachment_point != 0)
+ {
+ // If we know the attachment point then we got here by clicking an
+ // "Attach to..." context menu item, so we should add, not replace.
+ attachment_point |= ATTACHMENT_ADD;
+ }
+
sendListToRegions(
"ObjectAttach",
packAgentIDAndSessionAndAttachment,
@@ -4302,7 +4390,7 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i);
//unpack TE IDs
- std::vector<LLUUID> texture_ids;
+ uuid_vec_t texture_ids;
S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID);
if (size > 0)
{
@@ -4451,8 +4539,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
// the reporter widget askes the server for info about picked objects
if (request_flags & COMPLAINT_REPORT_REQUEST )
{
- EReportType report_type = COMPLAINT_REPORT ;
- LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type);
+ LLFloaterReporter *reporterp = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
if (reporterp)
{
std::string fullname;
@@ -4476,7 +4563,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
return (node->getObject() && node->getObject()->mID == mID);
}
} func(id);
- LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func);
+ LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func);
if (node)
{
@@ -4538,12 +4625,12 @@ void LLSelectMgr::updateSilhouettes()
{
S32 num_sils_genned = 0;
- LLVector3d cameraPos = gAgent.getCameraPositionGlobal();
- F32 currentCameraZoom = gAgent.getCurrentCameraBuildOffset();
+ LLVector3d cameraPos = gAgentCamera.getCameraPositionGlobal();
+ F32 currentCameraZoom = gAgentCamera.getCurrentCameraBuildOffset();
if (!mSilhouetteImagep)
{
- mSilhouetteImagep = gImageList.getImageFromFile("silhouette.j2c", TRUE, TRUE);
+ mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI);
}
mHighlightedObjects->cleanupNodes();
@@ -4560,59 +4647,12 @@ void LLSelectMgr::updateSilhouettes()
} func;
getSelection()->applyToObjects(&func);
- mLastCameraPos = gAgent.getCameraPositionGlobal();
+ mLastCameraPos = gAgentCamera.getCameraPositionGlobal();
}
std::vector<LLViewerObject*> changed_objects;
- if (mSelectedObjects->getNumNodes())
- {
- //gGLSPipelineSelection.set();
-
- //mSilhouetteImagep->bindTexture();
- //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
-
- for (S32 pass = 0; pass < 2; pass++)
- {
- for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
- iter != mSelectedObjects->end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* objectp = node->getObject();
- if (!objectp)
- continue;
- // do roots first, then children so that root flags are cleared ASAP
- BOOL roots_only = (pass == 0);
- BOOL is_root = (objectp->isRootEdit());
- if (roots_only != is_root || objectp->mDrawable.isNull())
- {
- continue;
- }
-
- if (!node->mSilhouetteExists
- || objectp->isChanged(LLXform::SILHOUETTE)
- || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
- {
- if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
- {
- generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
- changed_objects.push_back(objectp);
- }
- else if (objectp->isAttachment())
- {
- //RN: hack for orthogonal projection of HUD attachments
- LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
- if (attachment_pt && attachment_pt->getIsHUDAttachment())
- {
- LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
- generateSilhouette(node, camera_pos);
- }
- }
- }
- }
- }
- }
-
+ updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects);
if (mRectSelectedObjects.size() > 0)
{
//gGLSPipelineSelection.set();
@@ -4806,6 +4846,56 @@ void LLSelectMgr::updateSilhouettes()
//gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
+void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector<LLViewerObject*>& changed_objects)
+{
+ if (object_handle->getNumNodes())
+ {
+ //gGLSPipelineSelection.set();
+
+ //mSilhouetteImagep->bindTexture();
+ //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
+
+ for (S32 pass = 0; pass < 2; pass++)
+ {
+ for (LLObjectSelection::iterator iter = object_handle->begin();
+ iter != object_handle->end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* objectp = node->getObject();
+ if (!objectp)
+ continue;
+ // do roots first, then children so that root flags are cleared ASAP
+ BOOL roots_only = (pass == 0);
+ BOOL is_root = (objectp->isRootEdit());
+ if (roots_only != is_root || objectp->mDrawable.isNull())
+ {
+ continue;
+ }
+
+ if (!node->mSilhouetteExists
+ || objectp->isChanged(LLXform::SILHOUETTE)
+ || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
+ {
+ if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
+ {
+ generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
+ changed_objects.push_back(objectp);
+ }
+ else if (objectp->isAttachment())
+ {
+ //RN: hack for orthogonal projection of HUD attachments
+ LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
+ if (attachment_pt && attachment_pt->getIsHUDAttachment())
+ {
+ LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
+ generateSilhouette(node, camera_pos);
+ }
+ }
+ }
+ }
+ }
+ }
+}
void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
if (!mRenderSilhouettes)
@@ -4813,28 +4903,29 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
return;
}
- gGL.getTexUnit(0)->bind(mSilhouetteImagep.get());
+ gGL.getTexUnit(0)->bind(mSilhouetteImagep);
LLGLSPipelineSelection gls_select;
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
LLGLEnable blend(GL_BLEND);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if (for_hud && avatar)
+ if (isAgentAvatarValid() && for_hud)
{
- LLBBox hud_bbox = avatar->getHUDBBox();
+ LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
- F32 cur_zoom = gAgent.mHUDCurZoom;
+ F32 cur_zoom = gAgentCamera.mHUDCurZoom;
// set up transform to encompass bounding box of HUD
glMatrixMode(GL_PROJECTION);
- glPushMatrix();
+ gGL.pushMatrix();
glLoadIdentity();
F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gGL.pushMatrix();
+ gGL.pushUIMatrix();
+ gGL.loadUIIdentity();
glLoadIdentity();
glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame
glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
@@ -4842,8 +4933,22 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
}
if (mSelectedObjects->getNumNodes())
{
- LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
-
+ LLUUID inspect_item_id= LLUUID::null;
+ LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect");
+ if(inspect_instance && inspect_instance->getVisible())
+ {
+ inspect_item_id = inspect_instance->getSelectedUUID();
+ }
+ else
+ {
+ LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel();
+ if (panel_task_info)
+ {
+ inspect_item_id = panel_task_info->getSelectedUUID();
+ }
+ }
+
+ LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID();
for (S32 pass = 0; pass < 2; pass++)
{
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
@@ -4857,7 +4962,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
continue;
}
- if(objectp->getID() == inspect_item_id)
+ if (objectp->getID() == focus_item_id)
+ {
+ node->renderOneSilhouette(gFocusMgr.getFocusColor());
+ }
+ else if(objectp->getID() == inspect_item_id)
{
node->renderOneSilhouette(sHighlightInspectColor);
}
@@ -4911,13 +5020,14 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
}
}
- if (for_hud && avatar)
+ if (isAgentAvatarValid() && for_hud)
{
glMatrixMode(GL_PROJECTION);
- glPopMatrix();
+ gGL.popMatrix();
glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gGL.popMatrix();
+ gGL.popUIMatrix();
stop_glerror();
}
@@ -4939,6 +5049,16 @@ void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_
// Utility classes
//
LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
+: mObject(object),
+ mIndividualSelection(FALSE),
+ mTransient(FALSE),
+ mValid(FALSE),
+ mPermissions(new LLPermissions()),
+ mInventorySerial(0),
+ mSilhouetteExists(FALSE),
+ mDuplicated(FALSE),
+ mTESelectMask(0),
+ mLastTESelected(0)
{
mObject = object;
selectAllTEs(FALSE);
@@ -4960,11 +5080,7 @@ LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
{
- S32 i;
- for (i = 0; i < SELECT_MAX_TES; i++)
- {
- mTESelected[i] = nodep.mTESelected[i];
- }
+ mTESelectMask = nodep.mTESelectMask;
mLastTESelected = nodep.mLastTESelected;
mIndividualSelection = nodep.mIndividualSelection;
@@ -4979,6 +5095,7 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
mName = nodep.mName;
mDescription = nodep.mDescription;
mCategory = nodep.mCategory;
+ mInventorySerial = 0;
mSavedPositionLocal = nodep.mSavedPositionLocal;
mSavedPositionGlobal = nodep.mSavedPositionGlobal;
mSavedScale = nodep.mSavedScale;
@@ -5017,10 +5134,7 @@ LLSelectNode::~LLSelectNode()
void LLSelectNode::selectAllTEs(BOOL b)
{
- for (S32 i = 0; i < SELECT_MAX_TES; i++)
- {
- mTESelected[i] = b;
- }
+ mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0;
mLastTESelected = 0;
}
@@ -5030,7 +5144,15 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected)
{
return;
}
- mTESelected[te_index] = selected;
+ S32 mask = 0x1 << te_index;
+ if(selected)
+ {
+ mTESelectMask |= mask;
+ }
+ else
+ {
+ mTESelectMask &= ~mask;
+ }
mLastTESelected = te_index;
}
@@ -5040,7 +5162,7 @@ BOOL LLSelectNode::isTESelected(S32 te_index)
{
return FALSE;
}
- return mTESelected[te_index];
+ return (mTESelectMask & (0x1 << te_index)) != 0;
}
S32 LLSelectNode::getLastSelectedTE()
@@ -5083,13 +5205,13 @@ void LLSelectNode::saveColors()
}
}
-void LLSelectNode::saveTextures(const std::vector<LLUUID>& textures)
+void LLSelectNode::saveTextures(const uuid_vec_t& textures)
{
if (mObject.notNull())
{
mSavedTextures.clear();
- for (std::vector<LLUUID>::const_iterator texture_it = textures.begin();
+ for (uuid_vec_t::const_iterator texture_it = textures.begin();
texture_it != textures.end(); ++texture_it)
{
mSavedTextures.push_back(*texture_it);
@@ -5254,7 +5376,10 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
}
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gGL.pushMatrix();
+ gGL.pushUIMatrix();
+ gGL.loadUIIdentity();
+
if (!is_hud_object)
{
glLoadIdentity();
@@ -5271,9 +5396,9 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
if (volume)
{
F32 silhouette_thickness;
- if (is_hud_object && gAgent.getAvatarObject())
+ if (isAgentAvatarValid() && is_hud_object)
{
- silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.mHUDCurZoom;
+ silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgentCamera.mHUDCurZoom;
}
else
{
@@ -5293,7 +5418,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
LLGLEnable fog(GL_FOG);
glFogi(GL_FOG_MODE, GL_LINEAR);
float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec();
- LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
+ LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgentCamera.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
glFogf(GL_FOG_START, d);
glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
glFogfv(GL_FOG_COLOR, fogCol.mV);
@@ -5373,34 +5498,52 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
gGL.end();
gGL.flush();
}
- glPopMatrix();
+ gGL.popMatrix();
+ gGL.popUIMatrix();
}
//
// Utility Functions
//
-// Update everyone who cares about the selection list
+// *DEPRECATED: See header comment.
void dialog_refresh_all()
{
- if (gNoRender)
- {
- return;
- }
+ // This is the easiest place to fire the update signal, as it will
+ // make cleaning up the functions below easier. Also, sometimes entities
+ // outside the selection manager change properties of selected objects
+ // and call into this function. Yuck.
+ LLSelectMgr::getInstance()->mUpdateSignal();
- //could refresh selected object info in toolbar here
+ // *TODO: Eliminate all calls into outside classes below, make those
+ // objects register with the update signal.
gFloaterTools->dirty();
- gPieObject->needsArrange();
+ gMenuObject->needsArrange();
- if( gPieAttachment->getVisible() )
+ if( gMenuAttachmentSelf->getVisible() )
{
- gPieAttachment->arrange();
+ gMenuAttachmentSelf->arrange();
+ }
+ if( gMenuAttachmentOther->getVisible() )
+ {
+ gMenuAttachmentOther->arrange();
}
LLFloaterProperties::dirtyAll();
- LLFloaterInspect::dirty();
+
+ LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect");
+ if(inspect_instance)
+ {
+ inspect_instance->dirty();
+ }
+
+ LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel();
+ if (panel_task_info)
+ {
+ panel_task_info->dirty();
+ }
}
S32 get_family_count(LLViewerObject *parent)
@@ -5463,20 +5606,20 @@ void LLSelectMgr::updateSelectionCenter()
{
mSelectedObjects->mSelectType = getSelectTypeForObject(object);
- if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+ if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid())
{
- mPauseRequest = gAgent.getAvatarObject()->requestPause();
+ mPauseRequest = gAgentAvatarp->requestPause();
}
else
{
mPauseRequest = NULL;
}
- if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject())
+ if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid())
{
// reset hud ZOOM
- gAgent.mHUDTargetZoom = 1.f;
- gAgent.mHUDCurZoom = 1.f;
+ gAgentCamera.mHUDTargetZoom = 1.f;
+ gAgentCamera.mHUDCurZoom = 1.f;
}
mShowSelection = FALSE;
@@ -5486,6 +5629,10 @@ void LLSelectMgr::updateSelectionCenter()
LLVector3d select_center;
// keep a list of jointed objects for showing the joint HUDEffects
+ // Initialize the bounding box to the root prim, so the BBox orientation
+ // matches the root prim's (affecting the orientation of the manipulators).
+ bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() );
+
std::vector < LLViewerObject *> jointed_objects;
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
@@ -5495,10 +5642,10 @@ void LLSelectMgr::updateSelectionCenter()
LLViewerObject* object = node->getObject();
if (!object)
continue;
- LLViewerObject *myAvatar = gAgent.getAvatarObject();
+
LLViewerObject *root = object->getRootEdit();
if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment
- !root->isChild(myAvatar) && // not the object you're sitting on
+ !root->isChild(gAgentAvatarp) && // not the object you're sitting on
!object->isAvatar()) // not another avatar
{
mShowSelection = TRUE;
@@ -5568,26 +5715,26 @@ void LLSelectMgr::updatePointAt()
select_offset.setVec(pick.mObjectOffset);
select_offset.rotVec(~click_object->getRenderRotation());
- gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset);
- gAgent.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset);
+ gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset);
+ gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset);
}
else
{
// didn't click on an object this time, revert to pointing at center of first object
- gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
- gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
+ gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
+ gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
}
}
else
{
- gAgent.setPointAt(POINTAT_TARGET_CLEAR);
- gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
+ gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR);
+ gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
}
}
else
{
- gAgent.setPointAt(POINTAT_TARGET_CLEAR);
- gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
+ gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR);
+ gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
}
}
@@ -5641,8 +5788,22 @@ void LLSelectMgr::redo()
//-----------------------------------------------------------------------------
BOOL LLSelectMgr::canDoDelete() const
{
+ bool can_delete = false;
+ // This function is "logically const" - it does not change state in
+ // a way visible outside the selection manager.
+ LLSelectMgr* self = const_cast<LLSelectMgr*>(this);
+ LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject();
// Note: Can only delete root objects (see getFirstDeleteableObject() for more info)
- return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG
+ if (obj!= NULL)
+ {
+ // all the faces needs to be selected
+ if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES ))
+ {
+ can_delete = true;
+ }
+ }
+
+ return can_delete;
}
//-----------------------------------------------------------------------------
@@ -5763,20 +5924,41 @@ BOOL LLSelectMgr::setForceSelection(BOOL force)
void LLSelectMgr::resetAgentHUDZoom()
{
- gAgent.mHUDTargetZoom = 1.f;
- gAgent.mHUDCurZoom = 1.f;
+ gAgentCamera.mHUDTargetZoom = 1.f;
+ gAgentCamera.mHUDCurZoom = 1.f;
}
void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const
{
- target_zoom = gAgent.mHUDTargetZoom;
- current_zoom = gAgent.mHUDCurZoom;
+ target_zoom = gAgentCamera.mHUDTargetZoom;
+ current_zoom = gAgentCamera.mHUDCurZoom;
}
void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
{
- gAgent.mHUDTargetZoom = target_zoom;
- gAgent.mHUDCurZoom = current_zoom;
+ gAgentCamera.mHUDTargetZoom = target_zoom;
+ gAgentCamera.mHUDCurZoom = current_zoom;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Object selection iterator helpers
+/////////////////////////////////////////////////////////////////////////////
+bool LLObjectSelection::is_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && (object->isRootEdit() || object->isJointChild());
}
LLObjectSelection::LLObjectSelection() :
@@ -6010,6 +6192,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first
return result;
}
+BOOL LLObjectSelection::isMultipleTESelected()
+{
+ BOOL te_selected = FALSE;
+ // ...all faces
+ for (LLObjectSelection::iterator iter = begin();
+ iter != end(); iter++)
+ {
+ LLSelectNode* nodep = *iter;
+ for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ {
+ if(nodep->isTESelected(i))
+ {
+ if(te_selected)
+ {
+ return TRUE;
+ }
+ te_selected = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
//-----------------------------------------------------------------------------
// contains()
//-----------------------------------------------------------------------------
@@ -6033,8 +6238,14 @@ BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te)
LLSelectNode* nodep = *iter;
if (nodep->getObject() == object)
{
+ // Optimization
+ if (nodep->getTESelectMask() == TE_SELECT_MASK_ALL)
+ {
+ return TRUE;
+ }
+
BOOL all_selected = TRUE;
- for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ for (S32 i = 0; i < object->getNumTEs(); i++)
{
all_selected = all_selected && nodep->isTESelected(i);
}