llselectmgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:177k
- /**
- * @file llselectmgr.cpp
- * @brief A manager for selected objects and faces.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, Linden Research, Inc.
- *
- * 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
- *
- * 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
- *
- * 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.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- // file include
- #define LLSELECTMGR_CPP
- #include "llselectmgr.h"
- // library includes
- #include "llcachename.h"
- #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"
- #include "message.h"
- #include "object_flags.h"
- #include "llquaternion.h"
- // viewer includes
- #include "llagent.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"
- #include "lltooldraganddrop.h"
- #include "lltoolmgr.h"
- #include "lltoolpie.h"
- #include "llui.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewertexturelist.h"
- #include "llviewermedia.h"
- #include "llviewermediafocus.h"
- #include "llviewermenu.h"
- #include "llviewerobject.h"
- #include "llviewerobjectlist.h"
- #include "llviewerregion.h"
- #include "llviewerstats.h"
- #include "llvoavatarself.h"
- #include "llvovolume.h"
- #include "pipeline.h"
- #include "llglheaders.h"
- LLViewerObject* getSelectedParentObject(LLViewerObject *object) ;
- //
- // Consts
- //
- const S32 NUM_SELECTION_UNDO_ENTRIES = 200;
- 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
- //
- //BOOL gDebugSelectMgr = FALSE;
- //BOOL gHideSelectedObjects = FALSE;
- //BOOL gAllowSelectAvatar = FALSE;
- BOOL LLSelectMgr::sRectSelectInclusive = TRUE;
- BOOL LLSelectMgr::sRenderHiddenSelections = TRUE;
- BOOL LLSelectMgr::sRenderLightRadius = FALSE;
- F32 LLSelectMgr::sHighlightThickness = 0.f;
- F32 LLSelectMgr::sHighlightUScale = 0.f;
- F32 LLSelectMgr::sHighlightVScale = 0.f;
- F32 LLSelectMgr::sHighlightAlpha = 0.f;
- F32 LLSelectMgr::sHighlightAlphaTest = 0.f;
- F32 LLSelectMgr::sHighlightUAnim = 0.f;
- F32 LLSelectMgr::sHighlightVAnim = 0.f;
- LLColor4 LLSelectMgr::sSilhouetteParentColor;
- LLColor4 LLSelectMgr::sSilhouetteChildColor;
- LLColor4 LLSelectMgr::sHighlightInspectColor;
- LLColor4 LLSelectMgr::sHighlightParentColor;
- LLColor4 LLSelectMgr::sHighlightChildColor;
- LLColor4 LLSelectMgr::sContextSilhouetteColor;
- static LLObjectSelection *get_null_object_selection();
- template<>
- const LLSafeHandle<LLObjectSelection>::NullFunc
- LLSafeHandle<LLObjectSelection>::sNullFunc = get_null_object_selection;
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // struct LLDeRezInfo
- //
- // Used to keep track of important derez info.
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- struct LLDeRezInfo
- {
- EDeRezDestination mDestination;
- LLUUID mDestinationID;
- LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) :
- mDestination(dest), mDestinationID(dest_id) {}
- };
- //
- // Imports
- //
- static LLPointer<LLObjectSelection> sNullSelection;
- //
- // Functions
- //
- void LLSelectMgr::cleanupGlobals()
- {
- sNullSelection = NULL;
- LLSelectMgr::getInstance()->clearSelections();
- }
- LLObjectSelection *get_null_object_selection()
- {
- if (sNullSelection.isNull())
- {
- sNullSelection = new LLObjectSelection;
- }
- return sNullSelection;
- }
- // Build time optimization, generate this function once here
- template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance();
- //-----------------------------------------------------------------------------
- // LLSelectMgr()
- //-----------------------------------------------------------------------------
- LLSelectMgr::LLSelectMgr()
- : mHideSelectedObjects(LLCachedControl<bool>(gSavedSettings, "HideSelectedObjects", FALSE)),
- mAllowSelectAvatar( LLCachedControl<bool>(gSavedSettings, "AllowSelectAvatar", FALSE)),
- mDebugSelectMgr(LLCachedControl<bool>(gSavedSettings, "DebugSelectMgr", FALSE))
- {
- mTEMode = FALSE;
- mLastCameraPos.clearVec();
- sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness");
- sHighlightUScale = gSavedSettings.getF32("SelectionHighlightUScale");
- sHighlightVScale = gSavedSettings.getF32("SelectionHighlightVScale");
- sHighlightAlpha = gSavedSettings.getF32("SelectionHighlightAlpha");
- sHighlightAlphaTest = gSavedSettings.getF32("SelectionHighlightAlphaTest");
- sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim");
- sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim");
- 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");
-
- mRenderSilhouettes = TRUE;
- mGridMode = GRID_MODE_WORLD;
- gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD);
- mGridValid = FALSE;
- mSelectedObjects = new LLObjectSelection();
- mHoverObjects = new LLObjectSelection();
- mHighlightedObjects = new LLObjectSelection();
- mForceSelection = FALSE;
- mShowSelection = FALSE;
- }
- //-----------------------------------------------------------------------------
- // ~LLSelectMgr()
- //-----------------------------------------------------------------------------
- LLSelectMgr::~LLSelectMgr()
- {
- clearSelections();
- }
- void LLSelectMgr::clearSelections()
- {
- mHoverObjects->deleteAllNodes();
- mSelectedObjects->deleteAllNodes();
- mHighlightedObjects->deleteAllNodes();
- mRectSelectedObjects.clear();
- mGridObjects.deleteAllNodes();
- }
- void LLSelectMgr::update()
- {
- mSelectedObjects->cleanupNodes();
- }
- void LLSelectMgr::updateEffects()
- {
- //keep reference grid objects active
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
- {
- gPipeline.markMoved(drawable);
- }
- return true;
- }
- } func;
- mGridObjects.applyToObjects(&func);
- if (mEffectsTimer.getElapsedTimeF32() > 1.f)
- {
- mSelectedObjects->updateEffects();
- mEffectsTimer.reset();
- }
- }
- void LLSelectMgr::overrideObjectUpdates()
- {
- //override any position updates from simulator on objects being edited
- struct f : public LLSelectedNodeFunctor
- {
- virtual bool apply(LLSelectNode* selectNode)
- {
- LLViewerObject* object = selectNode->getObject();
- if (object && object->permMove())
- {
- if (!selectNode->mLastPositionLocal.isExactlyZero())
- {
- object->setPosition(selectNode->mLastPositionLocal);
- }
- if (selectNode->mLastRotation != LLQuaternion())
- {
- object->setRotation(selectNode->mLastRotation);
- }
- if (!selectNode->mLastScale.isExactlyZero())
- {
- object->setScale(selectNode->mLastScale);
- }
- }
- return true;
- }
- } func;
- getSelection()->applyToNodes(&func);
- }
- //-----------------------------------------------------------------------------
- // Select just the object, not any other group members.
- //-----------------------------------------------------------------------------
- LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
- {
- llassert( object );
- //remember primary object
- mSelectedObjects->mPrimaryObject = object;
- // Don't add an object that is already in the list
- if (object->isSelected() ) {
- // make sure point at position is updated
- updatePointAt();
- gEditMenuHandler = this;
- return NULL;
- }
- if (!canSelectObject(object))
- {
- //make_ui_sound("UISndInvalidOp");
- return NULL;
- }
- // llinfos << "Adding object to selected object list" << llendl;
- // Place it in the list and tag it.
- // This will refresh dialogs.
- addAsIndividual(object, face);
- // Stop the object from moving (this anticipates changes on the
- // simulator in LLTask::userSelect)
- // *FIX: shouldn't zero out these either
- object->setVelocity(LLVector3::zero);
- object->setAcceleration(LLVector3::zero);
- //object->setAngularVelocity(LLVector3::zero);
- object->resetRot();
- // Always send to simulator, so you get a copy of the
- // permissions structure back.
- gMessageSystem->newMessageFast(_PREHASH_ObjectSelect);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
- LLViewerRegion* regionp = object->getRegion();
- gMessageSystem->sendReliable( regionp->getHost());
- updatePointAt();
- updateSelectionCenter();
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- // have selection manager handle edit menu immediately after
- // user selects an object
- if (mSelectedObjects->getObjectCount())
- {
- gEditMenuHandler = this;
- }
- return mSelectedObjects;
- }
- //-----------------------------------------------------------------------------
- // Select the object, parents and children.
- //-----------------------------------------------------------------------------
- LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
- {
- llassert( obj );
- //remember primary object
- mSelectedObjects->mPrimaryObject = obj;
- // This may be incorrect if things weren't family selected before... - djs 07/08/02
- // Don't add an object that is already in the list
- if (obj->isSelected() )
- {
- // make sure pointat position is updated
- updatePointAt();
- gEditMenuHandler = this;
- return NULL;
- }
- if (!canSelectObject(obj))
- {
- //make_ui_sound("UISndInvalidOp");
- return NULL;
- }
- // Since we're selecting a family, start at the root, but
- // don't include an avatar.
- LLViewerObject* root = obj;
-
- while(!root->isAvatar() && root->getParent() && !root->isJointChild())
- {
- LLViewerObject* parent = (LLViewerObject*)root->getParent();
- if (parent->isAvatar())
- {
- break;
- }
- root = parent;
- }
- // Collect all of the objects
- std::vector<LLViewerObject*> objects;
- root->addThisAndNonJointChildren(objects);
- addAsFamily(objects, add_to_end);
- updateSelectionCenter();
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- updatePointAt();
- dialog_refresh_all();
- // Always send to simulator, so you get a copy of the permissions
- // structure back.
- sendSelect();
- // Stop the object from moving (this anticipates changes on the
- // simulator in LLTask::userSelect)
- root->setVelocity(LLVector3::zero);
- root->setAcceleration(LLVector3::zero);
- //root->setAngularVelocity(LLVector3::zero);
- root->resetRot();
- // leave component mode
- if (gSavedSettings.getBOOL("EditLinkedParts"))
- {
- gSavedSettings.setBOOL("EditLinkedParts", FALSE);
- promoteSelectionToRoot();
- }
- // have selection manager handle edit menu immediately after
- // user selects an object
- if (mSelectedObjects->getObjectCount())
- {
- gEditMenuHandler = this;
- }
- return mSelectedObjects;
- }
- //-----------------------------------------------------------------------------
- // Select the object, parents and children.
- //-----------------------------------------------------------------------------
- LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLViewerObject*>& object_list,
- BOOL send_to_sim)
- {
- // Collect all of the objects, children included
- std::vector<LLViewerObject*> objects;
- //clear primary object (no primary object)
- mSelectedObjects->mPrimaryObject = NULL;
- if (object_list.size() < 1)
- {
- return NULL;
- }
-
- // NOTE -- we add the objects in REVERSE ORDER
- // to preserve the order in the mSelectedObjects list
- for (std::vector<LLViewerObject*>::const_reverse_iterator riter = object_list.rbegin();
- riter != object_list.rend(); ++riter)
- {
- LLViewerObject *object = *riter;
- llassert( object );
- if (!canSelectObject(object)) continue;
- object->addThisAndNonJointChildren(objects);
- addAsFamily(objects);
- // Stop the object from moving (this anticipates changes on the
- // simulator in LLTask::userSelect)
- object->setVelocity(LLVector3::zero);
- object->setAcceleration(LLVector3::zero);
- //object->setAngularVelocity(LLVector3::zero);
- object->resetRot();
- }
- updateSelectionCenter();
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- updatePointAt();
- dialog_refresh_all();
- // Almost always send to simulator, so you get a copy of the permissions
- // structure back.
- // JC: The one case where you don't want to do this is if you're selecting
- // all the objects on a sim.
- if (send_to_sim)
- {
- sendSelect();
- }
- // leave component mode
- if (gSavedSettings.getBOOL("EditLinkedParts"))
- {
- gSavedSettings.setBOOL("EditLinkedParts", FALSE);
- promoteSelectionToRoot();
- }
- // have selection manager handle edit menu immediately after
- // user selects an object
- if (mSelectedObjects->getObjectCount())
- {
- gEditMenuHandler = this;
- }
- return mSelectedObjects;
- }
- // Use for when the simulator kills an object. This version also
- // handles informing the current tool of the object's deletion.
- //
- // Caller needs to call dialog_refresh_all if necessary.
- BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
- {
- BOOL object_found = FALSE;
- LLTool *tool = NULL;
- if (!gNoRender)
- {
- tool = LLToolMgr::getInstance()->getCurrentTool();
- // It's possible that the tool is editing an object that is not selected
- LLViewerObject* tool_editing_object = tool->getEditingObject();
- if( tool_editing_object && tool_editing_object->mID == id)
- {
- tool->stopEditing();
- object_found = TRUE;
- }
- }
- // Iterate through selected objects list and kill the object
- if( !object_found )
- {
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); )
- {
- LLObjectSelection::iterator curiter = iter++;
- LLViewerObject* object = (*curiter)->getObject();
- if (object->mID == id)
- {
- if (tool)
- {
- tool->stopEditing();
- }
- // lose the selection, don't tell simulator, it knows
- deselectObjectAndFamily(object, FALSE);
- object_found = TRUE;
- break; // must break here, may have removed multiple objects from list
- }
- 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.
- deselectObjectAndFamily(object, FALSE);
- break; // must break here, may have removed multiple objects from list
- }
- }
- }
- return object_found;
- }
- void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object)
- {
- // bail if nothing selected or if object wasn't selected in the first place
- if(!object) return;
- if(!object->isSelected()) return;
- // Collect all of the objects, and remove them
- std::vector<LLViewerObject*> objects;
- if (include_entire_object)
- {
- // Since we're selecting a family, start at the root, but
- // don't include an avatar.
- LLViewerObject* root = object;
-
- while(!root->isAvatar() && root->getParent() && !root->isJointChild())
- {
- LLViewerObject* parent = (LLViewerObject*)root->getParent();
- if (parent->isAvatar())
- {
- break;
- }
- root = parent;
- }
-
- object = root;
- }
- else
- {
- object = (LLViewerObject*)object->getRoot();
- }
- object->addThisAndAllChildren(objects);
- remove(objects);
- if (!send_to_sim) return;
- //-----------------------------------------------------------
- // Inform simulator of deselection
- //-----------------------------------------------------------
- LLViewerRegion* regionp = object->getRegion();
- BOOL start_new_message = TRUE;
- S32 select_count = 0;
- LLMessageSystem* msg = gMessageSystem;
- for (U32 i = 0; i < objects.size(); i++)
- {
- if (start_new_message)
- {
- msg->newMessageFast(_PREHASH_ObjectDeselect);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- select_count++;
- start_new_message = FALSE;
- }
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID());
- select_count++;
- // Zap the angular velocity, as the sim will set it to zero
- objects[i]->setAngularVelocity( 0,0,0 );
- objects[i]->setVelocity( 0,0,0 );
- if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET)
- {
- msg->sendReliable(regionp->getHost() );
- select_count = 0;
- start_new_message = TRUE;
- }
- }
- if (!start_new_message)
- {
- msg->sendReliable(regionp->getHost() );
- }
- updatePointAt();
- updateSelectionCenter();
- }
- void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim)
- {
- // bail if nothing selected or if object wasn't selected in the first place
- if (!object) return;
- if (!object->isSelected() ) return;
- // Zap the angular velocity, as the sim will set it to zero
- object->setAngularVelocity( 0,0,0 );
- object->setVelocity( 0,0,0 );
- if (send_to_sim)
- {
- LLViewerRegion* region = object->getRegion();
- gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
- gMessageSystem->sendReliable(region->getHost());
- }
- // This will refresh dialogs.
- remove( object );
- updatePointAt();
- updateSelectionCenter();
- }
- //-----------------------------------------------------------------------------
- // addAsFamily
- //-----------------------------------------------------------------------------
- void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to_end)
- {
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
- {
- LLViewerObject* objectp = *iter;
-
- // Can't select yourself
- if (objectp->mID == gAgentID
- && !LLSelectMgr::getInstance()->mAllowSelectAvatar)
- {
- continue;
- }
- if (!objectp->isSelected())
- {
- LLSelectNode *nodep = new LLSelectNode(objectp, TRUE);
- if (add_to_end)
- {
- mSelectedObjects->addNodeAtEnd(nodep);
- }
- else
- {
- mSelectedObjects->addNode(nodep);
- }
- objectp->setSelected(TRUE);
- if (objectp->getNumTEs() > 0)
- {
- nodep->selectAllTEs(TRUE);
- }
- else
- {
- // object has no faces, so don't mess with faces
- }
- }
- else
- {
- // we want this object to be selected for real
- // so clear transient flag
- LLSelectNode* select_node = mSelectedObjects->findNode(objectp);
- if (select_node)
- {
- select_node->setTransient(FALSE);
- }
- }
- }
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- }
- //-----------------------------------------------------------------------------
- // addAsIndividual() - a single object, face, etc
- //-----------------------------------------------------------------------------
- void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable)
- {
- // check to see if object is already in list
- LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
- // if not in list, add it
- if (!nodep)
- {
- nodep = new LLSelectNode(objectp, TRUE);
- mSelectedObjects->addNode(nodep);
- llassert_always(nodep->getObject());
- }
- else
- {
- // make this a full-fledged selection
- nodep->setTransient(FALSE);
- // Move it to the front of the list
- mSelectedObjects->moveNodeToFront(nodep);
- }
- // Make sure the object is tagged as selected
- objectp->setSelected( TRUE );
- // And make sure we don't consider it as part of a family
- nodep->mIndividualSelection = TRUE;
- // Handle face selection
- if (objectp->getNumTEs() <= 0)
- {
- // object has no faces, so don't do anything
- }
- else if (face == SELECT_ALL_TES)
- {
- nodep->selectAllTEs(TRUE);
- }
- else if (0 <= face && face < SELECT_MAX_TES)
- {
- nodep->selectTE(face, TRUE);
- }
- else
- {
- llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl;
- return;
- }
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- updateSelectionCenter();
- dialog_refresh_all();
- }
- LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face)
- {
- 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;
- }
- mHoverObjects->mPrimaryObject = objectp;
- objectp = objectp->getRootEdit();
- // 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)
- {
- // 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);
- }
- return mHoverObjects;
- }
- LLSelectNode *LLSelectMgr::getHoverNode()
- {
- return mHoverObjects->getFirstRootNode();
- }
- LLSelectNode *LLSelectMgr::getPrimaryHoverNode()
- {
- return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject];
- }
- void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
- {
- if (!objectp)
- {
- return;
- }
- if (objectp->getPCode() != LL_PCODE_VOLUME)
- {
- return;
- }
-
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
- || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
- {
- // only select my own objects
- return;
- }
- mRectSelectedObjects.insert(objectp);
- }
- void LLSelectMgr::highlightObjectAndFamily(LLViewerObject* objectp)
- {
- if (!objectp)
- {
- return;
- }
- LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot();
- highlightObjectOnly(root_obj);
- LLViewerObject::const_child_list_t& child_list = root_obj->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- highlightObjectOnly(child);
- }
- }
- // Note that this ignores the "select owned only" flag
- // It's also more efficient than calling the single-object version over and over.
- void LLSelectMgr::highlightObjectAndFamily(const std::vector<LLViewerObject*>& objects)
- {
- for (std::vector<LLViewerObject*>::const_iterator iter1 = objects.begin();
- iter1 != objects.end(); ++iter1)
- {
- LLViewerObject* object = *iter1;
- if (!object)
- {
- continue;
- }
- if (object->getPCode() != LL_PCODE_VOLUME)
- {
- continue;
- }
- LLViewerObject* root = (LLViewerObject*)object->getRoot();
- mRectSelectedObjects.insert(root);
- LLViewerObject::const_child_list_t& child_list = root->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter2 = child_list.begin();
- iter2 != child_list.end(); iter2++)
- {
- LLViewerObject* child = *iter2;
- mRectSelectedObjects.insert(child);
- }
- }
- }
- void LLSelectMgr::unhighlightObjectOnly(LLViewerObject* objectp)
- {
- if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
- {
- return;
- }
- mRectSelectedObjects.erase(objectp);
- }
- void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp)
- {
- if (!objectp)
- {
- return;
- }
- LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot();
- unhighlightObjectOnly(root_obj);
- LLViewerObject::const_child_list_t& child_list = root_obj->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- unhighlightObjectOnly(child);
- }
- }
- void LLSelectMgr::unhighlightAll()
- {
- mRectSelectedObjects.clear();
- mHighlightedObjects->deleteAllNodes();
- }
- LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects()
- {
- if (!mHighlightedObjects->getNumNodes())
- {
- return NULL;
- }
- //clear primary object
- mSelectedObjects->mPrimaryObject = NULL;
- for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin();
- iter != getHighlightedObjects()->end(); )
- {
- LLObjectSelection::iterator curiter = iter++;
-
- LLSelectNode *nodep = *curiter;
- LLViewerObject* objectp = nodep->getObject();
- if (!canSelectObject(objectp))
- {
- continue;
- }
- // already selected
- if (objectp->isSelected())
- {
- continue;
- }
- LLSelectNode* new_nodep = new LLSelectNode(*nodep);
- mSelectedObjects->addNode(new_nodep);
- // flag this object as selected
- objectp->setSelected(TRUE);
- mSelectedObjects->mSelectType = getSelectTypeForObject(objectp);
- // request properties on root objects
- if (objectp->isRootEdit())
- {
- requestObjectPropertiesFamily(objectp);
- }
- }
- // pack up messages to let sim know these objects are selected
- sendSelect();
- unhighlightAll();
- updateSelectionCenter();
- saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- updatePointAt();
- if (mSelectedObjects->getObjectCount())
- {
- gEditMenuHandler = this;
- }
- return mSelectedObjects;
- }
- void LLSelectMgr::deselectHighlightedObjects()
- {
- BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
- for (std::set<LLPointer<LLViewerObject> >::iterator iter = mRectSelectedObjects.begin();
- iter != mRectSelectedObjects.end(); iter++)
- {
- LLViewerObject *objectp = *iter;
- if (!select_linked_set)
- {
- deselectObjectOnly(objectp);
- }
- else
- {
- LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot();
- if (root_object->isSelected())
- {
- deselectObjectAndFamily(root_object);
- }
- }
- }
- unhighlightAll();
- }
- void LLSelectMgr::addGridObject(LLViewerObject* objectp)
- {
- LLSelectNode* nodep = new LLSelectNode(objectp, FALSE);
- mGridObjects.addNodeAtEnd(nodep);
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- nodep = new LLSelectNode(child, FALSE);
- mGridObjects.addNodeAtEnd(nodep);
- }
- }
- void LLSelectMgr::clearGridObjects()
- {
- mGridObjects.deleteAllNodes();
- }
- void LLSelectMgr::setGridMode(EGridMode mode)
- {
- mGridMode = mode;
- gSavedSettings.setS32("GridMode", mode);
- updateSelectionCenter();
- mGridValid = FALSE;
- }
- void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale)
- {
- mGridObjects.cleanupNodes();
-
- LLViewerObject* first_grid_object = mGridObjects.getFirstObject();
- if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount())
- {
- //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject());
- LLBBox bbox = mSavedSelectionBBox;
- mGridOrigin = mSavedSelectionBBox.getCenterAgent();
- mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f;
- // DEV-12570 Just taking the saved selection box rotation prevents
- // wild rotations of linked sets while in local grid mode
- //if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull())
- {
- mGridRotation = mSavedSelectionBBox.getRotation();
- }
- /*else //set to the root object
- {
- mGridRotation = root->getRenderRotation();
- }*/
- }
- else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull())
- {
- mGridRotation = first_grid_object->getRenderRotation();
- LLVector3 first_grid_obj_pos = first_grid_object->getRenderPosition();
- LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX);
- LLVector3 max_extents(-F32_MAX, -F32_MAX, -F32_MAX);
- BOOL grid_changed = FALSE;
- for (LLObjectSelection::iterator iter = mGridObjects.begin();
- iter != mGridObjects.end(); ++iter)
- {
- LLViewerObject* object = (*iter)->getObject();
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
- {
- const LLVector3* ext = drawable->getSpatialExtents();
- update_min_max(min_extents, max_extents, ext[0]);
- update_min_max(min_extents, max_extents, ext[1]);
- grid_changed = TRUE;
- }
- }
- if (grid_changed)
- {
- mGridOrigin = lerp(min_extents, max_extents, 0.5f);
- LLDrawable* drawable = first_grid_object->mDrawable;
- if (drawable && drawable->isActive())
- {
- mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix();
- }
- mGridScale = (max_extents - min_extents) * 0.5f;
- }
- }
- else // GRID_MODE_WORLD or just plain default
- {
- const BOOL non_root_ok = TRUE;
- LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok);
- mGridOrigin.clearVec();
- mGridRotation.loadIdentity();
- mSelectedObjects->mSelectType = getSelectTypeForObject( first_object );
- switch (mSelectedObjects->mSelectType)
- {
- case SELECT_TYPE_ATTACHMENT:
- if (first_object && first_object->getRootEdit()->mDrawable.notNull())
- {
- // this means this object *has* to be an attachment
- LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent();
- mGridOrigin = attachment_point_xform->getWorldPosition();
- mGridRotation = attachment_point_xform->getWorldRotation();
- mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution");
- }
- break;
- case SELECT_TYPE_HUD:
- // use HUD-scaled grid
- mGridScale = LLVector3(0.25f, 0.25f, 0.25f);
- break;
- case SELECT_TYPE_WORLD:
- mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution");
- break;
- }
- }
- llassert(mGridOrigin.isFinite());
- origin = mGridOrigin;
- rotation = mGridRotation;
- scale = mGridScale;
- mGridValid = TRUE;
- }
- //-----------------------------------------------------------------------------
- // remove() - an array of objects
- //-----------------------------------------------------------------------------
- void LLSelectMgr::remove(std::vector<LLViewerObject*>& objects)
- {
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
- {
- LLViewerObject* objectp = *iter;
- LLSelectNode* nodep = mSelectedObjects->findNode(objectp);
- if (nodep)
- {
- objectp->setSelected(FALSE);
- mSelectedObjects->removeNode(nodep);
- nodep = NULL;
- }
- }
- updateSelectionCenter();
- dialog_refresh_all();
- }
- //-----------------------------------------------------------------------------
- // remove() - a single object
- //-----------------------------------------------------------------------------
- void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
- {
- // get object node (and verify it is in the selected list)
- LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
- if (!nodep)
- {
- return;
- }
- // if face = all, remove object from list
- if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES))
- {
- // Remove all faces (or the object doesn't have faces) so remove the node
- mSelectedObjects->removeNode(nodep);
- nodep = NULL;
- objectp->setSelected( FALSE );
- }
- else if (0 <= te && te < SELECT_MAX_TES)
- {
- // ...valid face, check to see if it was on
- if (nodep->isTESelected(te))
- {
- nodep->selectTE(te, FALSE);
- }
- else
- {
- llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl;
- return;
- }
- // ...check to see if this operation turned off all faces
- BOOL found = FALSE;
- for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++)
- {
- found = found || nodep->isTESelected(i);
- }
- // ...all faces now turned off, so remove
- if (!found)
- {
- mSelectedObjects->removeNode(nodep);
- nodep = NULL;
- objectp->setSelected( FALSE );
- // *FIXME: Doesn't update simulator that object is no longer selected
- }
- }
- else
- {
- // ...out of range face
- llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl;
- }
- updateSelectionCenter();
- dialog_refresh_all();
- }
- //-----------------------------------------------------------------------------
- // removeAll()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::removeAll()
- {
- for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
- iter != mSelectedObjects->end(); iter++ )
- {
- LLViewerObject *objectp = (*iter)->getObject();
- objectp->setSelected( FALSE );
- }
- mSelectedObjects->deleteAllNodes();
-
- updateSelectionCenter();
- dialog_refresh_all();
- }
- //-----------------------------------------------------------------------------
- // promoteSelectionToRoot()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::promoteSelectionToRoot()
- {
- std::set<LLViewerObject*> selection_set;
- BOOL selection_changed = FALSE;
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); )
- {
- LLObjectSelection::iterator curiter = iter++;
- LLSelectNode* nodep = *curiter;
- LLViewerObject* object = nodep->getObject();
- if (nodep->mIndividualSelection)
- {
- selection_changed = TRUE;
- }
- LLViewerObject* parentp = object;
- while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild()))
- {
- parentp = (LLViewerObject*)parentp->getParent();
- }
-
- selection_set.insert(parentp);
- }
- if (selection_changed)
- {
- deselectAll();
- std::set<LLViewerObject*>::iterator set_iter;
- for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter)
- {
- selectObjectAndFamily(*set_iter);
- }
- }
- }
- //-----------------------------------------------------------------------------
- // demoteSelectionToIndividuals()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::demoteSelectionToIndividuals()
- {
- std::vector<LLViewerObject*> objects;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++)
- {
- LLViewerObject* object = (*iter)->getObject();
- object->addThisAndNonJointChildren(objects);
- }
- if (!objects.empty())
- {
- deselectAll();
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
- {
- LLViewerObject* objectp = *iter;
- selectObjectOnly(objectp);
- }
- }
- }
- //-----------------------------------------------------------------------------
- // dump()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::dump()
- {
- llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl;
- llinfos << "TE mode " << mTEMode << llendl;
- S32 count = 0;
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); iter++ )
- {
- LLViewerObject* objectp = (*iter)->getObject();
- llinfos << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl;
- llinfos << " hasLSL " << objectp->flagScripted() << llendl;
- llinfos << " hasTouch " << objectp->flagHandleTouch() << llendl;
- llinfos << " hasMoney " << objectp->flagTakesMoney() << llendl;
- llinfos << " getposition " << objectp->getPosition() << llendl;
- llinfos << " getpositionAgent " << objectp->getPositionAgent() << llendl;
- llinfos << " getpositionRegion " << objectp->getPositionRegion() << llendl;
- llinfos << " getpositionGlobal " << objectp->getPositionGlobal() << llendl;
- LLDrawable* drawablep = objectp->mDrawable;
- llinfos << " " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << llendl;
- llinfos << " " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << llendl;
- count++;
- }
- // Face iterator
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); iter++ )
- {
- LLSelectNode* node = *iter;
- LLViewerObject* objectp = node->getObject();
- if (!objectp)
- continue;
- for (S32 te = 0; te < objectp->getNumTEs(); ++te )
- {
- if (node->isTESelected(te))
- {
- llinfos << "Object " << objectp << " te " << te << llendl;
- }
- }
- }
- llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl;
- llinfos << "Center global " << mSelectionCenterGlobal << llendl;
- }
- //-----------------------------------------------------------------------------
- // cleanup()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::cleanup()
- {
- mSilhouetteImagep = NULL;
- }
- //---------------------------------------------------------------------------
- // Manipulate properties of selected objects
- //---------------------------------------------------------------------------
- struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- if (object->permModify())
- {
- object->sendTEUpdate();
- }
- return true;
- }
- };
- //-----------------------------------------------------------------------------
- // selectionSetImage()
- //-----------------------------------------------------------------------------
- // *TODO: re-arch texture applying out of lltooldraganddrop
- void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
- {
- // First for (no copy) textures and multiple object selection
- LLViewerInventoryItem* item = gInventory.getItem(imageid);
- if(item
- && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
- && (mSelectedObjects->getNumNodes() > 1) )
- {
- llwarns << "Attempted to apply no-copy texture to multiple objects"
- << llendl;
- return;
- }
- struct f : public LLSelectedTEFunctor
- {
- LLViewerInventoryItem* mItem;
- LLUUID mImageID;
- f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {}
- bool apply(LLViewerObject* objectp, S32 te)
- {
- if (mItem)
- {
- if (te == -1) // all faces
- {
- LLToolDragAndDrop::dropTextureAllFaces(objectp,
- mItem,
- LLToolDragAndDrop::SOURCE_AGENT,
- LLUUID::null);
- }
- else // one face
- {
- LLToolDragAndDrop::dropTextureOneFace(objectp,
- te,
- mItem,
- LLToolDragAndDrop::SOURCE_AGENT,
- LLUUID::null);
- }
- }
- else // not an inventory item
- {
- // 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, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
- }
- return true;
- }
- } setfunc(item, imageid);
- getSelection()->applyToTEs(&setfunc);
- struct g : public LLSelectedObjectFunctor
- {
- LLViewerInventoryItem* mItem;
- g(LLViewerInventoryItem* item) : mItem(item) {}
- virtual bool apply(LLViewerObject* object)
- {
- if (!mItem)
- {
- object->sendTEUpdate();
- // 1 particle effect per object
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
- effectp->setSourceObject(gAgent.getAvatarObject());
- effectp->setTargetObject(object);
- effectp->setDuration(LL_HUD_DUR_SHORT);
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- }
- return true;
- }
- } sendfunc(item);
- getSelection()->applyToObjects(&sendfunc);
- }
- //-----------------------------------------------------------------------------
- // selectionSetColor()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionSetColor(const LLColor4 &color)
- {
- struct f : public LLSelectedTEFunctor
- {
- LLColor4 mColor;
- f(const LLColor4& c) : mColor(c) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- object->setTEColor(te, mColor);
- }
- return true;
- }
- } setfunc(color);
- getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- //-----------------------------------------------------------------------------
- // selectionSetColorOnly()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color)
- {
- struct f : public LLSelectedTEFunctor
- {
- LLColor4 mColor;
- f(const LLColor4& c) : mColor(c) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- LLColor4 prev_color = object->getTE(te)->getColor();
- mColor.mV[VALPHA] = prev_color.mV[VALPHA];
- // update viewer side color in anticipation of update from simulator
- object->setTEColor(te, mColor);
- }
- return true;
- }
- } setfunc(color);
- getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- //-----------------------------------------------------------------------------
- // selectionSetAlphaOnly()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha)
- {
- struct f : public LLSelectedTEFunctor
- {
- F32 mAlpha;
- f(const F32& a) : mAlpha(a) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- LLColor4 prev_color = object->getTE(te)->getColor();
- prev_color.mV[VALPHA] = mAlpha;
- // update viewer side color in anticipation of update from simulator
- object->setTEColor(te, prev_color);
- }
- return true;
- }
- } setfunc(alpha);
- getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- void LLSelectMgr::selectionRevertColors()
- {
- struct f : public LLSelectedTEFunctor
- {
- LLObjectSelectionHandle mSelectedObjects;
- f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- LLSelectNode* nodep = mSelectedObjects->findNode(object);
- if (nodep && te < (S32)nodep->mSavedColors.size())
- {
- LLColor4 color = nodep->mSavedColors[te];
- // update viewer side color in anticipation of update from simulator
- object->setTEColor(te, color);
- }
- }
- return true;
- }
- } setfunc(mSelectedObjects);
- getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- BOOL LLSelectMgr::selectionRevertTextures()
- {
- struct f : public LLSelectedTEFunctor
- {
- LLObjectSelectionHandle mSelectedObjects;
- f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- LLSelectNode* nodep = mSelectedObjects->findNode(object);
- if (nodep && te < (S32)nodep->mSavedTextures.size())
- {
- LLUUID id = nodep->mSavedTextures[te];
- // update textures on viewer side
- if (id.isNull())
- {
- // this was probably a no-copy texture, leave image as-is
- return FALSE;
- }
- else
- {
- object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
- }
- }
- }
- return true;
- }
- } setfunc(mSelectedObjects);
- BOOL revert_successful = getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- return revert_successful;
- }
- void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
- {
- struct f : public LLSelectedTEFunctor
- {
- U8 mBump;
- f(const U8& b) : mBump(b) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- // update viewer side color in anticipation of update from simulator
- object->setTEBumpmap(te, mBump);
- }
- return true;
- }
- } setfunc(bumpmap);
- getSelection()->applyToTEs(&setfunc);
-
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- void LLSelectMgr::selectionSetTexGen(U8 texgen)
- {
- struct f : public LLSelectedTEFunctor
- {
- U8 mTexgen;
- f(const U8& t) : mTexgen(t) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- // update viewer side color in anticipation of update from simulator
- object->setTETexGen(te, mTexgen);
- }
- return true;
- }
- } setfunc(texgen);
- getSelection()->applyToTEs(&setfunc);
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- void LLSelectMgr::selectionSetShiny(U8 shiny)
- {
- struct f : public LLSelectedTEFunctor
- {
- U8 mShiny;
- f(const U8& t) : mShiny(t) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- // update viewer side color in anticipation of update from simulator
- object->setTEShiny(te, mShiny);
- }
- return true;
- }
- } setfunc(shiny);
- getSelection()->applyToTEs(&setfunc);
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- void LLSelectMgr::selectionSetFullbright(U8 fullbright)
- {
- struct f : public LLSelectedTEFunctor
- {
- U8 mFullbright;
- f(const U8& t) : mFullbright(t) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- // update viewer side color in anticipation of update from simulator
- object->setTEFullbright(te, mFullbright);
- }
- return true;
- }
- } setfunc(fullbright);
- getSelection()->applyToTEs(&setfunc);
- struct g : public LLSelectedObjectFunctor
- {
- U8 mFullbright;
- g(const U8& t) : mFullbright(t) {}
- virtual bool apply(LLViewerObject* object)
- {
- if (object->permModify())
- {
- object->sendTEUpdate();
- if (mFullbright)
- {
- U8 material = object->getMaterial();
- U8 mcode = material & LL_MCODE_MASK;
- if (mcode == LL_MCODE_LIGHT)
- {
- mcode = LL_MCODE_GLASS;
- material = (material & ~LL_MCODE_MASK) | mcode;
- object->setMaterial(material);
- object->sendMaterialUpdate();
- }
- }
- }
- return true;
- }
- } sendfunc(fullbright);
- getSelection()->applyToObjects(&sendfunc);
- }
- // 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;
- const LLSD &mMediaData;
- f(const U8& t, const LLSD& d) : mMediaFlags(t), mMediaData(d) {}
- bool apply(LLViewerObject* object, S32 te)
- {
- if (object->permModify())
- {
- // 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_type, media_data);
- getSelection()->applyToTEs(&setfunc);
-
- struct f2 : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- if (object->permModify())
- {
- object->sendTEUpdate();
- 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;
- }
- } func2;
- mSelectedObjects->applyToObjects( &func2 );
- }
- void LLSelectMgr::selectionSetGlow(F32 glow)
- {
- struct f1 : public LLSelectedTEFunctor
- {
- F32 mGlow;
- f1(F32 glow) : mGlow(glow) {};
- bool apply(LLViewerObject* object, S32 face)
- {
- if (object->permModify())
- {
- // update viewer side color in anticipation of update from simulator
- object->setTEGlow(face, mGlow);
- }
- return true;
- }
- } func1(glow);
- mSelectedObjects->applyToTEs( &func1 );
- struct f2 : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- if (object->permModify())
- {
- object->sendTEUpdate();
- }
- return true;
- }
- } func2;
- mSelectedObjects->applyToObjects( &func2 );
- }
- //-----------------------------------------------------------------------------
- // findObjectPermissions()
- //-----------------------------------------------------------------------------
- LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object)
- {
- for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin();
- iter != getSelection()->valid_end(); iter++ )
- {
- LLSelectNode* nodep = *iter;
- if (nodep->getObject() == object)
- {
- return nodep->mPermissions;
- }
- }
- return NULL;
- }
- //-----------------------------------------------------------------------------
- // selectionGetGlow()
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectionGetGlow(F32 *glow)
- {
- BOOL identical;
- F32 lglow = 0.f;
- struct f1 : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- return object->getTE(face)->getGlow();
- }
- } func;
- identical = mSelectedObjects->getSelectedTEValue( &func, lglow );
- *glow = lglow;
- return identical;
- }
- //-----------------------------------------------------------------------------
- // selectionSetMaterial()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionSetMaterial(U8 material)
- {
- struct f : public LLSelectedObjectFunctor
- {
- U8 mMaterial;
- f(const U8& t) : mMaterial(t) {}
- virtual bool apply(LLViewerObject* object)
- {
- if (object->permModify())
- {
- U8 cur_material = object->getMaterial();
- U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK);
- object->setMaterial(material);
- object->sendMaterialUpdate();
- }
- return true;
- }
- } sendfunc(material);
- getSelection()->applyToObjects(&sendfunc);
- }
- // TRUE if all selected objects have this PCode
- BOOL LLSelectMgr::selectionAllPCode(LLPCode code)
- {
- struct f : public LLSelectedObjectFunctor
- {
- LLPCode mCode;
- f(const LLPCode& t) : mCode(t) {}
- virtual bool apply(LLViewerObject* object)
- {
- if (object->getPCode() != mCode)
- {
- return FALSE;
- }
- return true;
- }
- } func(code);
- BOOL res = getSelection()->applyToObjects(&func);
- return res;
- }
- bool LLSelectMgr::selectionGetIncludeInSearch(bool* include_in_search_out)
- {
- LLViewerObject *object = mSelectedObjects->getFirstRootObject();
- if (!object) return FALSE;
- bool include_in_search = object->getIncludeInSearch();
- bool identical = true;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++)
- {
- LLViewerObject* object = (*iter)->getObject();
- if ( include_in_search != object->getIncludeInSearch())
- {
- identical = false;
- break;
- }
- }
- *include_in_search_out = include_in_search;
- return identical;
- }
- void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search)
- {
- LLViewerObject* object = NULL;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++)
- {
- object = (*iter)->getObject();
- object->setIncludeInSearch(include_in_search);
- }
- sendListToRegions(
- "ObjectIncludeInSearch",
- packAgentAndSessionID,
- packObjectIncludeInSearch,
- &include_in_search,
- SEND_ONLY_ROOTS);
- }
- BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action)
- {
- LLViewerObject *object = mSelectedObjects->getFirstObject();
- if (!object)
- {
- return FALSE;
- }
-
- U8 action = object->getClickAction();
- *out_action = action;
- struct f : public LLSelectedObjectFunctor
- {
- U8 mAction;
- f(const U8& t) : mAction(t) {}
- virtual bool apply(LLViewerObject* object)
- {
- if ( mAction != object->getClickAction())
- {
- return false;
- }
- return true;
- }
- } func(action);
- BOOL res = getSelection()->applyToObjects(&func);
- return res;
- }
- void LLSelectMgr::selectionSetClickAction(U8 action)
- {
- struct f : public LLSelectedObjectFunctor
- {
- U8 mAction;
- f(const U8& t) : mAction(t) {}
- virtual bool apply(LLViewerObject* object)
- {
- object->setClickAction(mAction);
- return true;
- }
- } func(action);
- getSelection()->applyToObjects(&func);
- sendListToRegions("ObjectClickAction",
- packAgentAndSessionID,
- packObjectClickAction,
- &action,
- SEND_INDIVIDUALS);
- }
- //-----------------------------------------------------------------------------
- // godlike requests
- //-----------------------------------------------------------------------------
- typedef std::pair<const std::string, const std::string> godlike_request_t;
- void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::string& param)
- {
- // If the agent is neither godlike nor an estate owner, the server
- // will reject the request.
- std::string message_type;
- if (gAgent.isGodlike())
- {
- message_type = "GodlikeMessage";
- }
- else
- {
- message_type = "EstateOwnerMessage";
- }
- godlike_request_t data(request, param);
- if(!mSelectedObjects->getRootObjectCount())
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage(message_type.c_str());
- LLSelectMgr::packGodlikeHead(&data);
- gAgent.sendReliableMessage();
- }
- else
- {
- sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS);
- }
- }
- void LLSelectMgr::packGodlikeHead(void* user_data)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addUUID("TransactionID", LLUUID::null);
- godlike_request_t* data = (godlike_request_t*)user_data;
- msg->nextBlock("MethodData");
- msg->addString("Method", data->first);
- msg->addUUID("Invoice", LLUUID::null);
- // The parameters used to be restricted to either string or
- // integer. This mimics that behavior under the new 'string-only'
- // parameter list by not packing a string if there wasn't one
- // specified. The object ids will be packed in the
- // packObjectIDAsParam() method.
- if(data->second.size() > 0)
- {
- msg->nextBlock("ParamList");
- msg->addString("Parameter", data->second);
- }
- }
- // static
- void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *)
- {
- std::string buf = llformat("%u", node->getObject()->getLocalID());
- gMessageSystem->nextBlock("ParamList");
- gMessageSystem->addString("Parameter", buf);
- }
- //-----------------------------------------------------------------------------
- // Rotation options
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionResetRotation()
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- LLQuaternion identity(0.f, 0.f, 0.f, 1.f);
- object->setRotation(identity);
- if (object->mDrawable.notNull())
- {
- gPipeline.markMoved(object->mDrawable, TRUE);
- }
- object->sendRotationUpdate();
- return true;
- }
- } func;
- getSelection()->applyToRootObjects(&func);
- }
- void LLSelectMgr::selectionRotateAroundZ(F32 degrees)
- {
- LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) );
- struct f : public LLSelectedObjectFunctor
- {
- LLQuaternion mRot;
- f(const LLQuaternion& rot) : mRot(rot) {}
- virtual bool apply(LLViewerObject* object)
- {
- object->setRotation( object->getRotationEdit() * mRot );
- if (object->mDrawable.notNull())
- {
- gPipeline.markMoved(object->mDrawable, TRUE);
- }
- object->sendRotationUpdate();
- return true;
- }
- } func(rot);
- getSelection()->applyToRootObjects(&func);
- }
- //-----------------------------------------------------------------------------
- // selectionTexScaleAutofit()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter)
- {
- struct f : public LLSelectedTEFunctor
- {
- F32 mRepeatsPerMeter;
- f(const F32& t) : mRepeatsPerMeter(t) {}
- bool apply(LLViewerObject* object, S32 te)
- {
-
- if (object->permModify())
- {
- // Compute S,T to axis mapping
- U32 s_axis, t_axis;
- if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis))
- {
- return TRUE;
- }
- F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter;
- F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter;
- object->setTEScale(te, new_s, new_t);
- }
- return true;
- }
- } setfunc(repeats_per_meter);
- getSelection()->applyToTEs(&setfunc);
- LLSelectMgrSendFunctor sendfunc;
- getSelection()->applyToObjects(&sendfunc);
- }
- // Called at the end of a scale operation, this adjusts the textures to attempt to
- // maintain a constant repeats per meter.
- // BUG: Only works for flex boxes.
- //-----------------------------------------------------------------------------
- // adjustTexturesByScale()
- //-----------------------------------------------------------------------------
- void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch)
- {
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); iter++)
- {
- LLSelectNode* selectNode = *iter;
- LLViewerObject* object = selectNode->getObject();
- if (!object)
- {
- continue;
- }
-
- if (!object->permModify())
- {
- continue;
- }
- if (object->getNumTEs() == 0)
- {
- continue;
- }
- BOOL send = FALSE;
-
- for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++)
- {
- const LLTextureEntry* tep = object->getTE(te_num);
- BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR;
- if (planar == stretch)
- {
- // Figure out how S,T changed with scale operation
- U32 s_axis, t_axis;
- if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis))
- {
- continue;
- }
-
- LLVector3 scale_ratio = selectNode->mTextureScaleRatios[te_num];
- LLVector3 object_scale = object->getScale();
-
- // Apply new scale to face
- if (planar)
- {
- object->setTEScale(te_num, 1.f/object_scale.mV[s_axis]*scale_ratio.mV[s_axis],
- 1.f/object_scale.mV[t_axis]*scale_ratio.mV[t_axis]);
- }
- else
- {
- object->setTEScale(te_num, scale_ratio.mV[s_axis]*object_scale.mV[s_axis],
- scale_ratio.mV[t_axis]*object_scale.mV[t_axis]);
- }
- send = send_to_sim;
- }
- }
- if (send)
- {
- object->sendTEUpdate();
- }
- }
- }
- //-----------------------------------------------------------------------------
- // selectGetAllRootsValid()
- // Returns TRUE if the viewer has information on all selected objects
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetAllRootsValid()
- {
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); ++iter )
- {
- LLSelectNode* node = *iter;
- if( !node->mValid )
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // selectGetAllValid()
- // Returns TRUE if the viewer has information on all selected objects
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetAllValid()
- {
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); ++iter )
- {
- LLSelectNode* node = *iter;
- if( !node->mValid )
- {
- return FALSE;
- }
- }
- 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
- // selected objects.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetModify()
- {
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); iter++ )
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if( !object || !node->mValid )
- {
- return FALSE;
- }
- if( !object->permModify() )
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // selectGetRootsModify() - return TRUE if current agent can modify all
- // selected root objects.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetRootsModify()
- {
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if( !node->mValid )
- {
- return FALSE;
- }
- if( !object->permModify() )
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // selectGetRootsTransfer() - return TRUE if current agent can transfer all
- // selected root objects.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetRootsTransfer()
- {
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if( !node->mValid )
- {
- return FALSE;
- }
- if(!object->permTransfer())
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // selectGetRootsCopy() - return TRUE if current agent can copy all
- // selected root objects.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetRootsCopy()
- {
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if( !node->mValid )
- {
- return FALSE;
- }
- if(!object->permCopy())
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // selectGetCreator()
- // Creator information only applies to root objects.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
- {
- BOOL identical = TRUE;
- BOOL first = TRUE;
- LLUUID first_id;
- for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
- iter != getSelection()->root_object_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- first_id = node->mPermissions->getCreator();
- first = FALSE;
- }
- else
- {
- if ( !(first_id == node->mPermissions->getCreator() ) )
- {
- identical = FALSE;
- break;
- }
- }
- }
- if (first_id.isNull())
- {
- name = LLTrans::getString("AvatarNameNobody");
- return FALSE;
- }
-
- result_id = first_id;
-
- if (identical)
- {
- name = LLSLURL::buildCommand("agent", first_id, "inspect");
- }
- else
- {
- name = LLTrans::getString("AvatarNameMultiple");
- }
- return identical;
- }
- //-----------------------------------------------------------------------------
- // selectGetOwner()
- // Owner information only applies to roots.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
- {
- BOOL identical = TRUE;
- BOOL first = TRUE;
- BOOL first_group_owned = FALSE;
- LLUUID first_id;
- for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
- iter != getSelection()->root_object_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
-
- if (first)
- {
- node->mPermissions->getOwnership(first_id, first_group_owned);
- first = FALSE;
- }
- else
- {
- LLUUID owner_id;
- BOOL is_group_owned = FALSE;
- if (!(node->mPermissions->getOwnership(owner_id, is_group_owned))
- || owner_id != first_id || is_group_owned != first_group_owned)
- {
- identical = FALSE;
- break;
- }
- }
- }
- if (first_id.isNull())
- {
- return FALSE;
- }
- result_id = first_id;
-
- if (identical)
- {
- BOOL public_owner = (first_id.isNull() && !first_group_owned);
- if (first_group_owned)
- {
- name = LLSLURL::buildCommand("group", first_id, "inspect");
- }
- else if(!public_owner)
- {
- name = LLSLURL::buildCommand("agent", first_id, "inspect");
- }
- else
- {
- name = LLTrans::getString("AvatarNameNobody");
- }
- }
- else
- {
- name = LLTrans::getString("AvatarNameMultiple");
- }
- return identical;
- }
- //-----------------------------------------------------------------------------
- // selectGetLastOwner()
- // Owner information only applies to roots.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name)
- {
- BOOL identical = TRUE;
- BOOL first = TRUE;
- LLUUID first_id;
- for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
- iter != getSelection()->root_object_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- first_id = node->mPermissions->getLastOwner();
- first = FALSE;
- }
- else
- {
- if ( !(first_id == node->mPermissions->getLastOwner() ) )
- {
- identical = FALSE;
- break;
- }
- }
- }
- if (first_id.isNull())
- {
- return FALSE;
- }
- result_id = first_id;
-
- if (identical)
- {
- BOOL public_owner = (first_id.isNull());
- if(!public_owner)
- {
- name = LLSLURL::buildCommand("agent", first_id, "inspect");
- }
- else
- {
- name.assign("Public or Group");
- }
- }
- else
- {
- name.assign( "" );
- }
- return identical;
- }
- //-----------------------------------------------------------------------------
- // selectGetGroup()
- // Group information only applies to roots.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id)
- {
- BOOL identical = TRUE;
- BOOL first = TRUE;
- LLUUID first_id;
- for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
- iter != getSelection()->root_object_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- first_id = node->mPermissions->getGroup();
- first = FALSE;
- }
- else
- {
- if ( !(first_id == node->mPermissions->getGroup() ) )
- {
- identical = FALSE;
- break;
- }
- }
- }
- result_id = first_id;
- return identical;
- }
- //-----------------------------------------------------------------------------
- // selectIsGroupOwned()
- // Only operates on root nodes.
- // Returns TRUE if all have valid data and they are all group owned.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectIsGroupOwned()
- {
- BOOL found_one = FALSE;
- for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
- iter != getSelection()->root_object_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- found_one = TRUE;
- if (!node->mPermissions->isGroupOwned())
- {
- return FALSE;
- }
- }
- return found_one ? TRUE : FALSE;
- }
- //-----------------------------------------------------------------------------
- // selectGetPerm()
- // Only operates on root nodes.
- // Returns TRUE if all have valid data.
- // mask_on has bits set to TRUE where all permissions are TRUE
- // mask_off has bits set to TRUE where all permissions are FALSE
- // if a bit is off both in mask_on and mask_off, the values differ within
- // the selection.
- //-----------------------------------------------------------------------------
- BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
- {
- U32 mask;
- U32 mask_and = 0xffffffff;
- U32 mask_or = 0x00000000;
- BOOL all_valid = FALSE;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- all_valid = FALSE;
- break;
- }
- all_valid = TRUE;
-
- switch( which_perm )
- {
- case PERM_BASE:
- mask = node->mPermissions->getMaskBase();
- break;
- case PERM_OWNER:
- mask = node->mPermissions->getMaskOwner();
- break;
- case PERM_GROUP:
- mask = node->mPermissions->getMaskGroup();
- break;
- case PERM_EVERYONE:
- mask = node->mPermissions->getMaskEveryone();
- break;
- case PERM_NEXT_OWNER:
- mask = node->mPermissions->getMaskNextOwner();
- break;
- default:
- mask = 0x0;
- break;
- }
- mask_and &= mask;
- mask_or |= mask;
- }
- if (all_valid)
- {
- // ...TRUE through all ANDs means all TRUE
- *mask_on = mask_and;
- // ...FALSE through all ORs means all FALSE
- *mask_off = ~mask_or;
- return TRUE;
- }
- else
- {
- *mask_on = 0;
- *mask_off = 0;
- return FALSE;
- }
- }
- BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm)
- {
- BOOL first = TRUE;
- LLPermissions perm;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- perm = *(node->mPermissions);
- first = FALSE;
- }
- else
- {
- perm.accumulate(*(node->mPermissions));
- }
- }
- result_perm = perm;
- return TRUE;
- }
- void LLSelectMgr::selectDelete()
- {
- S32 deleteable_count = 0;
- BOOL locked_but_deleteable_object = FALSE;
- BOOL no_copy_but_deleteable_object = FALSE;
- BOOL all_owned_by_you = TRUE;
- for (LLObjectSelection::iterator iter = getSelection()->begin();
- iter != getSelection()->end(); iter++)
- {
- LLViewerObject* obj = (*iter)->getObject();
- if( obj->isAttachment() )
- {
- continue;
- }
- deleteable_count++;
- // Check to see if you can delete objects which are locked.
- if(!obj->permMove())
- {
- locked_but_deleteable_object = TRUE;
- }
- if(!obj->permCopy())
- {
- no_copy_but_deleteable_object = TRUE;
- }
- if(!obj->permYouOwner())
- {
- all_owned_by_you = FALSE;
- }
- }
- if( 0 == deleteable_count )
- {
- make_ui_sound("UISndInvalidOp");
- return;
- }
- LLNotification::Params params("ConfirmObjectDeleteLock");
- params.functor.function(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection()));
- if(locked_but_deleteable_object ||
- no_copy_but_deleteable_object ||
- !all_owned_by_you)
- {
- // convert any transient pie-menu selections to full selection so this operation
- // has some context
- // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode
- // but this is ok, if not ideal
- convertTransient();
- //This is messy, but needed to get all english our of the UI.
- if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you)
- {
- //Locked only
- params.name("ConfirmObjectDeleteLock");
- }
- else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
- {
- //No Copy only
- params.name("ConfirmObjectDeleteNoCopy");
- }
- else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
- {
- //not owned only
- params.name("ConfirmObjectDeleteNoOwn");
- }
- else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
- {
- //locked and no copy
- params.name("ConfirmObjectDeleteLockNoCopy");
- }
- else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
- {
- //locked and not owned
- params.name("ConfirmObjectDeleteLockNoOwn");
- }
- else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you)
- {
- //no copy and not owned
- params.name("ConfirmObjectDeleteNoCopyNoOwn");
- }
- else
- {
- //locked, no copy and not owned
- params.name("ConfirmObjectDeleteLockNoCopyNoOwn");
- }
-
- LLNotifications::instance().add(params);
- }
- else
- {
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
- // static
- bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle)
- {
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (!handle->getObjectCount())
- {
- llwarns << "Nothing to delete!" << llendl;
- return false;
- }
- switch(option)
- {
- case 0:
- {
- // TODO: Make sure you have delete permissions on all of them.
- 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",
- packDeRezHeader,
- packObjectLocalID,
- (void*)info,
- SEND_ONLY_ROOTS);
- // VEFFECT: Delete Object - one effect for all deletes
- if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD)
- {
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() );
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- F32 duration = 0.5f;
- duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f;
- effectp->setDuration(duration);
- }
- gAgent.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);
- obj_delete_count += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount();
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count );
- }
- break;
- case 1:
- default:
- break;
- }
- return false;
- }
- void LLSelectMgr::selectForceDelete()
- {
- sendListToRegions(
- "ObjectDelete",
- packDeleteHeader,
- packObjectLocalID,
- (void*)TRUE,
- SEND_ONLY_ROOTS);
- }
- void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale,
- BOOL &is_for_sale_mixed,
- BOOL &is_sale_price_mixed,
- S32 &total_sale_price,
- S32 &individual_sale_price)
- {
- num_for_sale = 0;
- is_for_sale_mixed = FALSE;
- is_sale_price_mixed = FALSE;
- total_sale_price = 0;
- individual_sale_price = 0;
- // Empty set.
- if (getSelection()->root_begin() == getSelection()->root_end())
- return;
-
- LLSelectNode *node = *(getSelection()->root_begin());
- const BOOL first_node_for_sale = node->mSaleInfo.isForSale();
- const S32 first_node_sale_price = node->mSaleInfo.getSalePrice();
-
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- const BOOL node_for_sale = node->mSaleInfo.isForSale();
- const S32 node_sale_price = node->mSaleInfo.getSalePrice();
-
- // Set mixed if the fields don't match the first node's fields.
- if (node_for_sale != first_node_for_sale)
- is_for_sale_mixed = TRUE;
- if (node_sale_price != first_node_sale_price)
- is_sale_price_mixed = TRUE;
-
- if (node_for_sale)
- {
- total_sale_price += node_sale_price;
- num_for_sale ++;
- }
- }
-
- individual_sale_price = first_node_sale_price;
- if (is_for_sale_mixed)
- {
- is_sale_price_mixed = TRUE;
- individual_sale_price = 0;
- }
- }
- // returns TRUE if all nodes are valid. method also stores an
- // accumulated sale info.
- BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info)
- {
- BOOL first = TRUE;
- LLSaleInfo sale_info;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- sale_info = node->mSaleInfo;
- first = FALSE;
- }
- else
- {
- sale_info.accumulate(node->mSaleInfo);
- }
- }
- result_sale_info = sale_info;
- return TRUE;
- }
- BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm)
- {
- BOOL first = TRUE;
- LLAggregatePermissions perm;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- if (first)
- {
- perm = node->mAggregatePerm;
- first = FALSE;
- }
- else
- {
- perm.aggregate(node->mAggregatePerm);
- }
- }
- result_perm = perm;
- return TRUE;
- }
- BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& result_perm)
- {
- BOOL first = TRUE;
- LLAggregatePermissions perm;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mValid)
- {
- return FALSE;
- }
- LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm;
- if (first)
- {
- perm = t_perm;
- first = FALSE;
- }
- else
- {
- perm.aggregate(t_perm);
- }
- }
- result_perm = perm;
- return TRUE;
- }
- //--------------------------------------------------------------------
- // Duplicate objects
- //--------------------------------------------------------------------
- // JC - If this doesn't work right, duplicate the selection list
- // before doing anything, do a deselect, then send the duplicate
- // messages.
- struct LLDuplicateData
- {
- LLVector3 offset;
- U32 flags;
- };
- void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
- {
- if (mSelectedObjects->isAttachment())
- {
- //RN: do not duplicate attachments
- make_ui_sound("UISndInvalidOp");
- return;
- }
- LLDuplicateData data;
- data.offset = offset;
- data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0);
- sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS);
- if (select_copy)
- {
- // the new copy will be coming in selected
- deselectAll();
- }
- else
- {
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- node->mDuplicated = TRUE;
- node->mDuplicatePos = node->getObject()->getPositionGlobal();
- node->mDuplicateRot = node->getObject()->getRotation();
- }
- }
- }
- void LLSelectMgr::repeatDuplicate()
- {
- if (mSelectedObjects->isAttachment())
- {
- //RN: do not duplicate attachments
- make_ui_sound("UISndInvalidOp");
- return;
- }
- std::vector<LLViewerObject*> non_duplicated_objects;
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (!node->mDuplicated)
- {
- non_duplicated_objects.push_back(node->getObject());
- }
- }
- // make sure only previously duplicated objects are selected
- for (std::vector<LLViewerObject*>::iterator iter = non_duplicated_objects.begin();
- iter != non_duplicated_objects.end(); ++iter)
- {
- LLViewerObject* objectp = *iter;
- deselectObjectAndFamily(objectp);
- }
-
- // duplicate objects in place
- LLDuplicateData data;
- data.offset = LLVector3::zero;
- data.flags = 0x0;
- sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS);
- // move current selection based on delta from duplication position and update duplication position
- for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
- iter != getSelection()->root_end(); iter++ )
- {
- LLSelectNode* node = *iter;
- if (node->mDuplicated)
- {
- LLQuaternion cur_rot = node->getObject()->getRotation();
- LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot);
- LLQuaternion new_rot = cur_rot * rot_delta;
- LLVector3d cur_pos = node->getObject()->getPositionGlobal();
- LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta);
- node->mDuplicatePos = node->getObject()->getPositionGlobal();
- node->mDuplicateRot = node->getObject()->getRotation();
- node->getObject()->setPositionGlobal(new_pos);
- node->getObject()->setRotation(new_rot);
- }
- }
- sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
- }
- // static
- void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data )
- {
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID());
- }
- //--------------------------------------------------------------------
- // Duplicate On Ray
- //--------------------------------------------------------------------
- // Duplicates the selected objects, but places the copy along a cast
- // ray.
- struct LLDuplicateOnRayData
- {
- LLVector3 mRayStartRegion;
- LLVector3 mRayEndRegion;
- BOOL mBypassRaycast;
- BOOL mRayEndIsIntersection;
- LLUUID mRayTargetID;
- BOOL mCopyCenters;
- BOOL mCopyRotates;
- U32 mFlags;
- };
- void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region,
- const LLVector3 &ray_end_region,
- BOOL bypass_raycast,
- BOOL ray_end_is_intersection,
- const LLUUID &ray_target_id,
- BOOL copy_centers,
- BOOL copy_rotates,
- BOOL select_copy)
- {
- if (mSelectedObjects->isAttachment())
- {
- // do not duplicate attachments
- make_ui_sound("UISndInvalidOp");
- return;
- }
-
- LLDuplicateOnRayData data;
- data.mRayStartRegion = ray_start_region;
- data.mRayEndRegion = ray_end_region;
- data.mBypassRaycast = bypass_raycast;
- data.mRayEndIsIntersection = ray_end_is_intersection;
- data.mRayTargetID = ray_target_id;
- data.mCopyCenters = copy_centers;
- data.mCopyRotates = copy_rotates;
- data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0);
- sendListToRegions("ObjectDuplicateOnRay",
- packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS);
- if (select_copy)
- {
- // the new copy will be coming in selected
- deselectAll();
- }
- }
- // static
- void LLSelectMgr::packDuplicateOnRayHead(void *user_data)
- {
- LLMessageSystem *msg = gMessageSystem;
- LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data;
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
- msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion );
- msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion );
- msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast );
- msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection );
- msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters );
- msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates );
- msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID );
- msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags );
- }
- //------------------------------------------------------------------------
- // Object position, scale, rotation update, all-in-one
- //------------------------------------------------------------------------
- void LLSelectMgr::sendMultipleUpdate(U32 type)
- {
- if (type == UPD_NONE) return;
- // send individual updates when selecting textures or individual objects
- ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST;
- if (send_type == SEND_ONLY_ROOTS)
- {
- // tell simulator to apply to whole linked sets
- type |= UPD_LINKED_SETS;
- }
- sendListToRegions(
- "MultipleObjectUpdate",
- packAgentAndSessionID,
- packMultipleUpdate,
- &type,
- send_type);
- }
- // static
- void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data)
- {
- LLViewerObject* object = node->getObject();
- U32 *type32 = (U32 *)user_data;
- U8 type = (U8)*type32;
- U8 data[256];
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
- gMessageSystem->addU8Fast(_PREHASH_Type, type );
- S32 offset = 0;
- // JC: You MUST pack the data in this order. The receiving
- // routine process_multiple_update_message on simulator will
- // extract them in this order.
- if (type & UPD_POSITION)
- {
- htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12);
- offset += 12;
- }
- if (type & UPD_ROTATION)
- {
- LLQuaternion quat = object->getRotation();
- LLVector3 vec = quat.packToVector3();
- htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12);
- offset += 12;
- }
- if (type & UPD_SCALE)
- {
- //llinfos << "Sending object scale " << object->getScale() << llendl;
- htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12);
- offset += 12;
- }
- gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);
- }
- //------------------------------------------------------------------------
- // Ownership
- //------------------------------------------------------------------------
- struct LLOwnerData
- {
- LLUUID owner_id;
- LLUUID group_id;
- BOOL override;
- };
- void LLSelectMgr::sendOwner(const LLUUID& owner_id,
- const LLUUID& group_id,
- BOOL override)
- {
- LLOwnerData data;
- data.owner_id = owner_id;
- data.group_id = group_id;
- data.override = override;
- sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS);
- }
- // static
- void LLSelectMgr::packOwnerHead(void *user_data)
- {
- LLOwnerData *data = (LLOwnerData *)user_data;
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- gMessageSystem->nextBlockFast(_PREHASH_HeaderData);
- gMessageSystem->addBOOLFast(_PREHASH_Override, data->override);