llselectmgr.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 // file include
00035 #include "llselectmgr.h"
00036 
00037 // library includes
00038 #include "llcachename.h"
00039 #include "lldbstrings.h"
00040 #include "lleconomy.h"
00041 #include "llgl.h"
00042 #include "llglimmediate.h"
00043 #include "llpermissions.h"
00044 #include "llpermissionsflags.h"
00045 #include "llundo.h"
00046 #include "lluuid.h"
00047 #include "llvolume.h"
00048 #include "message.h"
00049 #include "object_flags.h"
00050 #include "llquaternion.h"
00051 
00052 // viewer includes
00053 #include "llagent.h"
00054 #include "llviewerwindow.h"
00055 #include "lldrawable.h"
00056 #include "llfloaterinspect.h"
00057 #include "llfloaterproperties.h"
00058 #include "llfloaterreporter.h"
00059 #include "llfloatertools.h"
00060 #include "llframetimer.h"
00061 #include "llhudeffecttrail.h"
00062 #include "llhudmanager.h"
00063 #include "llinventorymodel.h"
00064 #include "llmenugl.h"
00065 #include "llmutelist.h"
00066 #include "llstatusbar.h"
00067 #include "llsurface.h"
00068 #include "lltool.h"
00069 #include "lltooldraganddrop.h"
00070 #include "lltoolmgr.h"
00071 #include "lltoolpie.h"
00072 #include "llui.h"
00073 #include "llviewercamera.h"
00074 #include "llviewercontrol.h"
00075 #include "llviewerimagelist.h"
00076 #include "llviewermenu.h"
00077 #include "llviewerobject.h"
00078 #include "llviewerobjectlist.h"
00079 #include "llviewerregion.h"
00080 #include "llviewerstats.h"
00081 #include "llvoavatar.h"
00082 #include "llvovolume.h"
00083 #include "pipeline.h"
00084 
00085 #include "llglheaders.h"
00086 
00087 LLViewerObject* getSelectedParentObject(LLViewerObject *object) ;
00088 //
00089 // Consts
00090 //
00091 
00092 const S32 NUM_SELECTION_UNDO_ENTRIES = 200;
00093 const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f;
00094 const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constants.price_object_claim in the database.
00095 const S32 MAX_ACTION_QUEUE_SIZE = 20;
00096 const S32 MAX_SILS_PER_FRAME = 50;
00097 const S32 MAX_OBJECTS_PER_PACKET = 254;
00098 
00099 extern LLUUID                   gLastHitObjectID;
00100 extern LLVector3d               gLastHitObjectOffset;
00101 
00102 //
00103 // Globals
00104 //
00105 
00106 BOOL gDebugSelectMgr = FALSE;
00107 
00108 BOOL gHideSelectedObjects = FALSE;
00109 BOOL gAllowSelectAvatar = FALSE;
00110 
00111 BOOL LLSelectMgr::sRectSelectInclusive = TRUE;
00112 BOOL LLSelectMgr::sRenderHiddenSelections = TRUE;
00113 BOOL LLSelectMgr::sRenderLightRadius = FALSE;
00114 F32     LLSelectMgr::sHighlightThickness = 0.f;
00115 F32     LLSelectMgr::sHighlightUScale = 0.f;
00116 F32     LLSelectMgr::sHighlightVScale = 0.f;
00117 F32     LLSelectMgr::sHighlightAlpha = 0.f;
00118 F32     LLSelectMgr::sHighlightAlphaTest = 0.f;
00119 F32     LLSelectMgr::sHighlightUAnim = 0.f;
00120 F32     LLSelectMgr::sHighlightVAnim = 0.f;
00121 LLColor4 LLSelectMgr::sSilhouetteParentColor;
00122 LLColor4 LLSelectMgr::sSilhouetteChildColor;
00123 LLColor4 LLSelectMgr::sHighlightInspectColor;
00124 LLColor4 LLSelectMgr::sHighlightParentColor;
00125 LLColor4 LLSelectMgr::sHighlightChildColor;
00126 LLColor4 LLSelectMgr::sContextSilhouetteColor;
00127 
00128 static LLObjectSelection *get_null_object_selection();
00129 template<> 
00130         const LLSafeHandle<LLObjectSelection>::NullFunc 
00131                 LLSafeHandle<LLObjectSelection>::sNullFunc = get_null_object_selection;
00132 
00133 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00134 // struct LLDeRezInfo
00135 //
00136 // Used to keep track of important derez info. 
00137 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00138 
00139 struct LLDeRezInfo
00140 {
00141         EDeRezDestination mDestination;
00142         LLUUID mDestinationID;
00143         LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) :
00144                 mDestination(dest), mDestinationID(dest_id) {}
00145 };
00146 
00147 //
00148 // Imports
00149 //
00150 
00151 
00152 static LLPointer<LLObjectSelection> sNullSelection;
00153 
00154 //
00155 // Functions
00156 //
00157 
00158 void LLSelectMgr::cleanupGlobals()
00159 {
00160         sNullSelection = NULL;
00161         LLSelectMgr::getInstance()->clearSelections();
00162 }
00163 
00164 LLObjectSelection *get_null_object_selection()
00165 {
00166         if (sNullSelection.isNull())
00167         {
00168                 sNullSelection = new LLObjectSelection;
00169         }
00170         return sNullSelection;
00171 }
00172 
00173 
00174 //-----------------------------------------------------------------------------
00175 // LLSelectMgr()
00176 //-----------------------------------------------------------------------------
00177 LLSelectMgr::LLSelectMgr()
00178 {
00179         mTEMode = FALSE;
00180         mLastCameraPos.clearVec();
00181 
00182         sHighlightThickness     = gSavedSettings.getF32("SelectionHighlightThickness");
00183         sHighlightUScale        = gSavedSettings.getF32("SelectionHighlightUScale");
00184         sHighlightVScale        = gSavedSettings.getF32("SelectionHighlightVScale");
00185         sHighlightAlpha         = gSavedSettings.getF32("SelectionHighlightAlpha");
00186         sHighlightAlphaTest     = gSavedSettings.getF32("SelectionHighlightAlphaTest");
00187         sHighlightUAnim         = gSavedSettings.getF32("SelectionHighlightUAnim");
00188         sHighlightVAnim         = gSavedSettings.getF32("SelectionHighlightVAnim");
00189 
00190         sSilhouetteParentColor = gColors.getColor("SilhouetteParentColor");
00191         sSilhouetteChildColor = gColors.getColor("SilhouetteChildColor");
00192         sHighlightParentColor = gColors.getColor("HighlightParentColor");
00193         sHighlightChildColor = gColors.getColor("HighlightChildColor");
00194         sHighlightInspectColor = gColors.getColor("HighlightInspectColor");
00195         sContextSilhouetteColor = gColors.getColor("ContextSilhouetteColor")*0.5f;
00196 
00197         sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
00198         
00199         mRenderSilhouettes = TRUE;
00200 
00201         mGridMode = GRID_MODE_WORLD;
00202         gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD);
00203         mGridValid = FALSE;
00204 
00205         mSelectedObjects = new LLObjectSelection();
00206         mHoverObjects = new LLObjectSelection();
00207         mHighlightedObjects = new LLObjectSelection();
00208 }
00209 
00210 
00211 //-----------------------------------------------------------------------------
00212 // ~LLSelectMgr()
00213 //-----------------------------------------------------------------------------
00214 LLSelectMgr::~LLSelectMgr()
00215 {
00216         clearSelections();
00217 }
00218 
00219 void LLSelectMgr::clearSelections()
00220 {
00221         mHoverObjects->deleteAllNodes();
00222         mSelectedObjects->deleteAllNodes();
00223         mHighlightedObjects->deleteAllNodes();
00224         mRectSelectedObjects.clear();
00225         mGridObjects.deleteAllNodes();
00226 }
00227 
00228 void LLSelectMgr::update()
00229 {
00230         mSelectedObjects->cleanupNodes();
00231 }
00232 
00233 void LLSelectMgr::updateEffects()
00234 {
00235         //keep reference grid objects active
00236         struct f : public LLSelectedObjectFunctor
00237         {
00238                 virtual bool apply(LLViewerObject* object)
00239                 {
00240                         LLDrawable* drawable = object->mDrawable;
00241                         if (drawable)
00242                         {
00243                                 gPipeline.markMoved(drawable);
00244                         }
00245                         return true;
00246                 }
00247         } func;
00248         mGridObjects.applyToObjects(&func);
00249 
00250         if (mEffectsTimer.getElapsedTimeF32() > 1.f)
00251         {
00252                 mSelectedObjects->updateEffects();
00253                 mEffectsTimer.reset();
00254         }
00255 }
00256 
00257 void LLSelectMgr::overrideObjectUpdates()
00258 {
00259         //override any position updates from simulator on objects being edited
00260         struct f : public LLSelectedNodeFunctor
00261         {
00262                 virtual bool apply(LLSelectNode* selectNode)
00263                 {
00264                         LLViewerObject* object = selectNode->getObject();
00265                         if (object && object->permMove())
00266                         {
00267                                 if (!selectNode->mLastPositionLocal.isExactlyZero())
00268                                 {
00269                                         object->setPosition(selectNode->mLastPositionLocal);
00270                                 }
00271                                 if (selectNode->mLastRotation != LLQuaternion())
00272                                 {
00273                                         object->setRotation(selectNode->mLastRotation);
00274                                 }
00275                                 if (!selectNode->mLastScale.isExactlyZero())
00276                                 {
00277                                         object->setScale(selectNode->mLastScale);
00278                                 }
00279                         }
00280                         return true;
00281                 }
00282         } func;
00283         getSelection()->applyToNodes(&func);
00284 }
00285 
00286 //-----------------------------------------------------------------------------
00287 // Select just the object, not any other group members.
00288 //-----------------------------------------------------------------------------
00289 LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
00290 {
00291         llassert( object );
00292 
00293         //remember primary object
00294         mSelectedObjects->mPrimaryObject = object;
00295 
00296         // Don't add an object that is already in the list
00297         if (object->isSelected() ) {
00298                 // make sure point at position is updated
00299                 updatePointAt();
00300                 gEditMenuHandler = this;
00301                 return NULL;
00302         }
00303 
00304         if (!canSelectObject(object))
00305         {
00306                 //make_ui_sound("UISndInvalidOp");
00307                 return NULL;
00308         }
00309 
00310         // llinfos << "Adding object to selected object list" << llendl;
00311 
00312         // Place it in the list and tag it.
00313         // This will refresh dialogs.
00314         addAsIndividual(object, face);
00315 
00316         // Stop the object from moving (this anticipates changes on the
00317         // simulator in LLTask::userSelect)
00318         // *FIX: shouldn't zero out these either
00319         object->setVelocity(LLVector3::zero);
00320         object->setAcceleration(LLVector3::zero);
00321         //object->setAngularVelocity(LLVector3::zero);
00322         object->resetRot();
00323 
00324         // Always send to simulator, so you get a copy of the 
00325         // permissions structure back.
00326         gMessageSystem->newMessageFast(_PREHASH_ObjectSelect);
00327         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
00328         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00329         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00330         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
00331         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
00332         LLViewerRegion* regionp = object->getRegion();
00333         gMessageSystem->sendReliable( regionp->getHost());
00334 
00335         updatePointAt();
00336         updateSelectionCenter();
00337         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00338 
00339         // have selection manager handle edit menu immediately after 
00340         // user selects an object
00341         if (mSelectedObjects->getObjectCount())
00342         {
00343                 gEditMenuHandler = this;
00344         }
00345 
00346         return mSelectedObjects;
00347 }
00348 
00349 //-----------------------------------------------------------------------------
00350 // Select the object, parents and children.
00351 //-----------------------------------------------------------------------------
00352 LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
00353 {
00354         llassert( obj );
00355 
00356         //remember primary object
00357         mSelectedObjects->mPrimaryObject = obj;
00358 
00359         // This may be incorrect if things weren't family selected before... - djs 07/08/02
00360         // Don't add an object that is already in the list
00361         if (obj->isSelected() ) 
00362         {
00363                 // make sure pointat position is updated
00364                 updatePointAt();
00365                 gEditMenuHandler = this;
00366                 return NULL;
00367         }
00368 
00369         if (!canSelectObject(obj))
00370         {
00371                 //make_ui_sound("UISndInvalidOp");
00372                 return NULL;
00373         }
00374 
00375         // Since we're selecting a family, start at the root, but
00376         // don't include an avatar.
00377         LLViewerObject* root = obj;
00378         
00379         while(!root->isAvatar() && root->getParent() && !root->isJointChild())
00380         {
00381                 LLViewerObject* parent = (LLViewerObject*)root->getParent();
00382                 if (parent->isAvatar())
00383                 {
00384                         break;
00385                 }
00386                 root = parent;
00387         }
00388 
00389         // Collect all of the objects
00390         LLDynamicArray<LLViewerObject*> objects;
00391 
00392         root->addThisAndNonJointChildren(objects);
00393         addAsFamily(objects, add_to_end);
00394 
00395         updateSelectionCenter();
00396         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00397         updatePointAt();
00398 
00399         dialog_refresh_all();
00400 
00401         // Always send to simulator, so you get a copy of the permissions
00402         // structure back.
00403         sendSelect();
00404 
00405         // Stop the object from moving (this anticipates changes on the
00406         // simulator in LLTask::userSelect)
00407         root->setVelocity(LLVector3::zero);
00408         root->setAcceleration(LLVector3::zero);
00409         //root->setAngularVelocity(LLVector3::zero);
00410         root->resetRot();
00411 
00412         // leave component mode
00413         if (gSavedSettings.getBOOL("EditLinkedParts"))
00414         {
00415                 gSavedSettings.setBOOL("EditLinkedParts", FALSE);
00416                 promoteSelectionToRoot();
00417         }
00418 
00419         // have selection manager handle edit menu immediately after 
00420         // user selects an object
00421         if (mSelectedObjects->getObjectCount())
00422         {
00423                 gEditMenuHandler = this;
00424         }
00425 
00426         return mSelectedObjects;
00427 }
00428 
00429 //-----------------------------------------------------------------------------
00430 // Select the object, parents and children.
00431 //-----------------------------------------------------------------------------
00432 LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLViewerObject*>& object_list,
00433                                                                                                                    BOOL send_to_sim)
00434 {
00435         // Collect all of the objects, children included
00436         LLDynamicArray<LLViewerObject*> objects;
00437 
00438         //clear primary object (no primary object)
00439         mSelectedObjects->mPrimaryObject = NULL;
00440 
00441         if (object_list.size() < 1)
00442         {
00443                 return NULL;
00444         }
00445         
00446         // NOTE -- we add the objects in REVERSE ORDER 
00447         // to preserve the order in the mSelectedObjects list
00448         for (std::vector<LLViewerObject*>::const_reverse_iterator riter = object_list.rbegin();
00449                  riter != object_list.rend(); ++riter)
00450         {
00451                 LLViewerObject *object = *riter;
00452 
00453                 llassert( object );
00454 
00455                 if (!canSelectObject(object)) continue;
00456 
00457                 object->addThisAndNonJointChildren(objects);
00458                 addAsFamily(objects);
00459 
00460                 // Stop the object from moving (this anticipates changes on the
00461                 // simulator in LLTask::userSelect)
00462                 object->setVelocity(LLVector3::zero);
00463                 object->setAcceleration(LLVector3::zero);
00464                 //object->setAngularVelocity(LLVector3::zero);
00465                 object->resetRot();
00466         }
00467 
00468         updateSelectionCenter();
00469         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00470         updatePointAt();
00471         dialog_refresh_all();
00472 
00473         // Almost always send to simulator, so you get a copy of the permissions
00474         // structure back.
00475         // JC: The one case where you don't want to do this is if you're selecting
00476         // all the objects on a sim.
00477         if (send_to_sim)
00478         {
00479                 sendSelect();
00480         }
00481 
00482         // leave component mode
00483         if (gSavedSettings.getBOOL("EditLinkedParts"))
00484         {               
00485                 gSavedSettings.setBOOL("EditLinkedParts", FALSE);
00486                 promoteSelectionToRoot();
00487         }
00488 
00489         // have selection manager handle edit menu immediately after 
00490         // user selects an object
00491         if (mSelectedObjects->getObjectCount())
00492         {
00493                 gEditMenuHandler = this;
00494         }
00495 
00496         return mSelectedObjects;
00497 }
00498 
00499 // Use for when the simulator kills an object.  This version also
00500 // handles informing the current tool of the object's deletion.
00501 //
00502 // Caller needs to call dialog_refresh_all if necessary.
00503 BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
00504 {
00505         BOOL object_found = FALSE;
00506         LLTool *tool = NULL;
00507         if (!gNoRender)
00508         {
00509                 tool = LLToolMgr::getInstance()->getCurrentTool();
00510 
00511                 // It's possible that the tool is editing an object that is not selected
00512                 LLViewerObject* tool_editing_object = tool->getEditingObject();
00513                 if( tool_editing_object && tool_editing_object->mID == id)
00514                 {
00515                         tool->stopEditing();
00516                         object_found = TRUE;
00517                 }
00518         }
00519 
00520         // Iterate through selected objects list and kill the object
00521         if( !object_found )
00522         {
00523                 for (LLObjectSelection::iterator iter = getSelection()->begin();
00524                          iter != getSelection()->end(); )
00525                 {
00526                         LLObjectSelection::iterator curiter = iter++;
00527                         LLViewerObject* object = (*curiter)->getObject();
00528                         if (object->mID == id)
00529                         {
00530                                 if (tool)
00531                                 {
00532                                         tool->stopEditing();
00533                                 }
00534 
00535                                 // lose the selection, don't tell simulator, it knows
00536                                 deselectObjectAndFamily(object, FALSE);
00537                                 object_found = TRUE;
00538                                 break; // must break here, may have removed multiple objects from list
00539                         }
00540                         else if (object->isAvatar())
00541                         {
00542                                 // It's possible the item being removed has an avatar sitting on it
00543                                 // So remove the avatar that is sitting on the object.
00544                                 deselectObjectAndFamily(object, FALSE);
00545                                 break; // must break here, may have removed multiple objects from list
00546                         }
00547                 }
00548         }
00549 
00550         return object_found;
00551 }
00552 
00553 void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object)
00554 {
00555         // bail if nothing selected or if object wasn't selected in the first place
00556         if(!object) return;
00557         if(!object->isSelected()) return;
00558 
00559         // Collect all of the objects, and remove them
00560         LLDynamicArray<LLViewerObject*> objects;
00561 
00562         if (include_entire_object)
00563         {
00564                 // Since we're selecting a family, start at the root, but
00565                 // don't include an avatar.
00566                 LLViewerObject* root = object;
00567         
00568                 while(!root->isAvatar() && root->getParent() && !root->isJointChild())
00569                 {
00570                         LLViewerObject* parent = (LLViewerObject*)root->getParent();
00571                         if (parent->isAvatar())
00572                         {
00573                                 break;
00574                         }
00575                         root = parent;
00576                 }
00577         
00578                 object = root;
00579         }
00580         else
00581         {
00582                 object = (LLViewerObject*)object->getRoot();
00583         }
00584 
00585         object->addThisAndAllChildren(objects);
00586         remove(objects);
00587 
00588         if (!send_to_sim) return;
00589 
00590         //-----------------------------------------------------------
00591         // Inform simulator of deselection
00592         //-----------------------------------------------------------
00593         LLViewerRegion* regionp = object->getRegion();
00594 
00595         BOOL start_new_message = TRUE;
00596         S32 select_count = 0;
00597 
00598         LLMessageSystem* msg = gMessageSystem;
00599         for (U32 i = 0; i < objects.size(); i++)
00600         {
00601                 if (start_new_message)
00602                 {
00603                         msg->newMessageFast(_PREHASH_ObjectDeselect);
00604                         msg->nextBlockFast(_PREHASH_AgentData);
00605                         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00606                         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00607                         select_count++;
00608                         start_new_message = FALSE;
00609                 }
00610 
00611                 msg->nextBlockFast(_PREHASH_ObjectData);
00612                 msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID());
00613                 select_count++;
00614 
00615                 // Zap the angular velocity, as the sim will set it to zero
00616                 objects[i]->setAngularVelocity( 0,0,0 );
00617                 objects[i]->setVelocity( 0,0,0 );
00618 
00619                 if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET)
00620                 {
00621                         msg->sendReliable(regionp->getHost() );
00622                         select_count = 0;
00623                         start_new_message = TRUE;
00624                 }
00625         }
00626 
00627         if (!start_new_message)
00628         {
00629                 msg->sendReliable(regionp->getHost() );
00630         }
00631 
00632         updatePointAt();
00633         updateSelectionCenter();
00634 }
00635 
00636 void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim)
00637 {
00638         // bail if nothing selected or if object wasn't selected in the first place
00639         if (!object) return;
00640         if (!object->isSelected() ) return;
00641 
00642         // Zap the angular velocity, as the sim will set it to zero
00643         object->setAngularVelocity( 0,0,0 );
00644         object->setVelocity( 0,0,0 );
00645 
00646         if (send_to_sim)
00647         {
00648                 LLViewerRegion* region = object->getRegion();
00649                 gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect);
00650                 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
00651                 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00652                 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00653                 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
00654                 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
00655                 gMessageSystem->sendReliable(region->getHost());
00656         }
00657 
00658         // This will refresh dialogs.
00659         remove( object );
00660 
00661         updatePointAt();
00662         updateSelectionCenter();
00663 }
00664 
00665 
00666 //-----------------------------------------------------------------------------
00667 // addAsFamily
00668 //-----------------------------------------------------------------------------
00669 
00670 void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to_end)
00671 {
00672         for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
00673                  iter != objects.end(); ++iter)
00674         {
00675                 LLViewerObject* objectp = *iter;
00676                 
00677                 // Can't select yourself
00678                 if (objectp->mID == gAgentID
00679                         && !gAllowSelectAvatar)
00680                 {
00681                         continue;
00682                 }
00683 
00684                 if (!objectp->isSelected())
00685                 {
00686                         LLSelectNode *nodep = new LLSelectNode(objectp, TRUE);
00687                         if (add_to_end)
00688                         {
00689                                 mSelectedObjects->addNodeAtEnd(nodep);
00690                         }
00691                         else
00692                         {
00693                                 mSelectedObjects->addNode(nodep);
00694                         }
00695                         objectp->setSelected(TRUE);
00696 
00697                         if (objectp->getNumTEs() > 0)
00698                         {
00699                                 nodep->selectAllTEs(TRUE);
00700                         }
00701                         else
00702                         {
00703                                 // object has no faces, so don't mess with faces
00704                         }
00705                 }
00706                 else
00707                 {
00708                         // we want this object to be selected for real
00709                         // so clear transient flag
00710                         LLSelectNode* select_node = mSelectedObjects->findNode(objectp);
00711                         if (select_node)
00712                         {
00713                                 select_node->setTransient(FALSE);
00714                         }
00715                 }
00716         }
00717         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00718 }
00719 
00720 //-----------------------------------------------------------------------------
00721 // addAsIndividual() - a single object, face, etc
00722 //-----------------------------------------------------------------------------
00723 void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable)
00724 {
00725         // check to see if object is already in list
00726         LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
00727 
00728         // if not in list, add it
00729         if (!nodep)
00730         {
00731                 nodep = new LLSelectNode(objectp, TRUE);
00732                 mSelectedObjects->addNode(nodep);
00733                 llassert_always(nodep->getObject());
00734         }
00735         else
00736         {
00737                 // make this a full-fledged selection
00738                 nodep->setTransient(FALSE);
00739                 // Move it to the front of the list
00740                 mSelectedObjects->moveNodeToFront(nodep);
00741         }
00742 
00743         // Make sure the object is tagged as selected
00744         objectp->setSelected( TRUE );
00745 
00746         // And make sure we don't consider it as part of a family
00747         nodep->mIndividualSelection = TRUE;
00748 
00749         // Handle face selection
00750         if (objectp->getNumTEs() <= 0)
00751         {
00752                 // object has no faces, so don't do anything
00753         }
00754         else if (face == SELECT_ALL_TES)
00755         {
00756                 nodep->selectAllTEs(TRUE);
00757         }
00758         else if (0 <= face && face < SELECT_MAX_TES)
00759         {
00760                 nodep->selectTE(face, TRUE);
00761         }
00762         else
00763         {
00764                 llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl;
00765                 return;
00766         }
00767 
00768         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00769         updateSelectionCenter();
00770         dialog_refresh_all();
00771 }
00772 
00773 
00774 LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp)
00775 {
00776         // Always blitz hover list when setting
00777         mHoverObjects->deleteAllNodes();
00778 
00779         if (!objectp)
00780         {
00781                 return NULL;
00782         }
00783 
00784         // Can't select yourself
00785         if (objectp->mID == gAgentID)
00786         {
00787                 return NULL;
00788         }
00789 
00790         // Can't select land
00791         if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
00792         {
00793                 return NULL;
00794         }
00795 
00796         // Collect all of the objects
00797         LLDynamicArray<LLViewerObject*> objects;
00798         objectp = objectp->getRootEdit();
00799         objectp->addThisAndNonJointChildren(objects);
00800 
00801         for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
00802                  iter != objects.end(); ++iter)
00803         {
00804                 LLViewerObject* cur_objectp = *iter;
00805                 LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
00806                 mHoverObjects->addNodeAtEnd(nodep);
00807         }
00808 
00809         requestObjectPropertiesFamily(objectp);
00810         return mHoverObjects;
00811 }
00812 
00813 LLSelectNode *LLSelectMgr::getHoverNode()
00814 {
00815         return getHoverObjects()->getFirstRootNode();
00816 }
00817 
00818 void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
00819 {
00820         if (!objectp)
00821         {
00822                 return;
00823         }
00824 
00825         if (objectp->getPCode() != LL_PCODE_VOLUME)
00826         {
00827                 return;
00828         }
00829         
00830         if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) ||
00831                 (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
00832         {
00833                 // only select my own objects
00834                 return;
00835         }
00836 
00837         mRectSelectedObjects.insert(objectp);
00838 }
00839 
00840 void LLSelectMgr::highlightObjectAndFamily(LLViewerObject* objectp)
00841 {
00842         if (!objectp)
00843         {
00844                 return;
00845         }
00846 
00847         LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot();
00848 
00849         highlightObjectOnly(root_obj);
00850 
00851         for(U32 i = 0; i < root_obj->mChildList.size(); i++)
00852         {
00853                 highlightObjectOnly(root_obj->mChildList[i]);
00854         }
00855 }
00856 
00857 // Note that this ignores the "select owned only" flag
00858 // It's also more efficient than calling the single-object version over and over.
00859 void LLSelectMgr::highlightObjectAndFamily(const std::vector<LLViewerObject*>& objects)
00860 {
00861         for (std::vector<LLViewerObject*>::const_iterator iter1 = objects.begin();
00862                  iter1 != objects.end(); ++iter1)
00863         {
00864                 LLViewerObject* object = *iter1;
00865 
00866                 if (!object)
00867                 {
00868                         continue;
00869                 }
00870                 if (object->getPCode() != LL_PCODE_VOLUME)
00871                 {
00872                         continue;
00873                 }
00874 
00875                 LLViewerObject* root = (LLViewerObject*)object->getRoot();
00876                 mRectSelectedObjects.insert(root);
00877 
00878                 for (LLViewerObject::child_list_t::const_iterator iter2 = root->mChildList.begin();
00879                          iter2 != root->mChildList.end(); ++iter2)
00880                 {
00881                         LLViewerObject* child = *iter2;
00882                         mRectSelectedObjects.insert(child);
00883                 }
00884         }
00885 }
00886 
00887 void LLSelectMgr::unhighlightObjectOnly(LLViewerObject* objectp)
00888 {
00889         if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
00890         {
00891                 return;
00892         }
00893 
00894         mRectSelectedObjects.erase(objectp);
00895 }
00896 
00897 void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp)
00898 {
00899         if (!objectp)
00900         {
00901                 return;
00902         }
00903 
00904         LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot();
00905 
00906         unhighlightObjectOnly(root_obj);
00907 
00908         for (LLViewerObject::child_list_t::iterator iter2 = root_obj->mChildList.begin();
00909                  iter2 != root_obj->mChildList.end(); ++iter2)
00910         {
00911                 LLViewerObject* child = *iter2;
00912                 unhighlightObjectOnly(child);
00913         }
00914 }
00915 
00916 
00917 void LLSelectMgr::unhighlightAll()
00918 {
00919         mRectSelectedObjects.clear();
00920         mHighlightedObjects->deleteAllNodes();
00921 }
00922 
00923 LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects()
00924 {
00925         if (!mHighlightedObjects->getNumNodes())
00926         {
00927                 return NULL;
00928         }
00929 
00930         //clear primary object
00931         mSelectedObjects->mPrimaryObject = NULL;
00932 
00933         for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin();
00934                  iter != getHighlightedObjects()->end(); )
00935         {
00936                 LLObjectSelection::iterator curiter = iter++;
00937         
00938                 LLSelectNode *nodep = *curiter;
00939                 LLViewerObject* objectp = nodep->getObject();
00940 
00941                 if (!canSelectObject(objectp))
00942                 {
00943                         continue;
00944                 }
00945 
00946                 // already selected
00947                 if (objectp->isSelected())
00948                 {
00949                         continue;
00950                 }
00951 
00952                 LLSelectNode* new_nodep = new LLSelectNode(*nodep);
00953                 mSelectedObjects->addNode(new_nodep);
00954 
00955                 // flag this object as selected
00956                 objectp->setSelected(TRUE);
00957 
00958                 mSelectedObjects->mSelectType = getSelectTypeForObject(objectp);
00959 
00960                 // request properties on root objects
00961                 if (objectp->isRootEdit())
00962                 {
00963                         requestObjectPropertiesFamily(objectp);
00964                 }
00965         }
00966 
00967         // pack up messages to let sim know these objects are selected
00968         sendSelect();
00969         unhighlightAll();
00970         updateSelectionCenter();
00971         saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
00972         updatePointAt();
00973 
00974         if (mSelectedObjects->getObjectCount())
00975         {
00976                 gEditMenuHandler = this;
00977         }
00978 
00979         return mSelectedObjects;
00980 }
00981 
00982 void LLSelectMgr::deselectHighlightedObjects()
00983 {
00984         BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
00985         for (std::set<LLPointer<LLViewerObject> >::iterator iter = mRectSelectedObjects.begin();
00986                  iter != mRectSelectedObjects.end(); iter++)
00987         {
00988                 LLViewerObject *objectp = *iter;
00989                 if (!select_linked_set)
00990                 {
00991                         deselectObjectOnly(objectp);
00992                 }
00993                 else
00994                 {
00995                         LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot();
00996                         if (root_object->isSelected())
00997                         {
00998                                 deselectObjectAndFamily(root_object);
00999                         }
01000                 }
01001         }
01002 
01003         unhighlightAll();
01004 }
01005 
01006 void LLSelectMgr::addGridObject(LLViewerObject* objectp)
01007 {
01008         LLSelectNode* nodep = new LLSelectNode(objectp, FALSE);
01009         mGridObjects.addNodeAtEnd(nodep);
01010 
01011         for (LLViewerObject::child_list_t::iterator iter2 = objectp->mChildList.begin();
01012                  iter2 != objectp->mChildList.end(); ++iter2)
01013         {
01014                 LLViewerObject* child = *iter2;
01015                 nodep = new LLSelectNode(child, FALSE);
01016                 mGridObjects.addNodeAtEnd(nodep);
01017         }
01018 }
01019 
01020 void LLSelectMgr::clearGridObjects()
01021 {
01022         mGridObjects.deleteAllNodes();
01023 }
01024 
01025 void LLSelectMgr::setGridMode(EGridMode mode)
01026 {
01027         mGridMode = mode;
01028         gSavedSettings.setS32("GridMode", mode);
01029         updateSelectionCenter();
01030         mGridValid = FALSE;
01031 }
01032 
01033 void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale)
01034 {
01035         mGridObjects.cleanupNodes();
01036         
01037         LLViewerObject* first_grid_object = mGridObjects.getFirstObject();
01038 
01039         if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount())
01040         {
01041                 LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject());
01042                 LLBBox bbox = mSavedSelectionBBox;
01043                 mGridOrigin = mSavedSelectionBBox.getCenterAgent();
01044                 mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f;
01045 
01046                 if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull())
01047                 {
01048                         mGridRotation = mSavedSelectionBBox.getRotation();
01049                 }
01050                 else //set to the root object
01051                 {
01052                         mGridRotation = root->getRenderRotation();                      
01053                 }
01054         }
01055         else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull())
01056         {
01057                 mGridRotation = first_grid_object->getRenderRotation();
01058                 LLVector3 first_grid_obj_pos = first_grid_object->getRenderPosition();
01059 
01060                 LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX);
01061                 LLVector3 max_extents(-F32_MAX, -F32_MAX, -F32_MAX);
01062                 BOOL grid_changed = FALSE;
01063                 for (LLObjectSelection::iterator iter = mGridObjects.begin();
01064                          iter != mGridObjects.end(); ++iter)
01065                 {
01066                         LLViewerObject* object = (*iter)->getObject();
01067                         LLDrawable* drawable = object->mDrawable;
01068                         if (drawable)
01069                         {
01070                                 const LLVector3* ext = drawable->getSpatialExtents();
01071                                 update_min_max(min_extents, max_extents, ext[0]);
01072                                 update_min_max(min_extents, max_extents, ext[1]);
01073                                 grid_changed = TRUE;
01074                         }
01075                 }
01076                 if (grid_changed)
01077                 {
01078                         mGridOrigin = lerp(min_extents, max_extents, 0.5f);
01079                         LLDrawable* drawable = first_grid_object->mDrawable;
01080                         if (drawable && drawable->isActive())
01081                         {
01082                                 mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix();
01083                         }
01084                         mGridScale = (max_extents - min_extents) * 0.5f;
01085                 }
01086         }
01087         else // GRID_MODE_WORLD or just plain default
01088         {
01089                 const BOOL non_root_ok = TRUE;
01090                 LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok);
01091 
01092                 mGridOrigin.clearVec();
01093                 mGridRotation.loadIdentity();
01094 
01095                 mSelectedObjects->mSelectType = getSelectTypeForObject( first_object );
01096 
01097                 switch (mSelectedObjects->mSelectType)
01098                 {
01099                 case SELECT_TYPE_ATTACHMENT:
01100                         if (first_object)
01101                         {
01102                                 // this means this object *has* to be an attachment
01103                                 LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent();
01104                                 mGridOrigin = attachment_point_xform->getWorldPosition();
01105                                 mGridRotation = attachment_point_xform->getWorldRotation();
01106                                 mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution");
01107                         }
01108                         break;
01109                 case SELECT_TYPE_HUD:
01110                         // use HUD-scaled grid
01111                         mGridScale = LLVector3(0.25f, 0.25f, 0.25f);
01112                         break;
01113                 case SELECT_TYPE_WORLD:
01114                         mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution");
01115                         break;
01116                 }
01117         }
01118         llassert(mGridOrigin.isFinite());
01119 
01120         origin = mGridOrigin;
01121         rotation = mGridRotation;
01122         scale = mGridScale;
01123         mGridValid = TRUE;
01124 }
01125 
01126 //-----------------------------------------------------------------------------
01127 // remove() - an array of objects
01128 //-----------------------------------------------------------------------------
01129 
01130 void LLSelectMgr::remove(std::vector<LLViewerObject*>& objects)
01131 {
01132         for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
01133                  iter != objects.end(); ++iter)
01134         {
01135                 LLViewerObject* objectp = *iter;
01136                 LLSelectNode* nodep = mSelectedObjects->findNode(objectp);
01137                 if (nodep)
01138                 {
01139                         objectp->setSelected(FALSE);
01140                         mSelectedObjects->removeNode(nodep);
01141                         nodep = NULL;
01142                 }
01143         }
01144         updateSelectionCenter();
01145         dialog_refresh_all();
01146 }
01147 
01148 
01149 //-----------------------------------------------------------------------------
01150 // remove() - a single object
01151 //-----------------------------------------------------------------------------
01152 void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
01153 {
01154         // get object node (and verify it is in the selected list)
01155         LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
01156         if (!nodep)
01157         {
01158                 return;
01159         }
01160 
01161         // if face = all, remove object from list
01162         if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES))
01163         {
01164                 // Remove all faces (or the object doesn't have faces) so remove the node
01165                 mSelectedObjects->removeNode(nodep);
01166                 nodep = NULL;
01167                 objectp->setSelected( FALSE );
01168         }
01169         else if (0 <= te && te < SELECT_MAX_TES)
01170         {
01171                 // ...valid face, check to see if it was on
01172                 if (nodep->isTESelected(te))
01173                 {
01174                         nodep->selectTE(te, FALSE);
01175                 }
01176                 else
01177                 {
01178                         llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl;
01179                         return;
01180                 }
01181 
01182                 // ...check to see if this operation turned off all faces
01183                 BOOL found = FALSE;
01184                 for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++)
01185                 {
01186                         found = found || nodep->isTESelected(i);
01187                 }
01188 
01189                 // ...all faces now turned off, so remove
01190                 if (!found)
01191                 {
01192                         mSelectedObjects->removeNode(nodep);
01193                         nodep = NULL;
01194                         objectp->setSelected( FALSE );
01195                         // *FIXME: Doesn't update simulator that object is no longer selected
01196                 }
01197         }
01198         else
01199         {
01200                 // ...out of range face
01201                 llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl;
01202         }
01203 
01204         updateSelectionCenter();
01205         dialog_refresh_all();
01206 }
01207 
01208 
01209 //-----------------------------------------------------------------------------
01210 // removeAll()
01211 //-----------------------------------------------------------------------------
01212 void LLSelectMgr::removeAll()
01213 {
01214         for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
01215                  iter != mSelectedObjects->end(); iter++ )
01216         {
01217                 LLViewerObject *objectp = (*iter)->getObject();
01218                 objectp->setSelected( FALSE );
01219         }
01220 
01221         mSelectedObjects->deleteAllNodes();
01222         
01223         updateSelectionCenter();
01224         dialog_refresh_all();
01225 }
01226 
01227 //-----------------------------------------------------------------------------
01228 // promoteSelectionToRoot()
01229 //-----------------------------------------------------------------------------
01230 void LLSelectMgr::promoteSelectionToRoot()
01231 {
01232         std::set<LLViewerObject*> selection_set;
01233 
01234         BOOL selection_changed = FALSE;
01235 
01236         for (LLObjectSelection::iterator iter = getSelection()->begin();
01237                  iter != getSelection()->end(); )
01238         {
01239                 LLObjectSelection::iterator curiter = iter++;
01240                 LLSelectNode* nodep = *curiter;
01241                 LLViewerObject* object = nodep->getObject();
01242 
01243                 if (nodep->mIndividualSelection)
01244                 {
01245                         selection_changed = TRUE;
01246                 }
01247 
01248                 LLViewerObject* parentp = object;
01249                 while(parentp->getParent() && !(parentp->isRootEdit() || parentp->isJointChild()))
01250                 {
01251                         parentp = (LLViewerObject*)parentp->getParent();
01252                 }
01253         
01254                 selection_set.insert(parentp);
01255         }
01256 
01257         if (selection_changed)
01258         {
01259                 deselectAll();
01260 
01261                 std::set<LLViewerObject*>::iterator set_iter;
01262                 for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter)
01263                 {
01264                         selectObjectAndFamily(*set_iter);
01265                 }
01266         }
01267 }
01268 
01269 //-----------------------------------------------------------------------------
01270 // demoteSelectionToIndividuals()
01271 //-----------------------------------------------------------------------------
01272 void LLSelectMgr::demoteSelectionToIndividuals()
01273 {
01274         LLDynamicArray<LLViewerObject*> objects;
01275 
01276         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
01277                  iter != getSelection()->root_end(); iter++)
01278         {
01279                 LLViewerObject* object = (*iter)->getObject();
01280                 object->addThisAndNonJointChildren(objects);
01281         }
01282 
01283         if (objects.getLength())
01284         {
01285                 deselectAll();
01286                 for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
01287                          iter != objects.end(); ++iter)
01288                 {
01289                         LLViewerObject* objectp = *iter;
01290                         selectObjectOnly(objectp);
01291                 }
01292         }
01293 }
01294 
01295 //-----------------------------------------------------------------------------
01296 // dump()
01297 //-----------------------------------------------------------------------------
01298 void LLSelectMgr::dump()
01299 {
01300         llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl;
01301 
01302         llinfos << "TE mode " << mTEMode << llendl;
01303 
01304         S32 count = 0;
01305         for (LLObjectSelection::iterator iter = getSelection()->begin();
01306                  iter != getSelection()->end(); iter++ )
01307         {
01308                 LLViewerObject* objectp = (*iter)->getObject();
01309                 llinfos << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl;
01310                 llinfos << "  hasLSL " << objectp->flagScripted() << llendl;
01311                 llinfos << "  hasTouch " << objectp->flagHandleTouch() << llendl;
01312                 llinfos << "  hasMoney " << objectp->flagTakesMoney() << llendl;
01313                 llinfos << "  getposition " << objectp->getPosition() << llendl;
01314                 llinfos << "  getpositionAgent " << objectp->getPositionAgent() << llendl;
01315                 llinfos << "  getpositionRegion " << objectp->getPositionRegion() << llendl;
01316                 llinfos << "  getpositionGlobal " << objectp->getPositionGlobal() << llendl;
01317                 LLDrawable* drawablep = objectp->mDrawable;
01318                 llinfos << "  " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << llendl;
01319                 llinfos << "  " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << llendl;
01320                 count++;
01321         }
01322 
01323         // Face iterator
01324         for (LLObjectSelection::iterator iter = getSelection()->begin();
01325                  iter != getSelection()->end(); iter++ )
01326         {
01327                 LLSelectNode* node = *iter;
01328                 LLViewerObject* objectp = node->getObject();
01329                 if (!objectp)
01330                         continue;
01331                 for (S32 te = 0; te < objectp->getNumTEs(); ++te )
01332                 {
01333                         if (node->isTESelected(te))
01334                         {
01335                                 llinfos << "Object " << objectp << " te " << te << llendl;
01336                         }
01337                 }
01338         }
01339 
01340         llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl;
01341 
01342         llinfos << "Center global " << mSelectionCenterGlobal << llendl;
01343 }
01344 
01345 //-----------------------------------------------------------------------------
01346 // cleanup()
01347 //-----------------------------------------------------------------------------
01348 void LLSelectMgr::cleanup()
01349 {
01350         mSilhouetteImagep = NULL;
01351 }
01352 
01353 
01354 //---------------------------------------------------------------------------
01355 // Manipulate properties of selected objects
01356 //---------------------------------------------------------------------------
01357 
01358 struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor
01359 {
01360         virtual bool apply(LLViewerObject* object)
01361         {
01362                 if (object->permModify())
01363                 {
01364                         object->sendTEUpdate();
01365                 }
01366                 return true;
01367         }
01368 };
01369 
01370 //-----------------------------------------------------------------------------
01371 // selectionSetImage()
01372 //-----------------------------------------------------------------------------
01373 // *TODO: re-arch texture applying out of lltooldraganddrop
01374 void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
01375 {
01376         // First for (no copy) textures and multiple object selection
01377         LLViewerInventoryItem* item = gInventory.getItem(imageid);
01378         if(item 
01379                 && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
01380                 && (mSelectedObjects->getNumNodes() > 1) )
01381         {
01382                 llwarns << "Attempted to apply no-copy texture to multiple objects"
01383                                 << llendl;
01384                 return;
01385         }
01386 
01387         struct f : public LLSelectedTEFunctor
01388         {
01389                 LLViewerInventoryItem* mItem;
01390                 LLUUID mImageID;
01391                 f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {}
01392                 bool apply(LLViewerObject* objectp, S32 te)
01393                 {
01394                         if (mItem)
01395                         {
01396                                 if (te == -1) // all faces
01397                                 {
01398                                         LLToolDragAndDrop::dropTextureAllFaces(objectp,
01399                                                                                                                    mItem,
01400                                                                                                                    LLToolDragAndDrop::SOURCE_AGENT,
01401                                                                                                                    LLUUID::null);
01402                                 }
01403                                 else // one face
01404                                 {
01405                                         LLToolDragAndDrop::dropTextureOneFace(objectp,
01406                                                                                                                   te,
01407                                                                                                                   mItem,
01408                                                                                                                   LLToolDragAndDrop::SOURCE_AGENT,
01409                                                                                                                   LLUUID::null);
01410                                 }
01411                         }
01412                         else // not an inventory item
01413                         {
01414                                 // Texture picker defaults aren't inventory items
01415                                 // * Don't need to worry about permissions for them
01416                                 // * Can just apply the texture and be done with it.
01417                                 objectp->setTEImage(te, gImageList.getImage(mImageID, TRUE, FALSE));
01418                         }
01419                         return true;
01420                 }
01421         } setfunc(item, imageid);
01422         getSelection()->applyToTEs(&setfunc);
01423 
01424         struct g : public LLSelectedObjectFunctor
01425         {
01426                 LLViewerInventoryItem* mItem;
01427                 g(LLViewerInventoryItem* item) : mItem(item) {}
01428                 virtual bool apply(LLViewerObject* object)
01429                 {
01430                         if (!mItem)
01431                         {
01432                                 object->sendTEUpdate();
01433                                 // 1 particle effect per object                         
01434                                 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01435                                 effectp->setSourceObject(gAgent.getAvatarObject());
01436                                 effectp->setTargetObject(object);
01437                                 effectp->setDuration(LL_HUD_DUR_SHORT);
01438                                 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01439                         }
01440                         return true;
01441                 }
01442         } sendfunc(item);
01443         getSelection()->applyToObjects(&sendfunc);
01444 }
01445 
01446 //-----------------------------------------------------------------------------
01447 // selectionSetColor()
01448 //-----------------------------------------------------------------------------
01449 void LLSelectMgr::selectionSetColor(const LLColor4 &color)
01450 {
01451         struct f : public LLSelectedTEFunctor
01452         {
01453                 LLColor4 mColor;
01454                 f(const LLColor4& c) : mColor(c) {}
01455                 bool apply(LLViewerObject* object, S32 te)
01456                 {
01457                         if (object->permModify())
01458                         {
01459                                 object->setTEColor(te, mColor);
01460                         }
01461                         return true;
01462                 }
01463         } setfunc(color);
01464         getSelection()->applyToTEs(&setfunc);
01465         
01466         LLSelectMgrSendFunctor sendfunc;
01467         getSelection()->applyToObjects(&sendfunc);
01468 }
01469 
01470 //-----------------------------------------------------------------------------
01471 // selectionSetColorOnly()
01472 //-----------------------------------------------------------------------------
01473 void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color)
01474 {
01475         struct f : public LLSelectedTEFunctor
01476         {
01477                 LLColor4 mColor;
01478                 f(const LLColor4& c) : mColor(c) {}
01479                 bool apply(LLViewerObject* object, S32 te)
01480                 {
01481                         if (object->permModify())
01482                         {
01483                                 LLColor4 prev_color = object->getTE(te)->getColor();
01484                                 mColor.mV[VALPHA] = prev_color.mV[VALPHA];
01485                                 // update viewer side color in anticipation of update from simulator
01486                                 object->setTEColor(te, mColor);
01487                         }
01488                         return true;
01489                 }
01490         } setfunc(color);
01491         getSelection()->applyToTEs(&setfunc);
01492         
01493         LLSelectMgrSendFunctor sendfunc;
01494         getSelection()->applyToObjects(&sendfunc);
01495 }
01496 
01497 //-----------------------------------------------------------------------------
01498 // selectionSetAlphaOnly()
01499 //-----------------------------------------------------------------------------
01500 void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha)
01501 {
01502         struct f : public LLSelectedTEFunctor
01503         {
01504                 F32 mAlpha;
01505                 f(const F32& a) : mAlpha(a) {}
01506                 bool apply(LLViewerObject* object, S32 te)
01507                 {
01508                         if (object->permModify())
01509                         {
01510                                 LLColor4 prev_color = object->getTE(te)->getColor();
01511                                 prev_color.mV[VALPHA] = mAlpha;
01512                                 // update viewer side color in anticipation of update from simulator
01513                                 object->setTEColor(te, prev_color);
01514                         }
01515                         return true;
01516                 }
01517         } setfunc(alpha);
01518         getSelection()->applyToTEs(&setfunc);
01519         
01520         LLSelectMgrSendFunctor sendfunc;
01521         getSelection()->applyToObjects(&sendfunc);
01522 }
01523 
01524 void LLSelectMgr::selectionRevertColors()
01525 {
01526         struct f : public LLSelectedTEFunctor
01527         {
01528                 LLObjectSelectionHandle mSelectedObjects;
01529                 f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {}
01530                 bool apply(LLViewerObject* object, S32 te)
01531                 {
01532                         if (object->permModify())
01533                         {
01534                                 LLSelectNode* nodep = mSelectedObjects->findNode(object);
01535                                 if (nodep && te < (S32)nodep->mSavedColors.size())
01536                                 {
01537                                         LLColor4 color = nodep->mSavedColors[te];
01538                                         // update viewer side color in anticipation of update from simulator
01539                                         object->setTEColor(te, color);
01540                                 }
01541                         }
01542                         return true;
01543                 }
01544         } setfunc(mSelectedObjects);
01545         getSelection()->applyToTEs(&setfunc);
01546         
01547         LLSelectMgrSendFunctor sendfunc;
01548         getSelection()->applyToObjects(&sendfunc);
01549 }
01550 
01551 BOOL LLSelectMgr::selectionRevertTextures()
01552 {
01553         struct f : public LLSelectedTEFunctor
01554         {
01555                 LLObjectSelectionHandle mSelectedObjects;
01556                 f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {}
01557                 bool apply(LLViewerObject* object, S32 te)
01558                 {
01559                         if (object->permModify())
01560                         {
01561                                 LLSelectNode* nodep = mSelectedObjects->findNode(object);
01562                                 if (nodep && te < (S32)nodep->mSavedTextures.size())
01563                                 {
01564                                         LLUUID id = nodep->mSavedTextures[te];
01565                                         // update textures on viewer side
01566                                         if (id.isNull())
01567                                         {
01568                                                 // this was probably a no-copy texture, leave image as-is
01569                                                 return FALSE;
01570                                         }
01571                                         else
01572                                         {
01573                                                 object->setTEImage(te, gImageList.getImage(id));
01574                                         }
01575                                 }
01576                         }
01577                         return true;
01578                 }
01579         } setfunc(mSelectedObjects);
01580         BOOL revert_successful = getSelection()->applyToTEs(&setfunc);
01581         
01582         LLSelectMgrSendFunctor sendfunc;
01583         getSelection()->applyToObjects(&sendfunc);
01584 
01585         return revert_successful;
01586 }
01587 
01588 void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
01589 {
01590         struct f : public LLSelectedTEFunctor
01591         {
01592                 U8 mBump;
01593                 f(const U8& b) : mBump(b) {}
01594                 bool apply(LLViewerObject* object, S32 te)
01595                 {
01596                         if (object->permModify())
01597                         {
01598                                 // update viewer side color in anticipation of update from simulator
01599                                 object->setTEBumpmap(te, mBump);
01600                         }
01601                         return true;
01602                 }
01603         } setfunc(bumpmap);
01604         getSelection()->applyToTEs(&setfunc);
01605         
01606         LLSelectMgrSendFunctor sendfunc;
01607         getSelection()->applyToObjects(&sendfunc);
01608 }
01609 
01610 void LLSelectMgr::selectionSetTexGen(U8 texgen)
01611 {
01612         struct f : public LLSelectedTEFunctor
01613         {
01614                 U8 mTexgen;
01615                 f(const U8& t) : mTexgen(t) {}
01616                 bool apply(LLViewerObject* object, S32 te)
01617                 {
01618                         if (object->permModify())
01619                         {
01620                                 // update viewer side color in anticipation of update from simulator
01621                                 object->setTETexGen(te, mTexgen);
01622                         }
01623                         return true;
01624                 }
01625         } setfunc(texgen);
01626         getSelection()->applyToTEs(&setfunc);
01627 
01628         LLSelectMgrSendFunctor sendfunc;
01629         getSelection()->applyToObjects(&sendfunc);
01630 }
01631 
01632 
01633 void LLSelectMgr::selectionSetShiny(U8 shiny)
01634 {
01635         struct f : public LLSelectedTEFunctor
01636         {
01637                 U8 mShiny;
01638                 f(const U8& t) : mShiny(t) {}
01639                 bool apply(LLViewerObject* object, S32 te)
01640                 {
01641                         if (object->permModify())
01642                         {
01643                                 // update viewer side color in anticipation of update from simulator
01644                                 object->setTEShiny(te, mShiny);
01645                         }
01646                         return true;
01647                 }
01648         } setfunc(shiny);
01649         getSelection()->applyToTEs(&setfunc);
01650 
01651         LLSelectMgrSendFunctor sendfunc;
01652         getSelection()->applyToObjects(&sendfunc);
01653 }
01654 
01655 void LLSelectMgr::selectionSetFullbright(U8 fullbright)
01656 {
01657         struct f : public LLSelectedTEFunctor
01658         {
01659                 U8 mFullbright;
01660                 f(const U8& t) : mFullbright(t) {}
01661                 bool apply(LLViewerObject* object, S32 te)
01662                 {
01663                         if (object->permModify())
01664                         {
01665                                 // update viewer side color in anticipation of update from simulator
01666                                 object->setTEFullbright(te, mFullbright);
01667                         }
01668                         return true;
01669                 }
01670         } setfunc(fullbright);
01671         getSelection()->applyToTEs(&setfunc);
01672 
01673         struct g : public LLSelectedObjectFunctor
01674         {
01675                 U8 mFullbright;
01676                 g(const U8& t) : mFullbright(t) {}
01677                 virtual bool apply(LLViewerObject* object)
01678                 {
01679                         if (object->permModify())
01680                         {
01681                                 object->sendTEUpdate();
01682                                 if (mFullbright)
01683                                 {
01684                                         U8 material = object->getMaterial();
01685                                         U8 mcode = material & LL_MCODE_MASK;
01686                                         if (mcode == LL_MCODE_LIGHT)
01687                                         {
01688                                                 mcode = LL_MCODE_GLASS;
01689                                                 material = (material & ~LL_MCODE_MASK) | mcode;
01690                                                 object->setMaterial(material);
01691                                                 object->sendMaterialUpdate();
01692                                         }
01693                                 }
01694                         }
01695                         return true;
01696                 }
01697         } sendfunc(fullbright);
01698         getSelection()->applyToObjects(&sendfunc);
01699 }
01700 
01701 void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url)
01702 {
01703         U8 media_flags = LLTextureEntry::MF_NONE;
01704         if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE)
01705         {
01706                 media_flags = LLTextureEntry::MF_WEB_PAGE;
01707         }
01708         
01709         struct f : public LLSelectedTEFunctor
01710         {
01711                 U8 mMediaFlags;
01712                 f(const U8& t) : mMediaFlags(t) {}
01713                 bool apply(LLViewerObject* object, S32 te)
01714                 {
01715                         if (object->permModify())
01716                         {
01717                                 // update viewer side color in anticipation of update from simulator
01718                                 object->setTEMediaFlags(te, mMediaFlags);
01719                         }
01720                         return true;
01721                 }
01722         } setfunc(media_flags);
01723         getSelection()->applyToTEs(&setfunc);
01724 
01725         struct g : public LLSelectedObjectFunctor
01726         {
01727                 U8 media_type;
01728                 const std::string& media_url ;
01729                 g(U8 a, const std::string& b) : media_type(a), media_url(b) {}
01730                 virtual bool apply(LLViewerObject* object)
01731                 {
01732                         if (object->permModify())
01733                         {
01734                                 object->sendTEUpdate();
01735                                 object->setMediaType(media_type);
01736                                 object->setMediaURL(media_url);
01737                         }
01738                         return true;
01739                 }
01740         } sendfunc(media_type, media_url);
01741         getSelection()->applyToObjects(&sendfunc);
01742 }
01743 
01744 void LLSelectMgr::selectionSetGlow(F32 glow)
01745 {
01746         struct f1 : public LLSelectedTEFunctor
01747         {
01748                 F32 mGlow;
01749                 f1(F32 glow) : mGlow(glow) {};
01750                 bool apply(LLViewerObject* object, S32 face)
01751                 {
01752                         if (object->permModify())
01753                         {
01754                                 // update viewer side color in anticipation of update from simulator
01755                                 object->setTEGlow(face, mGlow);
01756                         }
01757                         return true;
01758                 }
01759         } func1(glow);
01760         mSelectedObjects->applyToTEs( &func1 );
01761 
01762         struct f2 : public LLSelectedObjectFunctor
01763         {
01764                 virtual bool apply(LLViewerObject* object)
01765                 {
01766                         if (object->permModify())
01767                         {
01768                                 object->sendTEUpdate();
01769                         }
01770                         return true;
01771                 }
01772         } func2;
01773         mSelectedObjects->applyToObjects( &func2 );
01774 }
01775 
01776 
01777 //-----------------------------------------------------------------------------
01778 // findObjectPermissions()
01779 //-----------------------------------------------------------------------------
01780 LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object)
01781 {
01782         for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin();
01783                  iter != getSelection()->valid_end(); iter++ )
01784         {
01785                 LLSelectNode* nodep = *iter;
01786                 if (nodep->getObject() == object)
01787                 {
01788                         return nodep->mPermissions;
01789                 }
01790         }
01791 
01792         return NULL;
01793 }
01794 
01795 
01796 //-----------------------------------------------------------------------------
01797 // selectionGetGlow()
01798 //-----------------------------------------------------------------------------
01799 BOOL LLSelectMgr::selectionGetGlow(F32 *glow)
01800 {
01801         BOOL identical;
01802         F32 lglow = 0.f;
01803         struct f1 : public LLSelectedTEGetFunctor<F32>
01804         {
01805                 F32 get(LLViewerObject* object, S32 face)
01806                 {
01807                         return object->getTE(face)->getGlow();
01808                 }
01809         } func;
01810         identical = mSelectedObjects->getSelectedTEValue( &func, lglow );
01811 
01812         *glow = lglow;
01813         return identical;
01814 }
01815 
01816 //-----------------------------------------------------------------------------
01817 // selectionSetMaterial()
01818 //-----------------------------------------------------------------------------
01819 void LLSelectMgr::selectionSetMaterial(U8 material)
01820 {
01821         struct f : public LLSelectedObjectFunctor
01822         {
01823                 U8 mMaterial;
01824                 f(const U8& t) : mMaterial(t) {}
01825                 virtual bool apply(LLViewerObject* object)
01826                 {
01827                         if (object->permModify())
01828                         {
01829                                 U8 cur_material = object->getMaterial();
01830                                 U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK);
01831                                 object->setMaterial(material);
01832                                 object->sendMaterialUpdate();
01833                         }
01834                         return true;
01835                 }
01836         } sendfunc(material);
01837         getSelection()->applyToObjects(&sendfunc);
01838 }
01839 
01840 // TRUE if all selected objects have this PCode
01841 BOOL LLSelectMgr::selectionAllPCode(LLPCode code)
01842 {
01843         struct f : public LLSelectedObjectFunctor
01844         {
01845                 LLPCode mCode;
01846                 f(const LLPCode& t) : mCode(t) {}
01847                 virtual bool apply(LLViewerObject* object)
01848                 {
01849                         if (object->getPCode() != mCode)
01850                         {
01851                                 return FALSE;
01852                         }
01853                         return true;
01854                 }
01855         } func(code);
01856         BOOL res = getSelection()->applyToObjects(&func);
01857         return res;
01858 }
01859 
01860 bool LLSelectMgr::selectionGetIncludeInSearch(bool* include_in_search_out)
01861 {
01862         LLViewerObject *object = mSelectedObjects->getFirstRootObject();
01863         if (!object) return FALSE;
01864 
01865         bool include_in_search = object->getIncludeInSearch();
01866 
01867         bool identical = true;
01868 
01869         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
01870                  iter != getSelection()->root_end(); iter++)
01871         {
01872                 LLViewerObject* object = (*iter)->getObject();
01873 
01874                 if ( include_in_search != object->getIncludeInSearch())
01875                 {
01876                         identical = false;
01877                         break;
01878                 }
01879         }
01880 
01881         *include_in_search_out = include_in_search;
01882         return identical;
01883 }
01884 
01885 void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search)
01886 {
01887         LLViewerObject* object = NULL;
01888         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
01889                  iter != getSelection()->root_end(); iter++)
01890         {
01891                 object = (*iter)->getObject();
01892                 object->setIncludeInSearch(include_in_search);
01893         }
01894         sendListToRegions(
01895                 "ObjectIncludeInSearch",
01896                 packAgentAndSessionID,
01897                 packObjectIncludeInSearch, 
01898                 &include_in_search,
01899                 SEND_ONLY_ROOTS);
01900 }
01901 
01902 BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action)
01903 {
01904         LLViewerObject *object = mSelectedObjects->getFirstObject();
01905         if (!object)
01906         {
01907                 return FALSE;
01908         }
01909         
01910         U8 action = object->getClickAction();
01911         *out_action = action;
01912 
01913         struct f : public LLSelectedObjectFunctor
01914         {
01915                 U8 mAction;
01916                 f(const U8& t) : mAction(t) {}
01917                 virtual bool apply(LLViewerObject* object)
01918                 {
01919                         if ( mAction != object->getClickAction())
01920                         {
01921                                 return false;
01922                         }
01923                         return true;
01924                 }
01925         } func(action);
01926         BOOL res = getSelection()->applyToObjects(&func);
01927         return res;
01928 }
01929 
01930 void LLSelectMgr::selectionSetClickAction(U8 action)
01931 {
01932         struct f : public LLSelectedObjectFunctor
01933         {
01934                 U8 mAction;
01935                 f(const U8& t) : mAction(t) {}
01936                 virtual bool apply(LLViewerObject* object)
01937                 {
01938                         object->setClickAction(mAction);
01939                         return true;
01940                 }
01941         } func(action);
01942         getSelection()->applyToObjects(&func);
01943 
01944         sendListToRegions("ObjectClickAction",
01945                                           packAgentAndSessionID,
01946                                           packObjectClickAction, 
01947                                           &action,
01948                                           SEND_INDIVIDUALS);
01949 }
01950 
01951 
01952 //-----------------------------------------------------------------------------
01953 // godlike requests
01954 //-----------------------------------------------------------------------------
01955 
01956 typedef std::pair<const LLString, const LLString> godlike_request_t;
01957 void LLSelectMgr::sendGodlikeRequest(const LLString& request, const LLString& param)
01958 {
01959         // If the agent is neither godlike nor an estate owner, the server
01960         // will reject the request.
01961         LLString message_type;
01962         if (gAgent.isGodlike())
01963         {
01964                 message_type = "GodlikeMessage";
01965         }
01966         else
01967         {
01968                 message_type = "EstateOwnerMessage";
01969         }
01970 
01971         godlike_request_t data(request, param);
01972         if(!mSelectedObjects->getRootObjectCount())
01973         {
01974                 LLMessageSystem* msg = gMessageSystem;
01975                 msg->newMessage(message_type.c_str());
01976                 LLSelectMgr::packGodlikeHead(&data);
01977                 gAgent.sendReliableMessage();
01978         }
01979         else
01980         {
01981                 sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS);
01982         }
01983 }
01984 
01985 void LLSelectMgr::packGodlikeHead(void* user_data)
01986 {
01987         LLMessageSystem* msg = gMessageSystem;
01988         msg->nextBlockFast(_PREHASH_AgentData);
01989         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01990         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01991         msg->addUUID("TransactionID", LLUUID::null);
01992         godlike_request_t* data = (godlike_request_t*)user_data;
01993         msg->nextBlock("MethodData");
01994         msg->addString("Method", data->first.c_str());
01995         msg->addUUID("Invoice", LLUUID::null);
01996 
01997         // The parameters used to be restricted to either string or
01998         // integer. This mimics that behavior under the new 'string-only'
01999         // parameter list by not packing a string if there wasn't one
02000         // specified. The object ids will be packed in the
02001         // packObjectIDAsParam() method.
02002         if(data->second.size() > 0)
02003         {
02004                 msg->nextBlock("ParamList");
02005                 msg->addString("Parameter", data->second);
02006         }
02007 }
02008 
02009 // static
02010 void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *)
02011 {
02012         char buf [MAX_STRING];          /* Flawfinder: ignore */
02013         snprintf(buf, MAX_STRING, "%u", node->getObject()->getLocalID());                       /* Flawfinder: ignore */
02014         gMessageSystem->nextBlock("ParamList");
02015         gMessageSystem->addString("Parameter", buf);
02016 }
02017 
02018 //-----------------------------------------------------------------------------
02019 // Rotation options
02020 //-----------------------------------------------------------------------------
02021 void LLSelectMgr::selectionResetRotation()
02022 {
02023         struct f : public LLSelectedObjectFunctor
02024         {
02025                 virtual bool apply(LLViewerObject* object)
02026                 {
02027                         LLQuaternion identity(0.f, 0.f, 0.f, 1.f);
02028                         object->setRotation(identity);
02029                         if (object->mDrawable.notNull())
02030                         {
02031                                 gPipeline.markMoved(object->mDrawable, TRUE);
02032                         }
02033                         object->sendRotationUpdate();
02034                         return true;
02035                 }
02036         } func;
02037         getSelection()->applyToRootObjects(&func);
02038 }
02039 
02040 void LLSelectMgr::selectionRotateAroundZ(F32 degrees)
02041 {
02042         LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) );
02043         struct f : public LLSelectedObjectFunctor
02044         {
02045                 LLQuaternion mRot;
02046                 f(const LLQuaternion& rot) : mRot(rot) {}
02047                 virtual bool apply(LLViewerObject* object)
02048                 {
02049                         object->setRotation( object->getRotationEdit() * mRot );
02050                         if (object->mDrawable.notNull())
02051                         {
02052                                 gPipeline.markMoved(object->mDrawable, TRUE);
02053                         }
02054                         object->sendRotationUpdate();
02055                         return true;
02056                 }
02057         } func(rot);
02058         getSelection()->applyToRootObjects(&func);      
02059 }
02060 
02061 
02062 //-----------------------------------------------------------------------------
02063 // selectionTexScaleAutofit()
02064 //-----------------------------------------------------------------------------
02065 void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter)
02066 {
02067         struct f : public LLSelectedTEFunctor
02068         {
02069                 F32 mRepeatsPerMeter;
02070                 f(const F32& t) : mRepeatsPerMeter(t) {}
02071                 bool apply(LLViewerObject* object, S32 te)
02072                 {
02073                         
02074                         if (object->permModify())
02075                         {
02076                                 // Compute S,T to axis mapping
02077                                 U32 s_axis, t_axis;
02078                                 if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis))
02079                                 {
02080                                         return TRUE;
02081                                 }
02082 
02083                                 F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter;
02084                                 F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter;
02085 
02086                                 object->setTEScale(te, new_s, new_t);
02087                         }
02088                         return true;
02089                 }
02090         } setfunc(repeats_per_meter);
02091         getSelection()->applyToTEs(&setfunc);
02092 
02093         LLSelectMgrSendFunctor sendfunc;
02094         getSelection()->applyToObjects(&sendfunc);
02095 }
02096 
02097 
02098 
02099 // Called at the end of a scale operation, this adjusts the textures to attempt to
02100 // maintain a constant repeats per meter.
02101 // BUG: Only works for flex boxes.
02102 //-----------------------------------------------------------------------------
02103 // adjustTexturesByScale()
02104 //-----------------------------------------------------------------------------
02105 void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch)
02106 {
02107         for (LLObjectSelection::iterator iter = getSelection()->begin();
02108                  iter != getSelection()->end(); iter++)
02109         {
02110                 LLSelectNode* selectNode = *iter;
02111                 LLViewerObject* object = selectNode->getObject();
02112 
02113                 if (!object)
02114                 {
02115                         continue;
02116                 }
02117                 
02118                 if (!object->permModify())
02119                 {
02120                         continue;
02121                 }
02122 
02123                 if (object->getNumTEs() == 0)
02124                 {
02125                         continue;
02126                 }
02127 
02128                 BOOL send = FALSE;
02129                 
02130                 for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++)
02131                 {
02132                         const LLTextureEntry* tep = object->getTE(te_num);
02133 
02134                         BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR;
02135                         if (planar == stretch)
02136                         {
02137                                 // Figure out how S,T changed with scale operation
02138                                 U32 s_axis, t_axis;
02139                                 if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis))
02140                                 {
02141                                         continue;
02142                                 }
02143                                 
02144                                 LLVector3 scale_ratio = selectNode->mTextureScaleRatios[te_num]; 
02145                                 LLVector3 object_scale = object->getScale();
02146                                 
02147                                 // Apply new scale to face
02148                                 if (planar)
02149                                 {
02150                                         object->setTEScale(te_num, 1.f/object_scale.mV[s_axis]*scale_ratio.mV[s_axis],
02151                                                                                 1.f/object_scale.mV[t_axis]*scale_ratio.mV[t_axis]);
02152                                 }
02153                                 else
02154                                 {
02155                                         object->setTEScale(te_num, scale_ratio.mV[s_axis]*object_scale.mV[s_axis],
02156                                                                                         scale_ratio.mV[t_axis]*object_scale.mV[t_axis]);
02157                                 }
02158                                 send = send_to_sim;
02159                         }
02160                 }
02161 
02162                 if (send)
02163                 {
02164                         object->sendTEUpdate();
02165                 }
02166         }               
02167 }
02168 
02169 //-----------------------------------------------------------------------------
02170 // selectGetAllRootsValid()
02171 // Returns TRUE if the viewer has information on all selected objects
02172 //-----------------------------------------------------------------------------
02173 BOOL LLSelectMgr::selectGetAllRootsValid()
02174 {
02175         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02176                  iter != getSelection()->root_end(); ++iter )
02177         {
02178                 LLSelectNode* node = *iter;
02179                 if( !node->mValid )
02180                 {
02181                         return FALSE;
02182                 }
02183         }
02184         return TRUE;
02185 }
02186 
02187 
02188 //-----------------------------------------------------------------------------
02189 // selectGetAllValid()
02190 // Returns TRUE if the viewer has information on all selected objects
02191 //-----------------------------------------------------------------------------
02192 BOOL LLSelectMgr::selectGetAllValid()
02193 {
02194         for (LLObjectSelection::iterator iter = getSelection()->begin();
02195                  iter != getSelection()->end(); ++iter )
02196         {
02197                 LLSelectNode* node = *iter;
02198                 if( !node->mValid )
02199                 {
02200                         return FALSE;
02201                 }
02202         }
02203         return TRUE;
02204 }
02205 
02206 
02207 //-----------------------------------------------------------------------------
02208 // selectGetModify() - return TRUE if current agent can modify all
02209 // selected objects.
02210 //-----------------------------------------------------------------------------
02211 BOOL LLSelectMgr::selectGetModify()
02212 {
02213         for (LLObjectSelection::iterator iter = getSelection()->begin();
02214                  iter != getSelection()->end(); iter++ )
02215         {
02216                 LLSelectNode* node = *iter;
02217                 LLViewerObject* object = node->getObject();
02218                 if( !object || !node->mValid )
02219                 {
02220                         return FALSE;
02221                 }
02222                 if( !object->permModify() )
02223                 {
02224                         return FALSE;
02225                 }
02226         }
02227         return TRUE;
02228 }
02229 
02230 //-----------------------------------------------------------------------------
02231 // selectGetRootsModify() - return TRUE if current agent can modify all
02232 // selected root objects.
02233 //-----------------------------------------------------------------------------
02234 BOOL LLSelectMgr::selectGetRootsModify()
02235 {
02236         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02237                  iter != getSelection()->root_end(); iter++ )
02238         {
02239                 LLSelectNode* node = *iter;
02240                 LLViewerObject* object = node->getObject();
02241                 if( !node->mValid )
02242                 {
02243                         return FALSE;
02244                 }
02245                 if( !object->permModify() )
02246                 {
02247                         return FALSE;
02248                 }
02249         }
02250 
02251         return TRUE;
02252 }
02253 
02254 
02255 //-----------------------------------------------------------------------------
02256 // selectGetRootsTransfer() - return TRUE if current agent can transfer all
02257 // selected root objects.
02258 //-----------------------------------------------------------------------------
02259 BOOL LLSelectMgr::selectGetRootsTransfer()
02260 {
02261         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02262                  iter != getSelection()->root_end(); iter++ )
02263         {
02264                 LLSelectNode* node = *iter;
02265                 LLViewerObject* object = node->getObject();
02266                 if( !node->mValid )
02267                 {
02268                         return FALSE;
02269                 }
02270                 if(!object->permTransfer())
02271                 {
02272                         return FALSE;
02273                 }
02274         }
02275         return TRUE;
02276 }
02277 
02278 //-----------------------------------------------------------------------------
02279 // selectGetRootsCopy() - return TRUE if current agent can copy all
02280 // selected root objects.
02281 //-----------------------------------------------------------------------------
02282 BOOL LLSelectMgr::selectGetRootsCopy()
02283 {
02284         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02285                  iter != getSelection()->root_end(); iter++ )
02286         {
02287                 LLSelectNode* node = *iter;
02288                 LLViewerObject* object = node->getObject();
02289                 if( !node->mValid )
02290                 {
02291                         return FALSE;
02292                 }
02293                 if(!object->permCopy())
02294                 {
02295                         return FALSE;
02296                 }
02297         }
02298         return TRUE;
02299 }
02300 
02301 //-----------------------------------------------------------------------------
02302 // selectGetCreator()
02303 // Creator information only applies to root objects.
02304 //-----------------------------------------------------------------------------
02305 BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, LLString& name)
02306 {
02307         BOOL identical = TRUE;
02308         BOOL first = TRUE;
02309         LLUUID first_id;
02310         for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
02311                  iter != getSelection()->root_object_end(); iter++ )
02312         {
02313                 LLSelectNode* node = *iter;     
02314                 if (!node->mValid)
02315                 {
02316                         return FALSE;
02317                 }
02318 
02319                 if (first)
02320                 {
02321                         first_id = node->mPermissions->getCreator();
02322                         first = FALSE;
02323                 }
02324                 else
02325                 {
02326                         if ( !(first_id == node->mPermissions->getCreator() ) )
02327                         {
02328                                 identical = FALSE;
02329                                 break;
02330                         }
02331                 }
02332         }
02333         if (first_id.isNull())
02334         {
02335                 return FALSE;
02336         }
02337         
02338         result_id = first_id;
02339         
02340         if (identical)
02341         {
02342                 gCacheName->getFullName(first_id, name);
02343         }
02344         else
02345         {
02346                 name.assign( "(multiple)" );
02347         }
02348 
02349         return identical;
02350 }
02351 
02352 
02353 //-----------------------------------------------------------------------------
02354 // selectGetOwner()
02355 // Owner information only applies to roots.
02356 //-----------------------------------------------------------------------------
02357 BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, LLString& name)
02358 {
02359         BOOL identical = TRUE;
02360         BOOL first = TRUE;
02361         BOOL first_group_owned = FALSE;
02362         LLUUID first_id;
02363         for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
02364                  iter != getSelection()->root_object_end(); iter++ )
02365         {
02366                 LLSelectNode* node = *iter;     
02367                 if (!node->mValid)
02368                 {
02369                         return FALSE;
02370                 }
02371                 
02372                 if (first)
02373                 {
02374                         node->mPermissions->getOwnership(first_id, first_group_owned);
02375                         first = FALSE;
02376                 }
02377                 else
02378                 {
02379                         LLUUID owner_id;
02380                         BOOL is_group_owned = FALSE;
02381                         if (!(node->mPermissions->getOwnership(owner_id, is_group_owned))
02382                                 || owner_id != first_id || is_group_owned != first_group_owned)
02383                         {
02384                                 identical = FALSE;
02385                                 break;
02386                         }
02387                 }
02388         }
02389         if (first_id.isNull())
02390         {
02391                 return FALSE;
02392         }
02393 
02394         result_id = first_id;
02395         
02396         if (identical)
02397         {
02398                 BOOL public_owner = (first_id.isNull() && !first_group_owned);
02399                 if (first_group_owned)
02400                 {
02401                         name.assign( "(Group Owned)");
02402                 }
02403                 else if(!public_owner)
02404                 {
02405                         gCacheName->getFullName(first_id, name);
02406                 }
02407                 else
02408                 {
02409                         name.assign("Public");
02410                 }
02411         }
02412         else
02413         {
02414                 name.assign( "(multiple)" );
02415         }
02416 
02417         return identical;
02418 }
02419 
02420 
02421 //-----------------------------------------------------------------------------
02422 // selectGetLastOwner()
02423 // Owner information only applies to roots.
02424 //-----------------------------------------------------------------------------
02425 BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, LLString& name)
02426 {
02427         BOOL identical = TRUE;
02428         BOOL first = TRUE;
02429         LLUUID first_id;
02430         for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
02431                  iter != getSelection()->root_object_end(); iter++ )
02432         {
02433                 LLSelectNode* node = *iter;     
02434                 if (!node->mValid)
02435                 {
02436                         return FALSE;
02437                 }
02438 
02439                 if (first)
02440                 {
02441                         first_id = node->mPermissions->getLastOwner();
02442                         first = FALSE;
02443                 }
02444                 else
02445                 {
02446                         if ( !(first_id == node->mPermissions->getLastOwner() ) )
02447                         {
02448                                 identical = FALSE;
02449                                 break;
02450                         }
02451                 }
02452         }
02453         if (first_id.isNull())
02454         {
02455                 return FALSE;
02456         }
02457 
02458         result_id = first_id;
02459         
02460         if (identical)
02461         {
02462                 BOOL public_owner = (first_id.isNull());
02463                 if(!public_owner)
02464                 {
02465                         gCacheName->getFullName(first_id, name);
02466                 }
02467                 else
02468                 {
02469                         name.assign("Public or Group");
02470                 }
02471         }
02472         else
02473         {
02474                 name.assign( "" );
02475         }
02476 
02477         return identical;
02478 }
02479 
02480 
02481 //-----------------------------------------------------------------------------
02482 // selectGetGroup()
02483 // Group information only applies to roots.
02484 //-----------------------------------------------------------------------------
02485 BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id)
02486 {
02487         BOOL identical = TRUE;
02488         BOOL first = TRUE;
02489         LLUUID first_id;
02490         for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
02491                  iter != getSelection()->root_object_end(); iter++ )
02492         {
02493                 LLSelectNode* node = *iter;     
02494                 if (!node->mValid)
02495                 {
02496                         return FALSE;
02497                 }
02498 
02499                 if (first)
02500                 {
02501                         first_id = node->mPermissions->getGroup();
02502                         first = FALSE;
02503                 }
02504                 else
02505                 {
02506                         if ( !(first_id == node->mPermissions->getGroup() ) )
02507                         {
02508                                 identical = FALSE;
02509                                 break;
02510                         }
02511                 }
02512         }
02513 
02514         result_id = first_id;
02515 
02516         return identical;
02517 }
02518 
02519 //-----------------------------------------------------------------------------
02520 // selectIsGroupOwned()
02521 // Only operates on root nodes.  
02522 // Returns TRUE if all have valid data and they are all group owned.
02523 //-----------------------------------------------------------------------------
02524 BOOL LLSelectMgr::selectIsGroupOwned()
02525 {
02526         BOOL found_one = FALSE;
02527         for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin();
02528                  iter != getSelection()->root_object_end(); iter++ )
02529         {
02530                 LLSelectNode* node = *iter;     
02531                 if (!node->mValid)
02532                 {
02533                         return FALSE;
02534                 }
02535                 found_one = TRUE;
02536                 if (!node->mPermissions->isGroupOwned())
02537                 {
02538                         return FALSE;
02539                 }
02540         }       
02541         return found_one ? TRUE : FALSE;
02542 }
02543 
02544 //-----------------------------------------------------------------------------
02545 // selectGetPerm()
02546 // Only operates on root nodes.
02547 // Returns TRUE if all have valid data.
02548 // mask_on has bits set to TRUE where all permissions are TRUE
02549 // mask_off has bits set to TRUE where all permissions are FALSE
02550 // if a bit is off both in mask_on and mask_off, the values differ within
02551 // the selection.
02552 //-----------------------------------------------------------------------------
02553 BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
02554 {
02555         U32 mask;
02556         U32 mask_and    = 0xffffffff;
02557         U32 mask_or             = 0x00000000;
02558         BOOL all_valid  = FALSE;
02559 
02560         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02561                  iter != getSelection()->root_end(); iter++)
02562         {
02563                 LLSelectNode* node = *iter;
02564 
02565                 if (!node->mValid)
02566                 {
02567                         all_valid = FALSE;
02568                         break;
02569                 }
02570 
02571                 all_valid = TRUE;
02572                 
02573                 switch( which_perm )
02574                 {
02575                 case PERM_BASE:
02576                         mask = node->mPermissions->getMaskBase();
02577                         break;
02578                 case PERM_OWNER:
02579                         mask = node->mPermissions->getMaskOwner();
02580                         break;
02581                 case PERM_GROUP:
02582                         mask = node->mPermissions->getMaskGroup();
02583                         break;
02584                 case PERM_EVERYONE:
02585                         mask = node->mPermissions->getMaskEveryone();
02586                         break;
02587                 case PERM_NEXT_OWNER:
02588                         mask = node->mPermissions->getMaskNextOwner();
02589                         break;
02590                 default:
02591                         mask = 0x0;
02592                         break;
02593                 }
02594                 mask_and &= mask;
02595                 mask_or  |= mask;
02596         }
02597 
02598         if (all_valid)
02599         {
02600                 // ...TRUE through all ANDs means all TRUE
02601                 *mask_on  = mask_and;
02602 
02603                 // ...FALSE through all ORs means all FALSE
02604                 *mask_off = ~mask_or;
02605                 return TRUE;
02606         }
02607         else
02608         {
02609                 *mask_on  = 0;
02610                 *mask_off = 0;
02611                 return FALSE;
02612         }
02613 }
02614 
02615 
02616 
02617 BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost)
02618 {
02619         return mSelectedObjects->getOwnershipCost(*out_cost);
02620 }
02621 
02622 BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm)
02623 {
02624         BOOL first = TRUE;
02625         LLPermissions perm;
02626         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02627                  iter != getSelection()->root_end(); iter++ )
02628         {
02629                 LLSelectNode* node = *iter;     
02630                 if (!node->mValid)
02631                 {
02632                         return FALSE;
02633                 }
02634 
02635                 if (first)
02636                 {
02637                         perm = *(node->mPermissions);
02638                         first = FALSE;
02639                 }
02640                 else
02641                 {
02642                         perm.accumulate(*(node->mPermissions));
02643                 }
02644         }
02645 
02646         result_perm = perm;
02647 
02648         return TRUE;
02649 }
02650 
02651 
02652 void LLSelectMgr::selectDelete()
02653 {
02654         S32 deleteable_count = 0;
02655 
02656         BOOL locked_but_deleteable_object = FALSE;
02657         BOOL no_copy_but_deleteable_object = FALSE;
02658         BOOL all_owned_by_you = TRUE;
02659 
02660         for (LLObjectSelection::iterator iter = getSelection()->begin();
02661                  iter != getSelection()->end(); iter++)
02662         {
02663                 LLViewerObject* obj = (*iter)->getObject();
02664 
02665                 if( obj->isAttachment() )
02666                 {
02667                         continue;
02668                 }
02669 
02670                 deleteable_count++;
02671 
02672                 // Check to see if you can delete objects which are locked.
02673                 if(!obj->permMove())
02674                 {
02675                         locked_but_deleteable_object = TRUE;
02676                 }
02677                 if(!obj->permCopy())
02678                 {
02679                         no_copy_but_deleteable_object = TRUE;
02680                 }
02681                 if(!obj->permYouOwner())
02682                 {
02683                         all_owned_by_you = FALSE;
02684                 }
02685         }
02686 
02687         if( 0 == deleteable_count )
02688         {
02689                 make_ui_sound("UISndInvalidOp");
02690                 return;
02691         }
02692 
02693         LLObjectSelectionHandle* selection_handlep = new LLObjectSelectionHandle(getSelection());
02694 
02695         if(locked_but_deleteable_object ||
02696            no_copy_but_deleteable_object ||
02697            !all_owned_by_you)
02698         {
02699                 // convert any transient pie-menu selections to full selection so this operation
02700                 // has some context
02701                 // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode
02702                 // but this is ok, if not ideal
02703                 convertTransient();
02704 
02705                 //This is messy, but needed to get all english our of the UI.
02706                 if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you)
02707                 {
02708                         //Locked only
02709                         gViewerWindow->alertXml(  "ConfirmObjectDeleteLock",
02710                                                                   &LLSelectMgr::confirmDelete,
02711                                                                   selection_handlep);
02712                 }
02713                 else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
02714                 {
02715                         //No Copy only
02716                         gViewerWindow->alertXml(  "ConfirmObjectDeleteNoCopy",
02717                                                                   &LLSelectMgr::confirmDelete,
02718                                                                   selection_handlep);
02719                 }
02720                 else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
02721                 {
02722                         //not owned only
02723                         gViewerWindow->alertXml(  "ConfirmObjectDeleteNoOwn",
02724                                                                   &LLSelectMgr::confirmDelete,
02725                                                                   selection_handlep);
02726                 }
02727                 else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
02728                 {
02729                         //locked and no copy
02730                         gViewerWindow->alertXml(  "ConfirmObjectDeleteLockNoCopy",
02731                                                                   &LLSelectMgr::confirmDelete,
02732                                                                   selection_handlep);
02733                 }
02734                 else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
02735                 {
02736                         //locked and not owned
02737                         gViewerWindow->alertXml(  "ConfirmObjectDeleteLockNoOwn",
02738                                                                   &LLSelectMgr::confirmDelete,
02739                                                                   selection_handlep);
02740                 }
02741                 else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you)
02742                 {
02743                         //no copy and not owned
02744                         gViewerWindow->alertXml(  "ConfirmObjectDeleteNoCopyNoOwn",
02745                                                                   &LLSelectMgr::confirmDelete,
02746                                                                   selection_handlep);
02747                 }
02748                 else
02749                 {
02750                         //locked, no copy and not owned
02751                         gViewerWindow->alertXml(  "ConfirmObjectDeleteLockNoCopyNoOwn",
02752                                                                   &LLSelectMgr::confirmDelete,
02753                                                                   selection_handlep);
02754                 }
02755                 
02756                 
02757                 
02758         }
02759         else
02760         {
02761                 confirmDelete(0, (void*)selection_handlep);
02762         }
02763 }
02764 
02765 // static
02766 void LLSelectMgr::confirmDelete(S32 option, void* data)
02767 {
02768         LLObjectSelectionHandle handle = *(LLObjectSelectionHandle*)data;
02769         delete (LLObjectSelectionHandle*)data;
02770 
02771         if (!handle->getObjectCount())
02772         {
02773                 llwarns << "Nothing to delete!" << llendl;
02774                 return;
02775         }
02776 
02777         switch(option)
02778         {
02779         case 0:
02780                 {
02781                         // TODO: Make sure you have delete permissions on all of them.
02782                         LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
02783                         // attempt to derez into the trash.
02784                         LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id);
02785                         LLSelectMgr::getInstance()->sendListToRegions("DeRezObject",
02786                                                                                   packDeRezHeader,
02787                                                                                   packObjectLocalID,
02788                                                                                   (void*)info,
02789                                                                                   SEND_ONLY_ROOTS);
02790                         // VEFFECT: Delete Object - one effect for all deletes
02791                         if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD)
02792                         {
02793                                 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
02794                                 effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() );
02795                                 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
02796                                 F32 duration = 0.5f;
02797                                 duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f;
02798                                 effectp->setDuration(duration);
02799                         }
02800 
02801                         gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
02802 
02803                         // Keep track of how many objects have been deleted.
02804                         F64 obj_delete_count = LLViewerStats::getInstance()->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT);
02805                         obj_delete_count += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount();
02806                         LLViewerStats::getInstance()->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count );
02807                 }
02808                 break;
02809         case 1:
02810         default:
02811                 break;
02812         }
02813 }
02814 
02815 
02816 void LLSelectMgr::selectForceDelete()
02817 {
02818         sendListToRegions(
02819                 "ObjectDelete",
02820                 packDeleteHeader,
02821                 packObjectLocalID,
02822                 (void*)TRUE,
02823                 SEND_ONLY_ROOTS);
02824 }
02825 
02826 
02827 // returns TRUE if anything is for sale. calculates the total price
02828 // and stores that value in price.
02829 BOOL LLSelectMgr::selectIsForSale(S32& price)
02830 {
02831         BOOL any_for_sale = FALSE;
02832         price = 0;
02833 
02834         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02835                  iter != getSelection()->root_end(); iter++)
02836         {
02837                 LLSelectNode* node = *iter;
02838                 if (node->mSaleInfo.isForSale())
02839                 {
02840                         price += node->mSaleInfo.getSalePrice();
02841                         any_for_sale = TRUE;
02842                 }
02843         }
02844 
02845         return any_for_sale;
02846 
02847 }
02848 
02849 // returns TRUE if all nodes are valid. method also stores an
02850 // accumulated sale info.
02851 BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info)
02852 {
02853         BOOL first = TRUE;
02854         LLSaleInfo sale_info;
02855         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02856                  iter != getSelection()->root_end(); iter++ )
02857         {
02858                 LLSelectNode* node = *iter;     
02859                 if (!node->mValid)
02860                 {
02861                         return FALSE;
02862                 }
02863 
02864                 if (first)
02865                 {
02866                         sale_info = node->mSaleInfo;
02867                         first = FALSE;
02868                 }
02869                 else
02870                 {
02871                         sale_info.accumulate(node->mSaleInfo);
02872                 }
02873         }
02874 
02875         result_sale_info = sale_info;
02876 
02877         return TRUE;
02878 }
02879 
02880 BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm)
02881 {
02882         BOOL first = TRUE;
02883         LLAggregatePermissions perm;
02884         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02885                  iter != getSelection()->root_end(); iter++ )
02886         {
02887                 LLSelectNode* node = *iter;     
02888                 if (!node->mValid)
02889                 {
02890                         return FALSE;
02891                 }
02892 
02893                 if (first)
02894                 {
02895                         perm = node->mAggregatePerm;
02896                         first = FALSE;
02897                 }
02898                 else
02899                 {
02900                         perm.aggregate(node->mAggregatePerm);
02901                 }
02902         }
02903 
02904         result_perm = perm;
02905 
02906         return TRUE;
02907 }
02908 
02909 BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& result_perm)
02910 {
02911         BOOL first = TRUE;
02912         LLAggregatePermissions perm;
02913         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02914                  iter != getSelection()->root_end(); iter++ )
02915         {
02916                 LLSelectNode* node = *iter;     
02917                 if (!node->mValid)
02918                 {
02919                         return FALSE;
02920                 }
02921 
02922                 LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm;
02923                 if (first)
02924                 {
02925                         perm = t_perm;
02926                         first = FALSE;
02927                 }
02928                 else
02929                 {
02930                         perm.aggregate(t_perm);
02931                 }
02932         }
02933 
02934         result_perm = perm;
02935 
02936         return TRUE;
02937 }
02938 
02939 
02940 //--------------------------------------------------------------------
02941 // Duplicate objects
02942 //--------------------------------------------------------------------
02943 
02944 // JC - If this doesn't work right, duplicate the selection list
02945 // before doing anything, do a deselect, then send the duplicate
02946 // messages.
02947 struct LLDuplicateData
02948 {
02949         LLVector3       offset;
02950         U32                     flags;
02951 };
02952 
02953 void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
02954 {
02955         if (mSelectedObjects->isAttachment())
02956         {
02957                 //RN: do not duplicate attachments
02958                 make_ui_sound("UISndInvalidOp");
02959                 return;
02960         }
02961         LLDuplicateData data;
02962 
02963         data.offset = offset;
02964         data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0);
02965 
02966         sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS);
02967 
02968         if (select_copy)
02969         {
02970                 // the new copy will be coming in selected
02971                 deselectAll();
02972         }
02973         else
02974         {
02975                 for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02976                          iter != getSelection()->root_end(); iter++ )
02977                 {
02978                         LLSelectNode* node = *iter;
02979                         node->mDuplicated = TRUE;
02980                         node->mDuplicatePos = node->getObject()->getPositionGlobal();
02981                         node->mDuplicateRot = node->getObject()->getRotation();
02982                 }
02983         }
02984 }
02985 
02986 void LLSelectMgr::repeatDuplicate()
02987 {
02988         if (mSelectedObjects->isAttachment())
02989         {
02990                 //RN: do not duplicate attachments
02991                 make_ui_sound("UISndInvalidOp");
02992                 return;
02993         }
02994 
02995         std::vector<LLViewerObject*> non_duplicated_objects;
02996 
02997         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
02998                  iter != getSelection()->root_end(); iter++ )
02999         {
03000                 LLSelectNode* node = *iter;     
03001                 if (!node->mDuplicated)
03002                 {
03003                         non_duplicated_objects.push_back(node->getObject());
03004                 }
03005         }
03006 
03007         // make sure only previously duplicated objects are selected
03008         for (std::vector<LLViewerObject*>::iterator iter = non_duplicated_objects.begin();
03009                  iter != non_duplicated_objects.end(); ++iter)
03010         {
03011                 LLViewerObject* objectp = *iter;
03012                 deselectObjectAndFamily(objectp);
03013         }
03014         
03015         // duplicate objects in place
03016         LLDuplicateData data;
03017 
03018         data.offset = LLVector3::zero;
03019         data.flags = 0x0;
03020 
03021         sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS);
03022 
03023         // move current selection based on delta from duplication position and update duplication position
03024         for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
03025                  iter != getSelection()->root_end(); iter++ )
03026         {
03027                 LLSelectNode* node = *iter;     
03028                 if (node->mDuplicated)
03029                 {
03030                         LLQuaternion cur_rot = node->getObject()->getRotation();
03031                         LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot);
03032                         LLQuaternion new_rot = cur_rot * rot_delta;
03033                         LLVector3d cur_pos = node->getObject()->getPositionGlobal();
03034                         LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta);
03035 
03036                         node->mDuplicatePos = node->getObject()->getPositionGlobal();
03037                         node->mDuplicateRot = node->getObject()->getRotation();
03038                         node->getObject()->setPositionGlobal(new_pos);
03039                         node->getObject()->setRotation(new_rot);
03040                 }
03041         }
03042 
03043         sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
03044 }
03045 
03046 // static 
03047 void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data )
03048 {
03049         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03050         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID());
03051 }
03052 
03053 
03054 //--------------------------------------------------------------------
03055 // Duplicate On Ray
03056 //--------------------------------------------------------------------
03057 
03058 // Duplicates the selected objects, but places the copy along a cast
03059 // ray.
03060 struct LLDuplicateOnRayData
03061 {
03062         LLVector3       mRayStartRegion;
03063         LLVector3       mRayEndRegion;
03064         BOOL            mBypassRaycast;
03065         BOOL            mRayEndIsIntersection;
03066         LLUUID          mRayTargetID;
03067         BOOL            mCopyCenters;
03068         BOOL            mCopyRotates;
03069         U32                     mFlags;
03070 };
03071 
03072 void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region,
03073                                                                            const LLVector3 &ray_end_region,
03074                                                                            BOOL bypass_raycast,
03075                                                                            BOOL ray_end_is_intersection,
03076                                                                            const LLUUID &ray_target_id,
03077                                                                            BOOL copy_centers,
03078                                                                            BOOL copy_rotates,
03079                                                                            BOOL select_copy)
03080 {
03081         if (mSelectedObjects->isAttachment())
03082         {
03083                 // do not duplicate attachments
03084                 make_ui_sound("UISndInvalidOp");
03085                 return;
03086         }
03087         
03088         LLDuplicateOnRayData    data;
03089 
03090         data.mRayStartRegion    = ray_start_region;
03091         data.mRayEndRegion              = ray_end_region;
03092         data.mBypassRaycast             = bypass_raycast;
03093         data.mRayEndIsIntersection = ray_end_is_intersection;
03094         data.mRayTargetID               = ray_target_id;
03095         data.mCopyCenters               = copy_centers;
03096         data.mCopyRotates               = copy_rotates;
03097         data.mFlags                             = (select_copy ? FLAGS_CREATE_SELECTED : 0x0);
03098 
03099         sendListToRegions("ObjectDuplicateOnRay", 
03100                 packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS);
03101 
03102         if (select_copy)
03103         {
03104                 // the new copy will be coming in selected
03105                 deselectAll();
03106         }
03107 }
03108 
03109 // static
03110 void LLSelectMgr::packDuplicateOnRayHead(void *user_data)
03111 {
03112         LLMessageSystem *msg = gMessageSystem;
03113         LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data;
03114 
03115         msg->nextBlockFast(_PREHASH_AgentData);
03116         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03117         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
03118         msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
03119         msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion );
03120         msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion );
03121         msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast );
03122         msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection );
03123         msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters );
03124         msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates );
03125         msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID );
03126         msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags );
03127 }
03128 
03129 
03130 
03131 //------------------------------------------------------------------------
03132 // Object position, scale, rotation update, all-in-one
03133 //------------------------------------------------------------------------
03134 
03135 void LLSelectMgr::sendMultipleUpdate(U32 type)
03136 {
03137         if (type == UPD_NONE) return;
03138         // send individual updates when selecting textures or individual objects
03139         ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST;
03140         if (send_type == SEND_ONLY_ROOTS)
03141         {
03142                 // tell simulator to apply to whole linked sets
03143                 type |= UPD_LINKED_SETS;
03144         }
03145 
03146         sendListToRegions(
03147                 "MultipleObjectUpdate",
03148                 packAgentAndSessionID,
03149                 packMultipleUpdate,
03150                 &type,
03151                 send_type);
03152 }
03153 
03154 // static
03155 void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data)
03156 {
03157         LLViewerObject* object = node->getObject();
03158         U32     *type32 = (U32 *)user_data;
03159         U8 type = (U8)*type32;
03160         U8      data[256];
03161 
03162         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03163         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID,      object->getLocalID() );
03164         gMessageSystem->addU8Fast(_PREHASH_Type, type );
03165 
03166         S32 offset = 0;
03167 
03168         // JC: You MUST pack the data in this order.  The receiving
03169         // routine process_multiple_update_message on simulator will
03170         // extract them in this order.
03171 
03172         if (type & UPD_POSITION)
03173         {
03174                 htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); 
03175                 offset += 12;
03176         }
03177         if (type & UPD_ROTATION)
03178         {
03179                 LLQuaternion quat = object->getRotation();
03180                 LLVector3 vec = quat.packToVector3();
03181                 htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); 
03182                 offset += 12;
03183         }
03184         if (type & UPD_SCALE)
03185         {
03186                 //llinfos << "Sending object scale " << object->getScale() << llendl;
03187                 htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); 
03188                 offset += 12;
03189         }
03190         gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);
03191 }
03192 
03193 //------------------------------------------------------------------------
03194 // Ownership
03195 //------------------------------------------------------------------------
03196 struct LLOwnerData
03197 {
03198         LLUUID  owner_id;
03199         LLUUID  group_id;
03200         BOOL    override;
03201 };
03202 
03203 void LLSelectMgr::sendOwner(const LLUUID& owner_id,
03204                                                         const LLUUID& group_id,
03205                                                         BOOL override)
03206 {
03207         LLOwnerData data;
03208 
03209         data.owner_id = owner_id;
03210         data.group_id = group_id;
03211         data.override = override;
03212 
03213         sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS);
03214 }
03215 
03216 // static
03217 void LLSelectMgr::packOwnerHead(void *user_data)
03218 {
03219         LLOwnerData *data = (LLOwnerData *)user_data;
03220 
03221         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03222         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03223         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
03224         gMessageSystem->nextBlockFast(_PREHASH_HeaderData);
03225         gMessageSystem->addBOOLFast(_PREHASH_Override, data->override);
03226         gMessageSystem->addUUIDFast(_PREHASH_OwnerID, data->owner_id);
03227         gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id);
03228 }
03229 
03230 //------------------------------------------------------------------------
03231 // Group
03232 //------------------------------------------------------------------------
03233 
03234 void LLSelectMgr::sendGroup(const LLUUID& group_id)
03235 {
03236         LLUUID local_group_id(group_id);
03237         sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS);
03238 }
03239 
03240 
03241 //------------------------------------------------------------------------
03242 // Buy
03243 //------------------------------------------------------------------------
03244 
03245 struct LLBuyData
03246 {
03247         std::vector<LLViewerObject*> mObjectsSent;
03248         LLUUID mCategoryID;
03249         LLSaleInfo mSaleInfo;
03250 };
03251 
03252 // *NOTE: does not work for multiple object buy, which UI does not
03253 // currently support sale info is used for verification only, if it
03254 // doesn't match region info then sale is canceled Need to get sale
03255 // info -as displayed in the UI- for every item.
03256 void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info)
03257 {
03258         LLBuyData buy;
03259         buy.mCategoryID = category_id;
03260         buy.mSaleInfo = sale_info;
03261         sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS);
03262 }
03263 
03264 // static
03265 void LLSelectMgr::packBuyObjectIDs(LLSelectNode* node, void* data)
03266 {
03267         LLBuyData* buy = (LLBuyData*)data;
03268 
03269         LLViewerObject* object = node->getObject();
03270         if (std::find(buy->mObjectsSent.begin(), buy->mObjectsSent.end(), object) == buy->mObjectsSent.end())
03271         {
03272                 buy->mObjectsSent.push_back(object);
03273                 gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03274                 gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() );
03275                 gMessageSystem->addU8Fast(_PREHASH_SaleType, buy->mSaleInfo.getSaleType());
03276                 gMessageSystem->addS32Fast(_PREHASH_SalePrice, buy->mSaleInfo.getSalePrice());
03277         }
03278 }
03279 
03280 //------------------------------------------------------------------------
03281 // Permissions
03282 //------------------------------------------------------------------------
03283 
03284 struct LLPermData
03285 {
03286         U8 mField;
03287         BOOL mSet;
03288         U32 mMask;
03289         BOOL mOverride;
03290 };
03291 
03292 // TODO: Make this able to fail elegantly.
03293 void LLSelectMgr::selectionSetObjectPermissions(U8 field,
03294                                                                            BOOL set,
03295                                                                            U32 mask,
03296                                                                            BOOL override)
03297 {
03298         LLPermData data;
03299 
03300         data.mField = field;
03301         data.mSet = set;
03302         data.mMask = mask;
03303         data.mOverride = override;
03304 
03305         sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS);
03306 }
03307 
03308 void LLSelectMgr::packPermissionsHead(void* user_data)
03309 {
03310         LLPermData* data = (LLPermData*)user_data;
03311         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03312         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03313         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03314         gMessageSystem->nextBlockFast(_PREHASH_HeaderData);
03315         gMessageSystem->addBOOLFast(_PREHASH_Override, data->mOverride);
03316 }       
03317 
03318 
03319 // Now that you've added a bunch of objects, send a select message
03320 // on the entire list for efficiency.
03321 /*
03322 void LLSelectMgr::sendSelect()
03323 {
03324         llerrs << "Not implemented" << llendl;
03325 }
03326 */
03327 
03328 void LLSelectMgr::deselectAll()
03329 {
03330         if (!mSelectedObjects->getNumNodes())
03331         {
03332                 return;
03333         }
03334 
03335         // Zap the angular velocity, as the sim will set it to zero
03336         for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
03337                  iter != mSelectedObjects->end(); iter++ )
03338         {
03339                 LLViewerObject *objectp = (*iter)->getObject();
03340                 objectp->setAngularVelocity( 0,0,0 );
03341                 objectp->setVelocity( 0,0,0 );
03342         }
03343 
03344         sendListToRegions(
03345                 "ObjectDeselect",
03346                 packAgentAndSessionID,
03347                 packObjectLocalID,
03348                 NULL,
03349                 SEND_INDIVIDUALS);
03350 
03351         removeAll();
03352         
03353         mLastSentSelectionCenterGlobal.clearVec();
03354 
03355         updatePointAt();
03356 }
03357 
03358 void LLSelectMgr::deselectAllForStandingUp()
03359 {
03360         /*
03361         This function is similar deselectAll() except for the first if statement
03362         which was removed. This is needed as a workaround for DEV-2854
03363         */
03364 
03365         // Zap the angular velocity, as the sim will set it to zero
03366         for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
03367                  iter != mSelectedObjects->end(); iter++ )
03368         {
03369                 LLViewerObject *objectp = (*iter)->getObject();
03370                 objectp->setAngularVelocity( 0,0,0 );
03371                 objectp->setVelocity( 0,0,0 );
03372         }
03373 
03374         sendListToRegions(
03375                 "ObjectDeselect",
03376                 packAgentAndSessionID,
03377                 packObjectLocalID,
03378                 NULL,
03379                 SEND_INDIVIDUALS);
03380 
03381         removeAll();
03382         
03383         mLastSentSelectionCenterGlobal.clearVec();
03384 
03385         updatePointAt();
03386 }
03387 
03388 void LLSelectMgr::deselectUnused()
03389 {
03390         // no more outstanding references to this selection
03391         if (mSelectedObjects->getNumRefs() == 1)
03392         {
03393                 deselectAll();
03394         }
03395 }
03396 
03397 void LLSelectMgr::convertTransient()
03398 {
03399         LLObjectSelection::iterator node_it;
03400         for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it)
03401         {
03402                 LLSelectNode *nodep = *node_it;
03403                 nodep->setTransient(FALSE);
03404         }
03405 }
03406 
03407 void LLSelectMgr::deselectAllIfTooFar()
03408 {
03409         if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD)
03410         {
03411                 return;
03412         }
03413 
03414         // HACK: Don't deselect when we're navigating to rate an object's
03415         // owner or creator.  JC
03416         if (gPieObject->getVisible() || gPieRate->getVisible() )
03417         {
03418                 return;
03419         }
03420 
03421         LLVector3d selectionCenter = getSelectionCenterGlobal();
03422         if (gSavedSettings.getBOOL("LimitSelectDistance") 
03423                 && !selectionCenter.isExactlyZero())
03424         {
03425                 F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance");
03426                 F32 deselect_dist_sq = deselect_dist * deselect_dist;
03427 
03428                 LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter;
03429                 F32 select_dist_sq = (F32) select_delta.magVecSquared();
03430 
03431                 if (select_dist_sq > deselect_dist_sq)
03432                 {
03433                         if (gDebugSelectMgr)
03434                         {
03435                                 llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl;
03436                                 llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl;
03437                                 llinfos << "selection pos global = " << selectionCenter << llendl;
03438                         }
03439 
03440                         deselectAll();
03441                 }
03442         }
03443 }
03444 
03445 
03446 void LLSelectMgr::selectionSetObjectName(const LLString& name)
03447 {
03448         // we only work correctly if 1 object is selected.
03449         if(mSelectedObjects->getRootObjectCount() == 1)
03450         {
03451                 sendListToRegions("ObjectName",
03452                                                   packAgentAndSessionID,
03453                                                   packObjectName,
03454                                                   (void*)name.c_str(),
03455                                                   SEND_ONLY_ROOTS);
03456         }
03457         else if(mSelectedObjects->getObjectCount() == 1)
03458         {
03459                 sendListToRegions("ObjectName",
03460                                                   packAgentAndSessionID,
03461                                                   packObjectName,
03462                                                   (void*)name.c_str(),
03463                                                   SEND_INDIVIDUALS);
03464         }
03465 }
03466 
03467 void LLSelectMgr::selectionSetObjectDescription(const LLString& desc)
03468 {
03469         // we only work correctly if 1 object is selected.
03470         if(mSelectedObjects->getRootObjectCount() == 1)
03471         {
03472                 sendListToRegions("ObjectDescription",
03473                                                   packAgentAndSessionID,
03474                                                   packObjectDescription,
03475                                                   (void*)desc.c_str(),
03476                                                   SEND_ONLY_ROOTS);
03477         }
03478         else if(mSelectedObjects->getObjectCount() == 1)
03479         {
03480                 sendListToRegions("ObjectDescription",
03481                                                   packAgentAndSessionID,
03482                                                   packObjectDescription,
03483                                                   (void*)desc.c_str(),
03484                                                   SEND_INDIVIDUALS);
03485         }
03486 }
03487 
03488 void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category)
03489 {
03490         // for now, we only want to be able to set one root category at
03491         // a time.
03492         if(mSelectedObjects->getRootObjectCount() != 1) return;
03493         sendListToRegions("ObjectCategory",
03494                                           packAgentAndSessionID,
03495                                           packObjectCategory,
03496                                           (void*)(&category),
03497                                           SEND_ONLY_ROOTS);
03498 }
03499 
03500 void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
03501 {
03502         // Only one sale info at a time for now
03503         if(mSelectedObjects->getRootObjectCount() != 1) return;
03504         sendListToRegions("ObjectSaleInfo",
03505                                           packAgentAndSessionID,
03506                                           packObjectSaleInfo,
03507                                           (void*)(&sale_info),
03508                                           SEND_ONLY_ROOTS);
03509 }
03510 
03511 //----------------------------------------------------------------------
03512 // Attachments
03513 //----------------------------------------------------------------------
03514 
03515 void LLSelectMgr::sendAttach(U8 attachment_point)
03516 {
03517         LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
03518 
03519         if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
03520         {
03521                 return;
03522         }
03523 
03524         BOOL build_mode = LLToolMgr::getInstance()->inEdit();
03525         // Special case: Attach to default location for this object.
03526         if (0 == attachment_point ||
03527                 get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))
03528         {
03529                 sendListToRegions(
03530                         "ObjectAttach",
03531                         packAgentIDAndSessionAndAttachment, 
03532                         packObjectIDAndRotation, 
03533                         &attachment_point, 
03534                         SEND_ONLY_ROOTS );
03535                 if (!build_mode)
03536                 {
03537                         deselectAll();
03538                 }
03539         }
03540 }
03541 
03542 void LLSelectMgr::sendDetach()
03543 {
03544         if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD)
03545         {
03546                 return;
03547         }
03548 
03549         sendListToRegions(
03550                 "ObjectDetach",
03551                 packAgentAndSessionID,
03552                 packObjectLocalID,
03553                 NULL,
03554                 SEND_ONLY_ROOTS );
03555 }
03556 
03557 
03558 void LLSelectMgr::sendDropAttachment()
03559 {
03560         if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD)
03561         {
03562                 return;
03563         }
03564 
03565         sendListToRegions(
03566                 "ObjectDrop",
03567                 packAgentAndSessionID,
03568                 packObjectLocalID,
03569                 NULL,
03570                 SEND_ONLY_ROOTS);
03571 }
03572 
03573 //----------------------------------------------------------------------
03574 // Links
03575 //----------------------------------------------------------------------
03576 
03577 void LLSelectMgr::sendLink()
03578 {
03579         if (!mSelectedObjects->getNumNodes())
03580         {
03581                 return;
03582         }
03583 
03584         sendListToRegions(
03585                 "ObjectLink",
03586                 packAgentAndSessionID,
03587                 packObjectLocalID,
03588                 NULL,
03589                 SEND_ONLY_ROOTS);
03590 }
03591 
03592 void LLSelectMgr::sendDelink()
03593 {
03594         if (!mSelectedObjects->getNumNodes())
03595         {
03596                 return;
03597         }
03598 
03599         // Delink needs to send individuals so you can unlink a single object from
03600         // a linked set.
03601         sendListToRegions(
03602                 "ObjectDelink",
03603                 packAgentAndSessionID,
03604                 packObjectLocalID,
03605                 NULL,
03606                 SEND_INDIVIDUALS);
03607 }
03608 
03609 
03610 //----------------------------------------------------------------------
03611 // Hinges
03612 //----------------------------------------------------------------------
03613 
03614 /*
03615 void LLSelectMgr::sendHinge(U8 type)
03616 {
03617         if (!mSelectedObjects->getNumNodes())
03618         {
03619                 return;
03620         }
03621 
03622         sendListToRegions(
03623                 "ObjectHinge",
03624                 packHingeHead,
03625                 packObjectLocalID,
03626                 &type,
03627                 SEND_ONLY_ROOTS);
03628 }
03629 
03630 
03631 void LLSelectMgr::sendDehinge()
03632 {
03633         if (!mSelectedObjects->getNumNodes())
03634         {
03635                 return;
03636         }
03637 
03638         sendListToRegions(
03639                 "ObjectDehinge",
03640                 packAgentAndSessionID,
03641                 packObjectLocalID,
03642                 NULL,
03643                 SEND_ONLY_ROOTS);
03644 }*/
03645 
03646 void LLSelectMgr::sendSelect()
03647 {
03648         if (!mSelectedObjects->getNumNodes())
03649         {
03650                 return;
03651         }
03652 
03653         sendListToRegions(
03654                 "ObjectSelect",
03655                 packAgentAndSessionID,
03656                 packObjectLocalID,
03657                 NULL,
03658                 SEND_INDIVIDUALS);
03659 }
03660 
03661 // static
03662 void LLSelectMgr::packHingeHead(void *user_data)
03663 {
03664         U8      *type = (U8 *)user_data;
03665 
03666         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03667         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03668         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
03669         gMessageSystem->nextBlockFast(_PREHASH_JointType);
03670         gMessageSystem->addU8Fast(_PREHASH_Type, *type );
03671 }
03672 
03673 
03674 void LLSelectMgr::selectionDump()
03675 {
03676         struct f : public LLSelectedObjectFunctor
03677         {
03678                 virtual bool apply(LLViewerObject* object)
03679                 {
03680                         object->dump();
03681                         return true;
03682                 }
03683         } func;
03684         getSelection()->applyToObjects(&func);  
03685 }
03686 
03687 void LLSelectMgr::saveSelectedObjectColors()
03688 {
03689         struct f : public LLSelectedNodeFunctor
03690         {
03691                 virtual bool apply(LLSelectNode* node)
03692                 {
03693                         node->saveColors();
03694                         return true;
03695                 }
03696         } func;
03697         getSelection()->applyToNodes(&func);    
03698 }
03699 
03700 void LLSelectMgr::saveSelectedObjectTextures()
03701 {
03702         // invalidate current selection so we update saved textures
03703         struct f : public LLSelectedNodeFunctor
03704         {
03705                 virtual bool apply(LLSelectNode* node)
03706                 {
03707                         node->mValid = FALSE;
03708                         return true;
03709                 }
03710         } func;
03711         getSelection()->applyToNodes(&func);    
03712 
03713         // request object properties message to get updated permissions data
03714         sendSelect();
03715 }
03716 
03717 
03718 // This routine should be called whenever a drag is initiated.
03719 // also need to know to which simulator to send update message
03720 void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type)
03721 {
03722         if (mSelectedObjects->isEmpty())
03723         {
03724                 // nothing selected, so nothing to save
03725                 return;
03726         }
03727 
03728         struct f : public LLSelectedNodeFunctor
03729         {
03730                 EActionType mActionType;
03731                 f(EActionType a) : mActionType(a) {}
03732                 virtual bool apply(LLSelectNode* selectNode)
03733                 {
03734                         LLViewerObject* object = selectNode->getObject();
03735                         if (!object)
03736                         {
03737                                 return true; // skip
03738                         }
03739                         selectNode->mSavedPositionLocal = object->getPosition();
03740                         if (object->isAttachment())
03741                         {
03742                                 if (object->isRootEdit())
03743                                 {
03744                                         LLXform* parent_xform = object->mDrawable->getXform()->getParent();
03745                                         if (parent_xform)
03746                                         {
03747                                                 selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition());
03748                                         }
03749                                         else
03750                                         {
03751                                                 selectNode->mSavedPositionGlobal = object->getPositionGlobal();
03752                                         }
03753                                 }
03754                                 else
03755                                 {
03756                                         LLViewerObject* attachment_root = (LLViewerObject*)object->getParent();
03757                                         LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL;
03758                                         if (parent_xform)
03759                                         {
03760                                                 LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();
03761                                                 LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation());
03762                                                 selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos);
03763                                         }
03764                                         else
03765                                         {
03766                                                 selectNode->mSavedPositionGlobal = object->getPositionGlobal();
03767                                         }
03768                                 }
03769                                 selectNode->mSavedRotation = object->getRenderRotation();
03770                         }
03771                         else
03772                         {
03773                                 selectNode->mSavedPositionGlobal = object->getPositionGlobal();
03774                                 selectNode->mSavedRotation = object->getRotationRegion();
03775                         }
03776                 
03777                         selectNode->mSavedScale = object->getScale();
03778                         selectNode->saveTextureScaleRatios();
03779                         return true;
03780                 }
03781         } func(action_type);
03782         getSelection()->applyToNodes(&func);    
03783         
03784         mSavedSelectionBBox = getBBoxOfSelection();
03785 }
03786 
03787 struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor
03788 {
03789         LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {}
03790         U32 mFlags;
03791         BOOL mState;
03792         virtual bool apply(LLViewerObject* object)
03793         {
03794                 if ( object->permModify() &&    // preemptive permissions check
03795                          object->isRoot() &&            // don't send for child objects
03796                          !object->isJointChild())
03797                 {
03798                         object->setFlags( mFlags, mState);
03799                 }
03800                 return true;
03801         }
03802 };
03803 
03804 void LLSelectMgr::selectionUpdatePhysics(BOOL physics)
03805 {
03806         LLSelectMgrApplyFlags func(     FLAGS_USE_PHYSICS, physics);
03807         getSelection()->applyToObjects(&func);  
03808 }
03809 
03810 void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary)
03811 {
03812         LLSelectMgrApplyFlags func(     FLAGS_TEMPORARY_ON_REZ, is_temporary);
03813         getSelection()->applyToObjects(&func);  
03814 }
03815 
03816 void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom)
03817 {
03818         LLSelectMgrApplyFlags func(     FLAGS_PHANTOM, is_phantom);
03819         getSelection()->applyToObjects(&func);  
03820 }
03821 
03822 void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows)
03823 {
03824         LLSelectMgrApplyFlags func(     FLAGS_CAST_SHADOWS, cast_shadows);
03825         getSelection()->applyToObjects(&func);  
03826 }
03827 
03828 
03829 //----------------------------------------------------------------------
03830 // Helpful packing functions for sendObjectMessage()
03831 //----------------------------------------------------------------------
03832 
03833 // static 
03834 void LLSelectMgr::packAgentIDAndSessionAndAttachment( void *user_data)
03835 {
03836         U8 *attachment_point = (U8*)user_data;
03837         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03838         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03839         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03840         gMessageSystem->addU8Fast(_PREHASH_AttachmentPoint, *attachment_point);
03841 }
03842 
03843 // static
03844 void LLSelectMgr::packAgentID(  void *user_data)
03845 {
03846         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03847         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03848 }
03849 
03850 // static
03851 void LLSelectMgr::packAgentAndSessionID(void* user_data)
03852 {
03853         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03854         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03855         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03856 }
03857 
03858 // static
03859 void LLSelectMgr::packAgentAndGroupID(void* user_data)
03860 {
03861         LLOwnerData *data = (LLOwnerData *)user_data;
03862 
03863         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03864         gMessageSystem->addUUIDFast(_PREHASH_AgentID, data->owner_id );
03865         gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id );
03866 }
03867 
03868 // static
03869 void LLSelectMgr::packAgentAndSessionAndGroupID(void* user_data)
03870 {
03871         LLUUID* group_idp = (LLUUID*) user_data;
03872         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03873         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03874         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03875         gMessageSystem->addUUIDFast(_PREHASH_GroupID, *group_idp);
03876 }
03877 
03878 // static
03879 void LLSelectMgr::packDuplicateHeader(void* data)
03880 {
03881         LLUUID group_id(gAgent.getGroupID());
03882         packAgentAndSessionAndGroupID(&group_id);
03883 
03884         LLDuplicateData* dup_data = (LLDuplicateData*) data;
03885 
03886         gMessageSystem->nextBlockFast(_PREHASH_SharedData);
03887         gMessageSystem->addVector3Fast(_PREHASH_Offset, dup_data->offset);
03888         gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, dup_data->flags);
03889 }
03890 
03891 // static
03892 void LLSelectMgr::packDeleteHeader(void* userdata)
03893 {
03894         BOOL force = (BOOL)(intptr_t)userdata;
03895 
03896         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03897         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03898         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03899         gMessageSystem->addBOOLFast(_PREHASH_Force, force);
03900 }
03901 
03902 // static
03903 void LLSelectMgr::packAgentGroupAndCatID(void* user_data)
03904 {
03905         LLBuyData* buy = (LLBuyData*)user_data;
03906         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03907         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03908         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03909         gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
03910         gMessageSystem->addUUIDFast(_PREHASH_CategoryID, buy->mCategoryID);
03911 }
03912 
03913 //static
03914 void LLSelectMgr::packDeRezHeader(void* user_data)
03915 {
03916         LLDeRezInfo* info = (LLDeRezInfo*)user_data;
03917         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03918         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03919         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03920         gMessageSystem->nextBlockFast(_PREHASH_AgentBlock);
03921         gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
03922         gMessageSystem->addU8Fast(_PREHASH_Destination, (U8)info->mDestination);
03923         gMessageSystem->addUUIDFast(_PREHASH_DestinationID, info->mDestinationID);
03924         LLUUID tid;
03925         tid.generate();
03926         gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid);
03927         const U8 PACKET = 1;
03928         gMessageSystem->addU8Fast(_PREHASH_PacketCount, PACKET);
03929         gMessageSystem->addU8Fast(_PREHASH_PacketNumber, PACKET);
03930 }
03931 
03932 // static 
03933 void LLSelectMgr::packObjectID(LLSelectNode* node, void *user_data)
03934 {
03935         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03936         gMessageSystem->addUUIDFast(_PREHASH_ObjectID, node->getObject()->mID );
03937 }
03938 
03939 void LLSelectMgr::packObjectIDAndRotation(LLSelectNode* node, void *user_data)
03940 {
03941         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03942         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() );
03943         gMessageSystem->addQuatFast(_PREHASH_Rotation, node->getObject()->getRotation());
03944 }
03945 
03946 void LLSelectMgr::packObjectClickAction(LLSelectNode* node, void *user_data)
03947 {
03948         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03949         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() );
03950         gMessageSystem->addU8("ClickAction", node->getObject()->getClickAction());
03951 }
03952 
03953 void LLSelectMgr::packObjectIncludeInSearch(LLSelectNode* node, void *user_data)
03954 {
03955         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03956         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() );
03957         gMessageSystem->addBOOL("IncludeInSearch", node->getObject()->getIncludeInSearch());
03958 }
03959 
03960 // static
03961 void LLSelectMgr::packObjectLocalID(LLSelectNode* node, void *)
03962 {
03963         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03964         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID());
03965 }
03966 
03967 // static
03968 void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data)
03969 {
03970         char* name = (char*)user_data;
03971         if(!name) return;
03972         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03973         gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID());
03974         gMessageSystem->addStringFast(_PREHASH_Name, name);
03975 }
03976 
03977 // static
03978 void LLSelectMgr::packObjectDescription(LLSelectNode* node,
03979                                                                                 void* user_data)
03980 {
03981         char* desc = (char*)user_data;
03982         if(!desc) return;
03983         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03984         gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID());
03985         gMessageSystem->addStringFast(_PREHASH_Description, desc);
03986 }
03987 
03988 // static
03989 void LLSelectMgr::packObjectCategory(LLSelectNode* node, void* user_data)
03990 {
03991         LLCategory* category = (LLCategory*)user_data;
03992         if(!category) return;
03993         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03994         gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID());
03995         category->packMessage(gMessageSystem);
03996 }
03997 
03998 // static
03999 void LLSelectMgr::packObjectSaleInfo(LLSelectNode* node, void* user_data)
04000 {
04001         LLSaleInfo* sale_info = (LLSaleInfo*)user_data;
04002         if(!sale_info) return;
04003         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
04004         gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID());
04005         sale_info->packMessage(gMessageSystem);
04006 }
04007 
04008 // static
04009 void LLSelectMgr::packPhysics(LLSelectNode* node, void *user_data)
04010 {
04011 }
04012 
04013 // static
04014 void LLSelectMgr::packShape(LLSelectNode* node, void *user_data)
04015 {
04016 }
04017 
04018 // static 
04019 void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data)
04020 {
04021         LLPermData *data = (LLPermData *)user_data;
04022 
04023         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
04024         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID());
04025 
04026         gMessageSystem->addU8Fast(_PREHASH_Field,       data->mField);
04027         gMessageSystem->addBOOLFast(_PREHASH_Set,               data->mSet);
04028         gMessageSystem->addU32Fast(_PREHASH_Mask,               data->mMask);
04029 }
04030 
04031 // Utility function to send some information to every region containing
04032 // an object on the selection list.  We want to do this to reduce the total
04033 // number of packets sent by the viewer.
04034 void LLSelectMgr::sendListToRegions(const LLString& message_name,
04035                                                                         void (*pack_header)(void *user_data), 
04036                                                                         void (*pack_body)(LLSelectNode* node, void *user_data), 
04037                                                                         void *user_data,
04038                                                                         ESendType send_type)
04039 {
04040         LLSelectNode* node;
04041         LLViewerRegion* last_region;
04042         LLViewerRegion* current_region;
04043 
04044         S32 objects_sent = 0;
04045         S32 packets_sent = 0;
04046         S32 objects_in_this_packet = 0;
04047 
04048         //clear update override data (allow next update through)
04049         struct f : public LLSelectedNodeFunctor
04050         {
04051                 virtual bool apply(LLSelectNode* node)
04052                 {
04053                         node->mLastPositionLocal.setVec(0,0,0);
04054                         node->mLastRotation = LLQuaternion();
04055                         node->mLastScale.setVec(0,0,0);
04056                         return true;
04057                 }
04058         } func;
04059         getSelection()->applyToNodes(&func);    
04060 
04061         std::queue<LLSelectNode*> nodes_to_send;
04062 
04063         struct push_all : public LLSelectedNodeFunctor
04064         {
04065                 std::queue<LLSelectNode*>& nodes_to_send;
04066                 push_all(std::queue<LLSelectNode*>& n) : nodes_to_send(n) {}
04067                 virtual bool apply(LLSelectNode* node)
04068                 {
04069                         if (node->getObject())
04070                         {
04071                                 nodes_to_send.push(node);
04072                         }
04073                         return true;
04074                 }
04075         };
04076         struct push_some : public LLSelectedNodeFunctor
04077         {
04078                 std::queue<LLSelectNode*>& nodes_to_send;
04079                 bool mRoots;
04080                 push_some(std::queue<LLSelectNode*>& n, bool roots) : nodes_to_send(n), mRoots(roots) {}
04081                 virtual bool apply(LLSelectNode* node)
04082                 {
04083                         if (node->getObject())
04084                         {
04085                                 BOOL is_root = node->getObject()->isRootEdit();
04086                                 if ((mRoots && is_root) || (!mRoots && !is_root))
04087                                 {
04088                                         nodes_to_send.push(node);
04089                                 }
04090                         }
04091                         return true;
04092                 }
04093         };
04094         struct push_all  pushall(nodes_to_send);
04095         struct push_some pushroots(nodes_to_send, TRUE);
04096         struct push_some pushnonroots(nodes_to_send, FALSE);
04097         
04098         switch(send_type)
04099         {
04100           case SEND_ONLY_ROOTS:
04101                   if(message_name == "ObjectBuy")
04102                         getSelection()->applyToRootNodes(&pushroots);
04103                   else
04104                         getSelection()->applyToRootNodes(&pushall);
04105                   
04106                 break;
04107           case SEND_INDIVIDUALS:
04108                 getSelection()->applyToNodes(&pushall);
04109                 break;
04110           case SEND_ROOTS_FIRST:
04111                 // first roots...
04112                 getSelection()->applyToNodes(&pushroots);
04113                 // then children...
04114                 getSelection()->applyToNodes(&pushnonroots);
04115                 break;
04116           case SEND_CHILDREN_FIRST:
04117                 // first children...
04118                 getSelection()->applyToNodes(&pushnonroots);
04119                 // then roots...
04120                 getSelection()->applyToNodes(&pushroots);
04121                 break;
04122 
04123         default:
04124                 llerrs << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl;
04125         }
04126 
04127         // bail if nothing selected
04128         if (nodes_to_send.empty())
04129         {
04130                 return;
04131         }
04132         
04133         node = nodes_to_send.front();
04134         nodes_to_send.pop();
04135 
04136         // cache last region information
04137         current_region = node->getObject()->getRegion();
04138 
04139         // Start duplicate message
04140         // CRO: this isn't 
04141         gMessageSystem->newMessage(message_name.c_str());
04142         (*pack_header)(user_data);
04143 
04144         // For each object
04145         while (node != NULL)
04146         {
04147                 // remember the last region, look up the current one
04148                 last_region = current_region;
04149                 current_region = node->getObject()->getRegion();
04150 
04151                 // if to same simulator and message not too big
04152                 if ((current_region == last_region)
04153                         && (! gMessageSystem->isSendFull(NULL))
04154                         && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET))
04155                 {
04156                         // add another instance of the body of the data
04157                         (*pack_body)(node, user_data);
04158                         ++objects_sent;
04159                         ++objects_in_this_packet;
04160 
04161                         // and on to the next object
04162                         if(nodes_to_send.empty())
04163                         {
04164                                 node = NULL;
04165                         }
04166                         else
04167                         {
04168                                 node = nodes_to_send.front();
04169                                 nodes_to_send.pop();
04170                         }
04171                 }
04172                 else
04173                 {
04174                         // otherwise send current message and start new one
04175                         gMessageSystem->sendReliable( last_region->getHost());
04176                         packets_sent++;
04177                         objects_in_this_packet = 0;
04178 
04179                         gMessageSystem->newMessage(message_name.c_str());
04180                         (*pack_header)(user_data);
04181 
04182                         // don't move to the next object, we still need to add the
04183                         // body data. 
04184                 }
04185         }
04186 
04187         // flush messages
04188         if (gMessageSystem->getCurrentSendTotal() > 0)
04189         {
04190                 gMessageSystem->sendReliable( current_region->getHost());
04191                 packets_sent++;
04192         }
04193         else
04194         {
04195                 gMessageSystem->clearMessage();
04196         }
04197 
04198         // llinfos << "sendListToRegions " << message_name << " obj " << objects_sent << " pkt " << packets_sent << llendl;
04199 }
04200 
04201 
04202 //
04203 // Network communications
04204 //
04205 
04206 void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object)
04207 {
04208         LLMessageSystem* msg = gMessageSystem;
04209 
04210         msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
04211         msg->nextBlockFast(_PREHASH_AgentData);
04212         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
04213         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
04214         msg->nextBlockFast(_PREHASH_ObjectData);
04215         msg->addU32Fast(_PREHASH_RequestFlags, 0x0 );
04216         msg->addUUIDFast(_PREHASH_ObjectID, object->mID );
04217 
04218         LLViewerRegion* regionp = object->getRegion();
04219         msg->sendReliable( regionp->getHost() );
04220 }
04221 
04222 
04223 // static
04224 void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data)
04225 {
04226         S32 i;
04227         S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData);
04228         for (i = 0; i < count; i++)
04229         {
04230                 LLUUID id;
04231                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i);
04232 
04233                 LLUUID creator_id;
04234                 LLUUID owner_id;
04235                 LLUUID group_id;
04236                 LLUUID last_owner_id;
04237                 U64 creation_date;
04238                 LLUUID extra_id;
04239                 U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask;
04240                 LLSaleInfo sale_info;
04241                 LLCategory category;
04242                 LLAggregatePermissions ag_perms;
04243                 LLAggregatePermissions ag_texture_perms;
04244                 LLAggregatePermissions ag_texture_perms_owner;
04245                 
04246                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_CreatorID, creator_id, i);
04247                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, i);
04248                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id, i);
04249                 msg->getU64Fast(_PREHASH_ObjectData, _PREHASH_CreationDate, creation_date, i);
04250                 msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask, i);
04251                 msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask, i);
04252                 msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_GroupMask, group_mask, i);
04253                 msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask, i);
04254                 msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask, i);
04255                 sale_info.unpackMultiMessage(msg, _PREHASH_ObjectData, i);
04256 
04257                 ag_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePerms, i);
04258                 ag_texture_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTextures, i);
04259                 ag_texture_perms_owner.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTexturesOwner, i);
04260                 category.unpackMultiMessage(msg, _PREHASH_ObjectData, i);
04261 
04262                 S16 inv_serial = 0;
04263                 msg->getS16Fast(_PREHASH_ObjectData, _PREHASH_InventorySerial, inv_serial, i);
04264 
04265                 LLUUID item_id;
04266                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ItemID, item_id, i);
04267                 LLUUID folder_id;
04268                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FolderID, folder_id, i);
04269                 LLUUID from_task_id;
04270                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FromTaskID, from_task_id, i);
04271 
04272                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i);
04273 
04274                 char name[DB_INV_ITEM_NAME_BUF_SIZE];           /* Flawfinder: ignore */
04275                 msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, i);
04276                 char desc[DB_INV_ITEM_DESC_BUF_SIZE];           /* Flawfinder: ignore */
04277                 msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc, i);
04278 
04279                 char touch_name[DB_INV_ITEM_NAME_BUF_SIZE];             /* Flawfinder: ignore */
04280                 msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, DB_INV_ITEM_NAME_BUF_SIZE, touch_name, i);
04281                 char sit_name[DB_INV_ITEM_DESC_BUF_SIZE];               /* Flawfinder: ignore */
04282                 msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, DB_INV_ITEM_DESC_BUF_SIZE, sit_name, i);
04283 
04284                 //unpack TE IDs
04285                 std::vector<LLUUID> texture_ids;
04286                 S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID);
04287                 if (size > 0)
04288                 {
04289                         S8 packed_buffer[SELECT_MAX_TES * UUID_BYTES];
04290                         msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureID, packed_buffer, 0, i, SELECT_MAX_TES * UUID_BYTES);
04291 
04292                         for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES)
04293                         {
04294                                 LLUUID tid;
04295                                 memcpy(tid.mData, packed_buffer + buf_offset, UUID_BYTES);              /* Flawfinder: ignore */
04296                                 texture_ids.push_back(tid);
04297                         }
04298                 }
04299 
04300 
04301                 // Iterate through nodes at end, since it can be on both the regular AND hover list
04302                 struct f : public LLSelectedNodeFunctor
04303                 {
04304                         LLUUID mID;
04305                         f(const LLUUID& id) : mID(id) {}
04306                         virtual bool apply(LLSelectNode* node)
04307                         {
04308                                 return (node->getObject() && node->getObject()->mID == mID);
04309                         }
04310                 } func(id);
04311                 LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func);
04312 
04313                 if (node)
04314                 {
04315                         if (node->mInventorySerial != inv_serial)
04316                         {
04317                                 node->getObject()->dirtyInventory();
04318                         }
04319 
04320                         // save texture data as soon as we get texture perms first time
04321                         if (!node->mValid)
04322                         {
04323                                 BOOL can_copy = FALSE;
04324                                 BOOL can_transfer = FALSE;
04325 
04326                                 LLAggregatePermissions::EValue value = LLAggregatePermissions::AP_NONE;
04327                                 if(node->getObject()->permYouOwner())
04328                                 {
04329                                         value = ag_texture_perms_owner.getValue(PERM_COPY);
04330                                         if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL)
04331                                         {
04332                                                 can_copy = TRUE;
04333                                         }
04334                                         value = ag_texture_perms_owner.getValue(PERM_TRANSFER);
04335                                         if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL)
04336                                         {
04337                                                 can_transfer = TRUE;
04338                                         }
04339                                 }
04340                                 else
04341                                 {
04342                                         value = ag_texture_perms.getValue(PERM_COPY);
04343                                         if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL)
04344                                         {
04345                                                 can_copy = TRUE;
04346                                         }
04347                                         value = ag_texture_perms.getValue(PERM_TRANSFER);
04348                                         if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL)
04349                                         {
04350                                                 can_transfer = TRUE;
04351                                         }
04352                                 }
04353 
04354                                 if (can_copy && can_transfer)
04355                                 {
04356                                         // this should be the only place that saved textures is called
04357                                         node->saveTextures(texture_ids);
04358                                 }
04359                         }
04360 
04361                         node->mValid = TRUE;
04362                         node->mPermissions->init(creator_id, owner_id,
04363                                                                          last_owner_id, group_id);
04364                         node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask);
04365                         node->mCreationDate = creation_date;
04366                         node->mItemID = item_id;
04367                         node->mFolderID = folder_id;
04368                         node->mFromTaskID = from_task_id;
04369                         node->mName.assign(name);
04370                         node->mDescription.assign(desc);
04371                         node->mSaleInfo = sale_info;
04372                         node->mAggregatePerm = ag_perms;
04373                         node->mAggregateTexturePerm = ag_texture_perms;
04374                         node->mAggregateTexturePermOwner = ag_texture_perms_owner;
04375                         node->mCategory = category;
04376                         node->mInventorySerial = inv_serial;
04377                         node->mSitName.assign(sit_name);
04378                         node->mTouchName.assign(touch_name);
04379                 }
04380         }
04381 
04382         dialog_refresh_all();
04383 
04384         // silly hack to allow 'save into inventory' 
04385         if(gPopupMenuView->getVisible())
04386         {
04387                 gPopupMenuView->setItemEnabled(SAVE_INTO_INVENTORY,
04388                                                                            enable_save_into_inventory(NULL));
04389         }
04390 
04391         // hack for left-click buy object
04392         LLToolPie::selectionPropertiesReceived();
04393 }
04394 
04395 // static
04396 void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data)
04397 {
04398         LLUUID id;
04399 
04400         U32 request_flags;
04401         LLUUID creator_id;
04402         LLUUID owner_id;
04403         LLUUID group_id;
04404         LLUUID extra_id;
04405         U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask;
04406         LLSaleInfo sale_info;
04407         LLCategory category;
04408         
04409         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags,     request_flags );
04410         msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID,                id );
04411         msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID,         owner_id );
04412         msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID,         group_id );
04413         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask,         base_mask );
04414         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask,                owner_mask );
04415         msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask,         group_mask );
04416         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask,     everyone_mask );
04417         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask);
04418         sale_info.unpackMessage(msg, _PREHASH_ObjectData);
04419         category.unpackMessage(msg, _PREHASH_ObjectData);
04420 
04421         LLUUID last_owner_id;
04422         msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id );
04423 
04424         // unpack name & desc
04425         char name[DB_INV_ITEM_NAME_BUF_SIZE];           /* Flawfinder: ignore */
04426         msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name);
04427 
04428         char desc[DB_INV_ITEM_DESC_BUF_SIZE];           /* Flawfinder: ignore */
04429         msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc);
04430 
04431         // the reporter widget askes the server for info about picked objects
04432         if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST))
04433         {
04434                 EReportType report_type = (COMPLAINT_REPORT_REQUEST & request_flags) ? COMPLAINT_REPORT : BUG_REPORT;
04435                 LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type);
04436                 if (reporterp)
04437                 {
04438                         std::string fullname;
04439                         gCacheName->getFullName(owner_id, fullname);
04440                         reporterp->setPickedObjectProperties(name, fullname, owner_id);
04441                 }
04442         }
04443         else if (request_flags & OBJECT_PAY_REQUEST)
04444         {
04445                 // check if the owner of the paid object is muted
04446                 LLMuteList::getInstance()->autoRemove(owner_id, LLMuteList::AR_MONEY);
04447         }
04448 
04449         // Now look through all of the hovered nodes
04450         struct f : public LLSelectedNodeFunctor
04451         {
04452                 LLUUID mID;
04453                 f(const LLUUID& id) : mID(id) {}
04454                 virtual bool apply(LLSelectNode* node)
04455                 {
04456                         return (node->getObject() && node->getObject()->mID == mID);
04457                 }
04458         } func(id);
04459         LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func);
04460 
04461         if (node)
04462         {
04463                 node->mValid = TRUE;
04464                 node->mPermissions->init(LLUUID::null, owner_id,
04465                                                                  last_owner_id, group_id);
04466                 node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask);
04467                 node->mSaleInfo = sale_info;
04468                 node->mCategory = category;
04469                 node->mName.assign(name);
04470                 node->mDescription.assign(desc);
04471         }
04472 
04473         dialog_refresh_all();
04474 }
04475 
04476 
04477 // static
04478 void LLSelectMgr::processForceObjectSelect(LLMessageSystem* msg, void**)
04479 {
04480         BOOL reset_list;
04481         msg->getBOOL("Header", "ResetList", reset_list);
04482 
04483         if (reset_list)
04484         {
04485                 LLSelectMgr::getInstance()->deselectAll();
04486         }
04487 
04488         LLUUID full_id;
04489         S32 local_id;
04490         LLViewerObject* object;
04491         std::vector<LLViewerObject*> objects;
04492         S32 i;
04493         S32 block_count = msg->getNumberOfBlocks("Data");
04494 
04495         for (i = 0; i < block_count; i++)
04496         {
04497                 msg->getS32("Data", "LocalID", local_id, i);
04498 
04499                 gObjectList.getUUIDFromLocal(full_id, 
04500                                                                          local_id, 
04501                                                                          msg->getSenderIP(),
04502                                                                          msg->getSenderPort());
04503                 object = gObjectList.findObject(full_id);
04504                 if (object)
04505                 {
04506                         objects.push_back(object);
04507                 }
04508         }
04509 
04510         // Don't select, just highlight
04511         LLSelectMgr::getInstance()->highlightObjectAndFamily(objects);
04512 }
04513 
04514 
04515 extern LLGLdouble       gGLModelView[16];
04516 
04517 void LLSelectMgr::updateSilhouettes()
04518 {
04519         S32 num_sils_genned = 0;
04520 
04521         LLVector3d      cameraPos = gAgent.getCameraPositionGlobal();
04522         F32 currentCameraZoom = gAgent.getCurrentCameraBuildOffset();
04523 
04524         if (!mSilhouetteImagep)
04525         {
04526                 mSilhouetteImagep = gImageList.getImageFromFile("silhouette.j2c", TRUE, TRUE);
04527         }
04528 
04529         mHighlightedObjects->cleanupNodes();
04530 
04531         if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom)
04532         {
04533                 struct f : public LLSelectedObjectFunctor
04534                 {
04535                         virtual bool apply(LLViewerObject* object)
04536                         {
04537                                 object->setChanged(LLXform::SILHOUETTE);
04538                                 return true;
04539                         }
04540                 } func;
04541                 getSelection()->applyToObjects(&func);  
04542                 
04543                 mLastCameraPos = gAgent.getCameraPositionGlobal();
04544         }
04545         
04546         std::vector<LLViewerObject*> changed_objects;
04547 
04548         if (mSelectedObjects->getNumNodes())
04549         {
04550                 //gGLSPipelineSelection.set();
04551 
04552                 //mSilhouetteImagep->bindTexture();
04553                 //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
04554 
04555                 for (S32 pass = 0; pass < 2; pass++)
04556                 {
04557                         for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
04558                                  iter != mSelectedObjects->end(); iter++)
04559                         {
04560                                 LLSelectNode* node = *iter;
04561                                 LLViewerObject* objectp = node->getObject();
04562                                 if (!objectp)
04563                                         continue;
04564                                 // do roots first, then children so that root flags are cleared ASAP
04565                                 BOOL roots_only = (pass == 0);
04566                                 BOOL is_root = (objectp->isRootEdit());
04567                                 if (roots_only != is_root || objectp->mDrawable.isNull())
04568                                 {
04569                                         continue;
04570                                 }
04571 
04572                                 if (!node->mSilhouetteExists 
04573                                         || objectp->isChanged(LLXform::SILHOUETTE)
04574                                         || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
04575                                 {
04576                                         if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
04577                                         {
04578                                                 generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
04579                                                 changed_objects.push_back(objectp);
04580                                         }
04581                                         else if (objectp->isAttachment())
04582                                         {
04583                                                 //RN: hack for orthogonal projection of HUD attachments
04584                                                 LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
04585                                                 if (attachment_pt && attachment_pt->getIsHUDAttachment())
04586                                                 {
04587                                                         LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
04588                                                         generateSilhouette(node, camera_pos);
04589                                                 }
04590                                         }
04591                                 }
04592                         }
04593                 }
04594         }
04595 
04596         if (mRectSelectedObjects.size() > 0)
04597         {
04598                 //gGLSPipelineSelection.set();
04599 
04600                 //mSilhouetteImagep->bindTexture();
04601                 //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
04602 
04603                 std::set<LLViewerObject*> roots;
04604 
04605                 // sync mHighlightedObjects with mRectSelectedObjects since the latter is rebuilt every frame and former
04606                 // persists from frame to frame to avoid regenerating object silhouettes
04607                 // mHighlightedObjects includes all siblings of rect selected objects
04608 
04609                 BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
04610 
04611                 // generate list of roots from current object selection
04612                 for (std::set<LLPointer<LLViewerObject> >::iterator iter = mRectSelectedObjects.begin();
04613                          iter != mRectSelectedObjects.end(); iter++)
04614                 {
04615                         LLViewerObject *objectp = *iter;
04616                         if (select_linked_set)
04617                         {
04618                                 LLViewerObject *rootp = (LLViewerObject*)objectp->getRoot();
04619                                 roots.insert(rootp);
04620                         }
04621                         else
04622                         {
04623                                 roots.insert(objectp);
04624                         }
04625                 }
04626 
04627                 // remove highlight nodes not in roots list
04628                 std::vector<LLSelectNode*> remove_these_nodes;
04629                 std::vector<LLViewerObject*> remove_these_roots;
04630 
04631                 for (LLObjectSelection::iterator iter = mHighlightedObjects->begin();
04632                          iter != mHighlightedObjects->end(); iter++)
04633                 {
04634                         LLSelectNode* node = *iter;
04635                         LLViewerObject* objectp = node->getObject();
04636                         if (!objectp)
04637                                 continue;
04638                         if (objectp->isRoot() || !select_linked_set)
04639                         {
04640                                 if (roots.count(objectp) == 0)
04641                                 {
04642                                         remove_these_nodes.push_back(node);
04643                                 }
04644                                 else
04645                                 {
04646                                         remove_these_roots.push_back(objectp);
04647                                 }
04648                         }
04649                         else
04650                         {
04651                                 LLViewerObject* rootp = (LLViewerObject*)objectp->getRoot();
04652 
04653                                 if (roots.count(rootp) == 0)
04654                                 {
04655                                         remove_these_nodes.push_back(node);
04656                                 }
04657                         }
04658                 }
04659 
04660                 // remove all highlight nodes no longer in rectangle selection
04661                 for (std::vector<LLSelectNode*>::iterator iter = remove_these_nodes.begin();
04662                          iter != remove_these_nodes.end(); ++iter)
04663                 {
04664                         LLSelectNode* nodep = *iter;
04665                         mHighlightedObjects->removeNode(nodep);
04666                 }
04667 
04668                 // remove all root objects already being highlighted
04669                 for (std::vector<LLViewerObject*>::iterator iter = remove_these_roots.begin();
04670                          iter != remove_these_roots.end(); ++iter)
04671                 {
04672                         LLViewerObject* objectp = *iter;
04673                         roots.erase(objectp);
04674                 }
04675 
04676                 // add all new objects in rectangle selection
04677                 for (std::set<LLViewerObject*>::iterator iter = roots.begin();
04678                          iter != roots.end(); iter++)
04679                 {
04680                         LLViewerObject* objectp = *iter;
04681                         if (!canSelectObject(objectp))
04682                         {
04683                                 continue;
04684                         }
04685 
04686                         LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE);
04687                         rect_select_root_node->selectAllTEs(TRUE);
04688 
04689                         if (!select_linked_set)
04690                         {
04691                                 rect_select_root_node->mIndividualSelection = TRUE;
04692                         }
04693                         else
04694                         {
04695                                 for (LLViewerObject::child_list_t::iterator iter = objectp->mChildList.begin();
04696                                          iter != objectp->mChildList.end(); ++iter)
04697                                 {
04698                                         LLViewerObject* child_objectp = *iter;
04699                                 
04700                                         if (!canSelectObject(child_objectp))
04701                                         {
04702                                                 continue;
04703                                         }
04704 
04705                                         LLSelectNode* rect_select_node = new LLSelectNode(child_objectp, TRUE);
04706                                         rect_select_node->selectAllTEs(TRUE);
04707                                         mHighlightedObjects->addNodeAtEnd(rect_select_node);
04708                                 }
04709                         }
04710 
04711                         // Add the root last, to preserve order for link operations.
04712                         mHighlightedObjects->addNodeAtEnd(rect_select_root_node);
04713                 }
04714 
04715                 num_sils_genned = 0;
04716 
04717                 // render silhouettes for highlighted objects
04718                 //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL);
04719                 for (S32 pass = 0; pass < 2; pass++)
04720                 {
04721                         for (LLObjectSelection::iterator iter = mHighlightedObjects->begin();
04722                                  iter != mHighlightedObjects->end(); iter++)
04723                         {
04724                                 LLSelectNode* node = *iter;
04725                                 LLViewerObject* objectp = node->getObject();
04726                                 if (!objectp)
04727                                         continue;
04728                                 
04729                                 // do roots first, then children so that root flags are cleared ASAP
04730                                 BOOL roots_only = (pass == 0);
04731                                 BOOL is_root = objectp->isRootEdit();
04732                                 if (roots_only != is_root)
04733                                 {
04734                                         continue;
04735                                 }
04736 
04737                                 if (!node->mSilhouetteExists 
04738                                         || objectp->isChanged(LLXform::SILHOUETTE)
04739                                         || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
04740                                 {
04741                                         if (num_sils_genned++ < MAX_SILS_PER_FRAME)
04742                                         {
04743                                                 generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
04744                                                 changed_objects.push_back(objectp);                     
04745                                         }
04746                                         else if (objectp->isAttachment() && objectp->getRootEdit()->mDrawable.notNull())
04747                                         {
04748                                                 //RN: hack for orthogonal projection of HUD attachments
04749                                                 LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
04750                                                 if (attachment_pt && attachment_pt->getIsHUDAttachment())
04751                                                 {
04752                                                         LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
04753                                                         generateSilhouette(node, camera_pos);
04754                                                 }
04755                                         }
04756                                 }
04757                                 //LLColor4 highlight_color;
04758                                 //
04759                                 //if (subtracting_from_selection)
04760                                 //{
04761                                 //      node->renderOneSilhouette(LLColor4::red);
04762                                 //}
04763                                 //else if (!objectp->isSelected())
04764                                 //{
04765                                 //      highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor;
04766                                 //      node->renderOneSilhouette(highlight_color);
04767                                 //}
04768                         }
04769                 }
04770                 //mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D);
04771         }
04772         else
04773         {
04774                 mHighlightedObjects->deleteAllNodes();
04775         }
04776 
04777         for (std::vector<LLViewerObject*>::iterator iter = changed_objects.begin();
04778                  iter != changed_objects.end(); ++iter)
04779         {
04780                 // clear flags after traversing node list (as child objects need to refer to parent flags, etc)
04781                 LLViewerObject* objectp = *iter;
04782                 objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE);
04783         }
04784         
04785         //glAlphaFunc(GL_GREATER, 0.01f);
04786 }
04787 
04788 void LLSelectMgr::renderSilhouettes(BOOL for_hud)
04789 {
04790         if (!mRenderSilhouettes)
04791         {
04792                 return;
04793         }
04794 
04795         LLViewerImage::bindTexture(mSilhouetteImagep);
04796         LLGLSPipelineSelection gls_select;
04797         glAlphaFunc(GL_GREATER, 0.0f);
04798         LLGLEnable blend(GL_BLEND);
04799         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
04800 
04801         LLVOAvatar* avatar = gAgent.getAvatarObject();
04802         if (for_hud && avatar)
04803         {
04804                 LLBBox hud_bbox = avatar->getHUDBBox();
04805 
04806                 F32 cur_zoom = avatar->mHUDCurZoom;
04807 
04808                 // set up transform to encompass bounding box of HUD
04809                 glMatrixMode(GL_PROJECTION);
04810                 glPushMatrix();
04811                 glLoadIdentity();
04812                 F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
04813                 glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
04814 
04815                 glMatrixMode(GL_MODELVIEW);
04816                 glPushMatrix();
04817                 glLoadIdentity();
04818                 glLoadMatrixf(OGL_TO_CFR_ROTATION);             // Load Cory's favorite reference frame
04819                 glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
04820                 glScalef(cur_zoom, cur_zoom, cur_zoom);
04821         }
04822         if (mSelectedObjects->getNumNodes())
04823         {
04824                 LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
04825                 for (S32 pass = 0; pass < 2; pass++)
04826                 {
04827                         for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
04828                                  iter != mSelectedObjects->end(); iter++)
04829                         {
04830                                 LLSelectNode* node = *iter;
04831                                 LLViewerObject* objectp = node->getObject();
04832                                 if (!objectp)
04833                                         continue;
04834                                 if (objectp->isHUDAttachment() != for_hud)
04835                                 {
04836                                         continue;
04837                                 }
04838                                 if(objectp->getID() == inspect_item_id)
04839                                 {
04840                                         node->renderOneSilhouette(sHighlightInspectColor);
04841                                 }
04842                                 else if (node->isTransient())
04843                                 {
04844                                         BOOL oldHidden = LLSelectMgr::sRenderHiddenSelections;
04845                                         LLSelectMgr::sRenderHiddenSelections = FALSE;
04846                                         node->renderOneSilhouette(sContextSilhouetteColor);
04847                                         LLSelectMgr::sRenderHiddenSelections = oldHidden;
04848                                 }
04849                                 else if (objectp->isRootEdit())
04850                                 {
04851                                         node->renderOneSilhouette(sSilhouetteParentColor);
04852                                 }
04853                                 else
04854                                 {
04855                                         node->renderOneSilhouette(sSilhouetteChildColor);
04856                                 }
04857                         }
04858                 }
04859         }
04860 
04861         if (mHighlightedObjects->getNumNodes())
04862         {
04863                 // render silhouettes for highlighted objects
04864                 BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL);
04865                 for (S32 pass = 0; pass < 2; pass++)
04866                 {
04867                         for (LLObjectSelection::iterator iter = mHighlightedObjects->begin();
04868                                  iter != mHighlightedObjects->end(); iter++)
04869                         {
04870                                 LLSelectNode* node = *iter;
04871                                 LLViewerObject* objectp = node->getObject();
04872                                 if (!objectp)
04873                                         continue;
04874                                 if (objectp->isHUDAttachment() != for_hud)
04875                                 {
04876                                         continue;
04877                                 }
04878 
04879                                 if (subtracting_from_selection)
04880                                 {
04881                                         node->renderOneSilhouette(LLColor4::red);
04882                                 }
04883                                 else if (!objectp->isSelected())
04884                                 {
04885                                         LLColor4 highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor;
04886                                         node->renderOneSilhouette(highlight_color);
04887                                 }
04888                         }
04889                 }
04890         }
04891 
04892         if (for_hud && avatar)
04893         {
04894                 glMatrixMode(GL_PROJECTION);
04895                 glPopMatrix();
04896 
04897                 glMatrixMode(GL_MODELVIEW);
04898                 glPopMatrix();
04899                 stop_glerror();
04900         }
04901 
04902         mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D);
04903         glAlphaFunc(GL_GREATER, 0.01f);
04904 }
04905 
04906 void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point)
04907 {
04908         LLViewerObject* objectp = nodep->getObject();
04909 
04910         if (objectp && objectp->getPCode() == LL_PCODE_VOLUME)
04911         {
04912                 ((LLVOVolume*)objectp)->generateSilhouette(nodep, view_point);
04913         }
04914 }
04915 
04916 //
04917 // Utility classes
04918 //
04919 LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
04920 {
04921         mObject = object;
04922         selectAllTEs(FALSE);
04923         mIndividualSelection    = FALSE;
04924         mTransient              = FALSE;
04925         mValid                  = FALSE;
04926         mPermissions    = new LLPermissions();
04927         mInventorySerial = 0;
04928         mName = LLString::null;
04929         mDescription = LLString::null;
04930         mTouchName = LLString::null;
04931         mSitName = LLString::null;
04932         mSilhouetteExists = FALSE;
04933         mDuplicated = FALSE;
04934 
04935         saveColors();
04936 }
04937 
04938 LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
04939 {
04940         S32 i;
04941         for (i = 0; i < SELECT_MAX_TES; i++)
04942         {
04943                 mTESelected[i] = nodep.mTESelected[i];
04944         }
04945         mLastTESelected = nodep.mLastTESelected;
04946 
04947         mIndividualSelection = nodep.mIndividualSelection;
04948 
04949         mValid = nodep.mValid;
04950         mTransient              = nodep.mTransient;
04951         mPermissions = new LLPermissions(*nodep.mPermissions);
04952         mSaleInfo = nodep.mSaleInfo;;
04953         mAggregatePerm = nodep.mAggregatePerm;
04954         mAggregateTexturePerm = nodep.mAggregateTexturePerm;
04955         mAggregateTexturePermOwner = nodep.mAggregateTexturePermOwner;
04956         mName = nodep.mName;
04957         mDescription = nodep.mDescription;
04958         mCategory = nodep.mCategory;
04959         mSavedPositionLocal = nodep.mSavedPositionLocal;
04960         mSavedPositionGlobal = nodep.mSavedPositionGlobal;
04961         mSavedScale = nodep.mSavedScale;
04962         mSavedRotation = nodep.mSavedRotation;
04963         mDuplicated = nodep.mDuplicated;
04964         mDuplicatePos = nodep.mDuplicatePos;
04965         mDuplicateRot = nodep.mDuplicateRot;
04966         mItemID = nodep.mItemID;
04967         mFolderID = nodep.mFolderID;
04968         mFromTaskID = nodep.mFromTaskID;
04969         mTouchName = nodep.mTouchName;
04970         mSitName = nodep.mSitName;
04971 
04972         mSilhouetteVertices = nodep.mSilhouetteVertices;
04973         mSilhouetteNormals = nodep.mSilhouetteNormals;
04974         mSilhouetteSegments = nodep.mSilhouetteSegments;
04975         mSilhouetteExists = nodep.mSilhouetteExists;
04976         mObject = nodep.mObject;
04977 
04978         std::vector<LLColor4>::const_iterator color_iter;
04979         mSavedColors.clear();
04980         for (color_iter = nodep.mSavedColors.begin(); color_iter != nodep.mSavedColors.end(); ++color_iter)
04981         {
04982                 mSavedColors.push_back(*color_iter);
04983         }
04984         
04985         saveTextures(nodep.mSavedTextures);
04986 }
04987 
04988 LLSelectNode::~LLSelectNode()
04989 {
04990         delete mPermissions;
04991         mPermissions = NULL;
04992 }
04993 
04994 void LLSelectNode::selectAllTEs(BOOL b)
04995 {
04996         for (S32 i = 0; i < SELECT_MAX_TES; i++)
04997         {
04998                 mTESelected[i] = b;
04999         }
05000         mLastTESelected = 0;
05001 }
05002 
05003 void LLSelectNode::selectTE(S32 te_index, BOOL selected)
05004 {
05005         if (te_index < 0 || te_index >= SELECT_MAX_TES)
05006         {
05007                 return;
05008         }
05009         mTESelected[te_index] = selected;
05010         mLastTESelected = te_index;
05011 }
05012 
05013 BOOL LLSelectNode::isTESelected(S32 te_index)
05014 {
05015         if (te_index < 0 || te_index >= mObject->getNumTEs())
05016         {
05017                 return FALSE;
05018         }
05019         return mTESelected[te_index];
05020 }
05021 
05022 S32 LLSelectNode::getLastSelectedTE()
05023 {
05024         if (!isTESelected(mLastTESelected))
05025         {
05026                 return -1;
05027         }
05028         return mLastTESelected;
05029 }
05030 
05031 LLViewerObject* LLSelectNode::getObject()
05032 {
05033         if (!mObject)
05034         {
05035                 return NULL;
05036         }
05037         else if (mObject->isDead())
05038         {
05039                 mObject = NULL;
05040         }
05041         return mObject;
05042 }
05043 
05044 void LLSelectNode::setObject(LLViewerObject* object)
05045 {
05046         mObject = object;
05047 }
05048 
05049 void LLSelectNode::saveColors()
05050 {
05051         if (mObject.notNull())
05052         {
05053                 mSavedColors.clear();
05054                 for (S32 i = 0; i < mObject->getNumTEs(); i++)
05055                 {
05056                         const LLTextureEntry* tep = mObject->getTE(i);
05057                         mSavedColors.push_back(tep->getColor());
05058                 }
05059         }
05060 }
05061 
05062 void LLSelectNode::saveTextures(const std::vector<LLUUID>& textures)
05063 {
05064         if (mObject.notNull())
05065         {
05066                 mSavedTextures.clear();
05067 
05068                 for (std::vector<LLUUID>::const_iterator texture_it = textures.begin();
05069                          texture_it != textures.end(); ++texture_it)
05070                 {
05071                         mSavedTextures.push_back(*texture_it);
05072                 }
05073         }
05074 }
05075 
05076 void LLSelectNode::saveTextureScaleRatios()
05077 {
05078         mTextureScaleRatios.clear();
05079         if (mObject.notNull())
05080         {
05081                 for (U8 i = 0; i < mObject->getNumTEs(); i++)
05082                 {
05083                         F32 s,t;
05084                         const LLTextureEntry* tep = mObject->getTE(i);
05085                         tep->getScale(&s,&t);
05086                         U32 s_axis = 0;
05087                         U32 t_axis = 0;
05088 
05089                         LLPrimitive::getTESTAxes(i, &s_axis, &t_axis);
05090 
05091                         LLVector3 v;
05092                         LLVector3 scale = mObject->getScale();
05093 
05094                         if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR)
05095                         {
05096                                 v.mV[s_axis] = s*scale.mV[s_axis];
05097                                 v.mV[t_axis] = t*scale.mV[t_axis];
05098                         }
05099                         else
05100                         {
05101                                 v.mV[s_axis] = s/scale.mV[s_axis];
05102                                 v.mV[t_axis] = t/scale.mV[t_axis];
05103                         }
05104 
05105                         mTextureScaleRatios.push_back(v);
05106                 }
05107         }
05108 }
05109 
05110 
05111 // This implementation should be similar to LLTask::allowOperationOnTask
05112 BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const
05113 {
05114         // Extract ownership.
05115         BOOL object_is_group_owned = FALSE;
05116         LLUUID object_owner_id;
05117         mPermissions->getOwnership(object_owner_id, object_is_group_owned);
05118 
05119         // Operations on invalid or public objects is not allowed.
05120         if (!mObject || (mObject->isDead()) || !mPermissions->isOwned())
05121         {
05122                 return FALSE;
05123         }
05124 
05125         // The transfer permissions can never be given through proxy.
05126         if (PERM_TRANSFER == op)
05127         {
05128                 // The owner of an agent-owned object can transfer to themselves.
05129                 if ( !object_is_group_owned 
05130                         && (gAgent.getID() == object_owner_id) )
05131                 {
05132                         return TRUE;
05133                 }
05134                 else
05135                 {
05136                         // Otherwise check aggregate permissions.
05137                         return mObject->permTransfer();
05138                 }
05139         }
05140 
05141         if (PERM_MOVE == op
05142                 || PERM_MODIFY == op)
05143         {
05144                 // only owners can move or modify their attachments
05145                 // no proxy allowed.
05146                 if (mObject->isAttachment() && object_owner_id != gAgent.getID())
05147                 {
05148                         return FALSE;
05149                 }
05150         }
05151 
05152         // Calculate proxy_agent_id and group_id to use for permissions checks.
05153         // proxy_agent_id may be set to the object owner through group powers.
05154         // group_id can only be set to the object's group, if the agent is in that group.
05155         LLUUID group_id = LLUUID::null;
05156         LLUUID proxy_agent_id = gAgent.getID();
05157 
05158         // Gods can always operate.
05159         if (gAgent.isGodlike())
05160         {
05161                 return TRUE;
05162         }
05163 
05164         // Check if the agent is in the same group as the object.
05165         LLUUID object_group_id = mPermissions->getGroup();
05166         if (object_group_id.notNull() &&
05167                 gAgent.isInGroup(object_group_id))
05168         {
05169                 // Assume the object's group during this operation.
05170                 group_id = object_group_id;
05171         }
05172 
05173         // Only allow proxy powers for PERM_COPY if the actual agent can
05174         // receive the item (ie has PERM_TRANSFER permissions).
05175         // NOTE: op == PERM_TRANSFER has already been handled, but if
05176         // that ever changes we need to BLOCK proxy powers for PERM_TRANSFER.  DK 03/28/06
05177         if (PERM_COPY != op || mPermissions->allowTransferTo(gAgent.getID()))
05178         {
05179                 // Check if the agent can assume ownership through group proxy or agent-granted proxy.
05180                 if (   ( object_is_group_owned 
05181                                 && gAgent.hasPowerInGroup(object_owner_id, group_proxy_power))
05182                                 // Only allow proxy for move, modify, and copy.
05183                                 || ( (PERM_MOVE == op || PERM_MODIFY == op || PERM_COPY == op)
05184                                         && (!object_is_group_owned
05185                                                 && gAgent.isGrantedProxy(*mPermissions))))
05186                 {
05187                         // This agent is able to assume the ownership role for this operation.
05188                         proxy_agent_id = object_owner_id;
05189                 }
05190         }
05191         
05192         // We now have max ownership information.
05193         if (PERM_OWNER == op)
05194         {
05195                 // This this was just a check for ownership, we can now return the answer.
05196                 return (proxy_agent_id == object_owner_id ? TRUE : FALSE);
05197         }
05198 
05199         // check permissions to see if the agent can operate
05200         return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id));
05201 }
05202 
05203 //-----------------------------------------------------------------------------
05204 // renderOneSilhouette()
05205 //-----------------------------------------------------------------------------
05206 void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
05207 {
05208         LLViewerObject* objectp = getObject();
05209         if (!objectp)
05210         {
05211                 return;
05212         }
05213 
05214         LLDrawable* drawable = objectp->mDrawable;
05215         if(!drawable)
05216         {
05217                 return;
05218         }
05219 
05220         if (!mSilhouetteExists)
05221         {
05222                 return;
05223         }
05224 
05225         BOOL is_hud_object = objectp->isHUDAttachment();
05226         
05227         if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size())
05228         {
05229                 return;
05230         }
05231 
05232         glMatrixMode(GL_MODELVIEW);
05233         glPushMatrix();
05234         if (!is_hud_object)
05235         {
05236                 glLoadIdentity();
05237                 glMultMatrixd(gGLModelView);
05238         }
05239         
05240         
05241         if (drawable->isActive())
05242         {
05243                 glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix);
05244         }
05245 
05246         LLVolume *volume = objectp->getVolume();
05247         if (volume)
05248         {
05249                 F32 silhouette_thickness;
05250                 if (is_hud_object && gAgent.getAvatarObject())
05251                 {
05252                         silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.getAvatarObject()->mHUDCurZoom;
05253                 }
05254                 else
05255                 {
05256                         LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition();
05257                         silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV());
05258                 }               
05259                 F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds();
05260 
05261                 F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f);
05262                 F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f);
05263                 F32 u_divisor = 1.f / ((F32)(mSilhouetteVertices.size() - 1));
05264 
05265                 if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible())
05266                 {
05267                         gGL.flush();
05268                         gGL.blendFunc(GL_SRC_COLOR, GL_ONE);
05269                         LLGLEnable fog(GL_FOG);
05270                         glFogi(GL_FOG_MODE, GL_LINEAR);
05271                         float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec();
05272                         LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
05273                         glFogf(GL_FOG_START, d);
05274                         glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
05275                         glFogfv(GL_FOG_COLOR, fogCol.mV);
05276 
05277                         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
05278                         glAlphaFunc(GL_GREATER, 0.01f);
05279                         gGL.begin(LLVertexBuffer::LINES);
05280                         {
05281                                 S32 i = 0;
05282                                 for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++)
05283                                 {
05284                                         for(; i < mSilhouetteSegments[seg_num]; i++)
05285                                         {
05286                                                 u_coord += u_divisor * LLSelectMgr::sHighlightUScale;
05287 
05288                                                 gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
05289                                                 gGL.texCoord2f( u_coord, v_coord );
05290                                                 gGL.vertex3fv( mSilhouetteVertices[i].mV );
05291                                         }
05292                                 }
05293                         }
05294             gGL.end();
05295                         u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f);
05296                 }
05297 
05298                 gGL.flush();
05299                 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
05300                 gGL.begin(LLVertexBuffer::TRIANGLES);
05301                 {
05302                         S32 i = 0;
05303                         for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++)
05304                         {
05305                                 S32 first_i = i;
05306                                 LLVector3 v;
05307                                 LLVector2 t;
05308 
05309                                 for(; i < mSilhouetteSegments[seg_num]; i++)
05310                                 {
05311 
05312                                         if (i == first_i) {
05313                                             LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness;
05314                                                 vert += mSilhouetteVertices[i];
05315 
05316                                                 gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha);
05317                                                 gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale );
05318                                                 gGL.vertex3fv( vert.mV ); 
05319                                                 
05320                                                 u_coord += u_divisor * LLSelectMgr::sHighlightUScale;
05321 
05322                                                 gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
05323                                                 gGL.texCoord2f( u_coord, v_coord );
05324                                                 gGL.vertex3fv( mSilhouetteVertices[i].mV );
05325 
05326                                                 v = mSilhouetteVertices[i];
05327                                                 t = LLVector2(u_coord, v_coord);
05328                                         }
05329                                         else {
05330                         LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness;
05331                                                 vert += mSilhouetteVertices[i];
05332 
05333                                                 gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha);
05334                                                 gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale );
05335                                                 gGL.vertex3fv( vert.mV ); 
05336                                                 gGL.vertex3fv( vert.mV ); 
05337                                                 
05338                                                 gGL.texCoord2fv(t.mV);
05339                                                 u_coord += u_divisor * LLSelectMgr::sHighlightUScale;
05340                                                 gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
05341                                                 gGL.vertex3fv(v.mV);
05342                                                 gGL.texCoord2f( u_coord, v_coord );
05343                                                 gGL.vertex3fv( mSilhouetteVertices[i].mV );
05344 
05345                                         }
05346                                 }
05347                         }
05348                 }
05349                 gGL.end();
05350                 gGL.flush();
05351         }
05352         glPopMatrix();
05353 }
05354 
05355 //
05356 // Utility Functions
05357 //
05358 
05359 // Update everyone who cares about the selection list
05360 void dialog_refresh_all()
05361 {
05362         if (gNoRender)
05363         {
05364                 return;
05365         }
05366 
05367         //could refresh selected object info in toolbar here
05368 
05369         gFloaterTools->dirty();
05370 
05371         if( gPieObject->getVisible() )
05372         {
05373                 gPieObject->arrange();
05374         }
05375 
05376         LLFloaterProperties::dirtyAll();
05377         LLFloaterInspect::dirty();
05378 }
05379 
05380 S32 get_family_count(LLViewerObject *parent)
05381 {
05382         if (!parent)
05383         {
05384                 llwarns << "Trying to get_family_count on null parent!" << llendl;
05385         }
05386         S32 count = 1;  // for this object
05387         for (LLViewerObject::child_list_t::iterator iter = parent->mChildList.begin();
05388                  iter != parent->mChildList.end(); ++iter)
05389         {
05390                 LLViewerObject* child = *iter;
05391 
05392                 if (!child)
05393                 {
05394                         llwarns << "Family object has NULL child!  Show Doug." << llendl;
05395                 }
05396                 else if (child->isDead())
05397                 {
05398                         llwarns << "Family object has dead child object.  Show Doug." << llendl;
05399                 }
05400                 else
05401                 {
05402                         if (LLSelectMgr::getInstance()->canSelectObject(child))
05403                         {
05404                                 count += get_family_count( child );
05405                         }
05406                 }
05407         }
05408         return count;
05409 }
05410 
05411 //-----------------------------------------------------------------------------
05412 // updateSelectionCenter
05413 //-----------------------------------------------------------------------------
05414 void LLSelectMgr::updateSelectionCenter()
05415 {
05416         const F32 MOVE_SELECTION_THRESHOLD = 1.f;               //  Movement threshold in meters for updating selection
05417                                                                                                         //  center (tractor beam)
05418 
05419         //override any object updates received
05420         //for selected objects
05421         overrideObjectUpdates();
05422 
05423         LLViewerObject* object = mSelectedObjects->getFirstObject();
05424         if (!object)
05425         {
05426                 // nothing selected, probably grabbing
05427                 // Ignore by setting to avatar origin.
05428                 mSelectionCenterGlobal.clearVec();
05429                 mShowSelection = FALSE;
05430                 mSelectionBBox = LLBBox(); 
05431                 mPauseRequest = NULL;
05432                 resetAgentHUDZoom();
05433 
05434         }
05435         else
05436         {
05437                 mSelectedObjects->mSelectType = getSelectTypeForObject(object);
05438 
05439                 if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
05440                 {
05441                         mPauseRequest = gAgent.getAvatarObject()->requestPause();
05442                 }
05443                 else
05444                 {
05445                         mPauseRequest = NULL;
05446                 }
05447 
05448                 if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject())
05449                 {
05450                         // reset hud ZOOM
05451                         gAgent.getAvatarObject()->mHUDTargetZoom = 1.f;
05452                         gAgent.getAvatarObject()->mHUDCurZoom = 1.f;
05453                 }
05454 
05455                 mShowSelection = FALSE;
05456                 LLBBox bbox;
05457 
05458                 // have stuff selected
05459                 LLVector3d select_center;
05460                 // keep a list of jointed objects for showing the joint HUDEffects
05461 
05462                 std::vector < LLViewerObject *> jointed_objects;
05463 
05464                 for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
05465                          iter != mSelectedObjects->end(); iter++)
05466                 {
05467                         LLSelectNode* node = *iter;
05468                         LLViewerObject* object = node->getObject();
05469                         if (!object)
05470                                 continue;
05471                         LLViewerObject *myAvatar = gAgent.getAvatarObject();
05472                         LLViewerObject *root = object->getRootEdit();
05473                         if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment
05474                                 !root->isChild(myAvatar) && // not the object you're sitting on
05475                                 !object->isAvatar()) // not another avatar
05476                         {
05477                                 mShowSelection = TRUE;
05478                         }
05479 
05480                         bbox.addBBoxAgent( object->getBoundingBoxAgent() );
05481 
05482                         if (object->isJointChild())
05483                         {
05484                                 jointed_objects.push_back(object);
05485                         }
05486                 }
05487                 
05488                 LLVector3 bbox_center_agent = bbox.getCenterAgent();
05489                 mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent);
05490                 mSelectionBBox = bbox;
05491 
05492         }
05493         
05494         if ( !(gAgentID == LLUUID::null)) 
05495         {
05496                 LLTool          *tool = LLToolMgr::getInstance()->getCurrentTool();
05497                 if (mShowSelection)
05498                 {
05499                         LLVector3d select_center_global;
05500 
05501                         if( tool->isEditing() )
05502                         {
05503                                 select_center_global = tool->getEditingPointGlobal();
05504                         }
05505                         else
05506                         {
05507                                 select_center_global = mSelectionCenterGlobal;
05508                         }
05509 
05510                         // Send selection center if moved beyond threshold (used to animate tractor beam)       
05511                         LLVector3d diff;
05512                         diff = select_center_global - mLastSentSelectionCenterGlobal;
05513 
05514                         if ( diff.magVecSquared() > MOVE_SELECTION_THRESHOLD*MOVE_SELECTION_THRESHOLD )
05515                         {
05516                                 //  Transmit updated selection center 
05517                                 mLastSentSelectionCenterGlobal = select_center_global;
05518                         }
05519                 }
05520         }
05521 
05522         // give up edit menu if no objects selected
05523         if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0)
05524         {
05525                 gEditMenuHandler = NULL;
05526         }
05527 }
05528 
05529 void LLSelectMgr::updatePointAt()
05530 {
05531         if (mShowSelection)
05532         {
05533                 if (mSelectedObjects->getObjectCount())
05534                 {                                       
05535                         LLVector3 select_offset;
05536                         LLViewerObject *click_object = gObjectList.findObject(gLastHitObjectID);
05537                         if (click_object && click_object->isSelected())
05538                         {
05539                                 // clicked on another object in our selection group, use that as target
05540                                 select_offset.setVec(gLastHitObjectOffset);
05541                                 select_offset.rotVec(~click_object->getRenderRotation());
05542                 
05543                                 gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset);
05544                                 gAgent.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset);
05545                         }
05546                         else
05547                         {
05548                                 // didn't click on an object this time, revert to pointing at center of first object
05549                                 gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
05550                                 gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
05551                         }
05552                 }
05553                 else
05554                 {
05555                         gAgent.setPointAt(POINTAT_TARGET_CLEAR);
05556                         gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
05557                 }
05558         }
05559         else
05560         {
05561                 gAgent.setPointAt(POINTAT_TARGET_CLEAR);
05562                 gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
05563         }
05564 }
05565 
05566 //-----------------------------------------------------------------------------
05567 // getBBoxOfSelection()
05568 //-----------------------------------------------------------------------------
05569 LLBBox LLSelectMgr::getBBoxOfSelection() const
05570 {
05571         return mSelectionBBox;
05572 }
05573 
05574 
05575 //-----------------------------------------------------------------------------
05576 // canUndo()
05577 //-----------------------------------------------------------------------------
05578 BOOL LLSelectMgr::canUndo() const
05579 {
05580         return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG
05581 }
05582 
05583 //-----------------------------------------------------------------------------
05584 // undo()
05585 //-----------------------------------------------------------------------------
05586 void LLSelectMgr::undo()
05587 {
05588         BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
05589         LLUUID group_id(gAgent.getGroupID());
05590         sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST);
05591 }
05592 
05593 //-----------------------------------------------------------------------------
05594 // canRedo()
05595 //-----------------------------------------------------------------------------
05596 BOOL LLSelectMgr::canRedo() const
05597 {
05598         return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG
05599 }
05600 
05601 //-----------------------------------------------------------------------------
05602 // redo()
05603 //-----------------------------------------------------------------------------
05604 void LLSelectMgr::redo()
05605 {
05606         BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
05607         LLUUID group_id(gAgent.getGroupID());
05608         sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST);
05609 }
05610 
05611 //-----------------------------------------------------------------------------
05612 // canDoDelete()
05613 //-----------------------------------------------------------------------------
05614 BOOL LLSelectMgr::canDoDelete() const
05615 {
05616         // Note: Can only delete root objects (see getFirstDeleteableObject() for more info)
05617         return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG
05618 }
05619 
05620 //-----------------------------------------------------------------------------
05621 // doDelete()
05622 //-----------------------------------------------------------------------------
05623 void LLSelectMgr::doDelete()
05624 {
05625         selectDelete();
05626 }
05627 
05628 //-----------------------------------------------------------------------------
05629 // canDeselect()
05630 //-----------------------------------------------------------------------------
05631 BOOL LLSelectMgr::canDeselect() const
05632 {
05633         return !mSelectedObjects->isEmpty();
05634 }
05635 
05636 //-----------------------------------------------------------------------------
05637 // deselect()
05638 //-----------------------------------------------------------------------------
05639 void LLSelectMgr::deselect()
05640 {
05641         deselectAll();
05642 }
05643 //-----------------------------------------------------------------------------
05644 // canDuplicate()
05645 //-----------------------------------------------------------------------------
05646 BOOL LLSelectMgr::canDuplicate() const
05647 {
05648         return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstCopyableObject() != NULL; // HACK: casting away constness - MG
05649 }
05650 //-----------------------------------------------------------------------------
05651 // duplicate()
05652 //-----------------------------------------------------------------------------
05653 void LLSelectMgr::duplicate()
05654 {
05655         LLVector3 offset(0.5f, 0.5f, 0.f);
05656         selectDuplicate(offset, TRUE);
05657 }
05658 
05659 ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object)
05660 {
05661         if (!object)
05662         {
05663                 return SELECT_TYPE_WORLD;
05664         }
05665         if (object->isHUDAttachment())
05666         {
05667                 return SELECT_TYPE_HUD;
05668         }
05669         else if (object->isAttachment())
05670         {
05671                 return SELECT_TYPE_ATTACHMENT;
05672         }
05673         else
05674         {
05675                 return SELECT_TYPE_WORLD;
05676         }
05677 }
05678 
05679 void LLSelectMgr::validateSelection()
05680 {
05681         struct f : public LLSelectedObjectFunctor
05682         {
05683                 virtual bool apply(LLViewerObject* object)
05684                 {
05685                         if (!LLSelectMgr::getInstance()->canSelectObject(object))
05686                         {
05687                                 LLSelectMgr::getInstance()->deselectObjectOnly(object);
05688                         }
05689                         return true;
05690                 }
05691         } func;
05692         getSelection()->applyToObjects(&func);  
05693 }
05694 
05695 BOOL LLSelectMgr::canSelectObject(LLViewerObject* object)
05696 {
05697         // Never select dead objects
05698         if (!object || object->isDead())
05699         {
05700                 return FALSE;
05701         }
05702         
05703         if (mForceSelection)
05704         {
05705                 return TRUE;
05706         }
05707 
05708         if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) ||
05709                 (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove()))
05710         {
05711                 // only select my own objects
05712                 return FALSE;
05713         }
05714 
05715         // Can't select orphans
05716         if (object->isOrphaned()) return FALSE;
05717         
05718         // Can't select avatars
05719         if (object->isAvatar()) return FALSE;
05720 
05721         // Can't select land
05722         if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE;
05723 
05724         ESelectType selection_type = getSelectTypeForObject(object);
05725         if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE;
05726 
05727         return TRUE;
05728 }
05729 
05730 BOOL LLSelectMgr::setForceSelection(BOOL force) 
05731 { 
05732         std::swap(mForceSelection,force); 
05733         return force; 
05734 }
05735 
05736 void LLSelectMgr::resetAgentHUDZoom()
05737 {
05738         if (gAgent.getAvatarObject())
05739         {
05740                 gAgent.getAvatarObject()->mHUDTargetZoom = 1.f;
05741                 gAgent.getAvatarObject()->mHUDCurZoom = 1.f;
05742         }
05743 }
05744 
05745 void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const
05746 {
05747         if (gAgent.getAvatarObject())
05748         {
05749                 target_zoom = gAgent.getAvatarObject()->mHUDTargetZoom;
05750                 current_zoom = gAgent.getAvatarObject()->mHUDCurZoom;
05751         }
05752 }
05753 
05754 void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
05755 {
05756         if (gAgent.getAvatarObject())
05757         {
05758                 gAgent.getAvatarObject()->mHUDTargetZoom = target_zoom;
05759                 gAgent.getAvatarObject()->mHUDCurZoom = current_zoom;
05760         }
05761 }
05762 
05763 LLObjectSelection::LLObjectSelection() : 
05764         LLRefCount(),
05765         mSelectType(SELECT_TYPE_WORLD)
05766 {
05767 }
05768 
05769 LLObjectSelection::~LLObjectSelection()
05770 {
05771         deleteAllNodes();
05772 }
05773 
05774 void LLObjectSelection::cleanupNodes()
05775 {
05776         for (list_t::iterator iter = mList.begin(); iter != mList.end(); )
05777         {
05778                 list_t::iterator curiter = iter++;
05779                 LLSelectNode* node = *curiter;
05780                 if (node->getObject() == NULL || node->getObject()->isDead())
05781                 {
05782                         mList.erase(curiter);
05783                         delete node;
05784                 }
05785         }
05786 }
05787 
05788 void LLObjectSelection::updateEffects()
05789 {
05790 }
05791 
05792 S32 LLObjectSelection::getNumNodes()
05793 {
05794         return mList.size();
05795 }
05796 
05797 void LLObjectSelection::addNode(LLSelectNode *nodep)
05798 {
05799         llassert_always(nodep->getObject() && !nodep->getObject()->isDead());
05800         mList.push_front(nodep);
05801         mSelectNodeMap[nodep->getObject()] = nodep;
05802 }
05803 
05804 void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep)
05805 {
05806         llassert_always(nodep->getObject() && !nodep->getObject()->isDead());
05807         mList.push_back(nodep);
05808         mSelectNodeMap[nodep->getObject()] = nodep;
05809 }
05810 
05811 void LLObjectSelection::moveNodeToFront(LLSelectNode *nodep)
05812 {
05813         mList.remove(nodep);
05814         mList.push_front(nodep);
05815 }
05816 
05817 void LLObjectSelection::removeNode(LLSelectNode *nodep)
05818 {
05819         mSelectNodeMap.erase(nodep->getObject());
05820         if (nodep->getObject() == mPrimaryObject)
05821         {
05822                 mPrimaryObject = NULL;
05823         }
05824         nodep->setObject(NULL); // Will get erased in cleanupNodes()
05825         mList.remove(nodep);
05826 }
05827 
05828 void LLObjectSelection::deleteAllNodes()
05829 {
05830         std::for_each(mList.begin(), mList.end(), DeletePointer());
05831         mList.clear();
05832         mSelectNodeMap.clear();
05833         mPrimaryObject = NULL;
05834 }
05835 
05836 LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp)
05837 {
05838         std::map<LLPointer<LLViewerObject>, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp);
05839         if (found_it != mSelectNodeMap.end())
05840         {
05841                 return found_it->second;
05842         }
05843         return NULL;
05844 }
05845 
05846 //-----------------------------------------------------------------------------
05847 // isEmpty()
05848 //-----------------------------------------------------------------------------
05849 BOOL LLObjectSelection::isEmpty() const
05850 {
05851         return (mList.size() == 0);
05852 }
05853 
05854 //-----------------------------------------------------------------------------
05855 // getOwnershipCost()
05856 //-----------------------------------------------------------------------------
05857 BOOL LLObjectSelection::getOwnershipCost(S32 &cost)
05858 {
05859         S32 count = getObjectCount();
05860         cost = count * OWNERSHIP_COST_PER_OBJECT;
05861         return (count > 0);
05862 }
05863 
05864 
05865 //-----------------------------------------------------------------------------
05866 // getObjectCount() - returns number of non null objects
05867 //-----------------------------------------------------------------------------
05868 S32 LLObjectSelection::getObjectCount()
05869 {
05870         cleanupNodes();
05871         S32 count = mList.size();
05872         return count;
05873 }
05874 
05875 
05876 //-----------------------------------------------------------------------------
05877 // getTECount()
05878 //-----------------------------------------------------------------------------
05879 S32 LLObjectSelection::getTECount()
05880 {
05881         S32 count = 0;
05882         for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++)
05883         {
05884                 LLSelectNode* node = *iter;
05885                 LLViewerObject* object = node->getObject();
05886                 if (!object)
05887                         continue;
05888                 S32 num_tes = object->getNumTEs();
05889                 for (S32 te = 0; te < num_tes; te++)
05890                 {
05891                         if (node->isTESelected(te))
05892                         {
05893                                 ++count;
05894                         }
05895                 }
05896         }
05897         return count;
05898 }
05899 
05900 //-----------------------------------------------------------------------------
05901 // getRootObjectCount()
05902 //-----------------------------------------------------------------------------
05903 S32 LLObjectSelection::getRootObjectCount()
05904 {
05905         S32 count = 0;
05906         for (LLObjectSelection::root_iterator iter = root_begin(); iter != root_end(); iter++)
05907         {
05908                 ++count;
05909         }
05910         return count;
05911 }
05912 
05913 bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func, bool firstonly)
05914 {
05915         bool result = firstonly ? false : true;
05916         for (iterator iter = begin(); iter != end(); )
05917         {
05918                 iterator nextiter = iter++;
05919                 LLViewerObject* object = (*nextiter)->getObject();
05920                 if (!object)
05921                         continue;
05922                 bool r = func->apply(object);
05923                 if (firstonly && r)
05924                         return true;
05925                 else
05926                         result = result && r;
05927         }
05928         return result;
05929 }
05930 
05931 bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly)
05932 {
05933         bool result = firstonly ? false : true;
05934         for (root_iterator iter = root_begin(); iter != root_end(); )
05935         {
05936                 root_iterator nextiter = iter++;
05937                 LLViewerObject* object = (*nextiter)->getObject();
05938                 if (!object)
05939                         continue;
05940                 bool r = func->apply(object);
05941                 if (firstonly && r)
05942                         return true;
05943                 else
05944                         result = result && r;
05945         }
05946         return result;
05947 }
05948 
05949 bool LLObjectSelection::applyToTEs(LLSelectedTEFunctor* func, bool firstonly)
05950 {
05951         bool result = firstonly ? false : true;
05952         for (iterator iter = begin(); iter != end(); )
05953         {
05954                 iterator nextiter = iter++;
05955                 LLSelectNode* node = *nextiter;
05956                 LLViewerObject* object = (*nextiter)->getObject();
05957                 if (!object)
05958                         continue;
05959                 S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces
05960                 for (S32 te = 0; te < num_tes; ++te)
05961                 {
05962                         if (node->isTESelected(te))
05963                         {
05964                                 bool r = func->apply(object, te);
05965                                 if (firstonly && r)
05966                                         return true;
05967                                 else
05968                                         result = result && r;
05969                         }
05970                 }
05971         }
05972         return result;
05973 }
05974 
05975 bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func, bool firstonly)
05976 {
05977         bool result = firstonly ? false : true;
05978         for (iterator iter = begin(); iter != end(); )
05979         {
05980                 iterator nextiter = iter++;
05981                 LLSelectNode* node = *nextiter;
05982                 bool r = func->apply(node);
05983                 if (firstonly && r)
05984                         return true;
05985                 else
05986                         result = result && r;
05987         }
05988         return result;
05989 }
05990 
05991 bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool firstonly)
05992 {
05993         bool result = firstonly ? false : true;
05994         for (root_iterator iter = root_begin(); iter != root_end(); )
05995         {
05996                 root_iterator nextiter = iter++;
05997                 LLSelectNode* node = *nextiter;
05998                 bool r = func->apply(node);
05999                 if (firstonly && r)
06000                         return true;
06001                 else
06002                         result = result && r;
06003         }
06004         return result;
06005 }
06006 
06007 //-----------------------------------------------------------------------------
06008 // contains()
06009 //-----------------------------------------------------------------------------
06010 BOOL LLObjectSelection::contains(LLViewerObject* object)
06011 {
06012         return findNode(object) != NULL;
06013 }
06014 
06015 
06016 //-----------------------------------------------------------------------------
06017 // contains()
06018 //-----------------------------------------------------------------------------
06019 BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te)
06020 {
06021         if (te == SELECT_ALL_TES)
06022         {
06023                 // ...all faces
06024                 for (LLObjectSelection::iterator iter = begin();
06025                          iter != end(); iter++)
06026                 {
06027                         LLSelectNode* nodep = *iter;
06028                         if (nodep->getObject() == object)
06029                         {
06030                                 BOOL all_selected = TRUE;
06031                                 for (S32 i = 0; i < SELECT_MAX_TES; i++)
06032                                 {
06033                                         all_selected = all_selected && nodep->isTESelected(i);
06034                                 }
06035                                 return all_selected;
06036                         }
06037                 }
06038                 return FALSE;
06039         }
06040         else
06041         {
06042                 // ...one face
06043                 for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++)
06044                 {
06045                         LLSelectNode* nodep = *iter;
06046                         if (nodep->getObject() == object && nodep->isTESelected(te))
06047                         {
06048                                 return TRUE;
06049                         }
06050                 }
06051                 return FALSE;
06052         }
06053 }
06054 
06055 // returns TRUE is any node is currenly worn as an attachment
06056 BOOL LLObjectSelection::isAttachment()
06057 {
06058         return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD);
06059 }
06060 
06061 //-----------------------------------------------------------------------------
06062 // getSelectedParentObject()
06063 //-----------------------------------------------------------------------------
06064 LLViewerObject* getSelectedParentObject(LLViewerObject *object)
06065 {
06066         LLViewerObject *parent;
06067         while (object && (parent = (LLViewerObject*)object->getParent()))
06068         {
06069                 if (parent->isSelected())
06070                 {
06071                         object = parent;
06072                 }
06073                 else
06074                 {
06075                         break;
06076                 }
06077         }
06078         return object;
06079 }
06080 
06081 //-----------------------------------------------------------------------------
06082 // getFirstNode
06083 //-----------------------------------------------------------------------------
06084 LLSelectNode* LLObjectSelection::getFirstNode(LLSelectedNodeFunctor* func)
06085 {
06086         for (iterator iter = begin(); iter != end(); ++iter)
06087         {
06088                 LLSelectNode* node = *iter;
06089                 if (func == NULL || func->apply(node))
06090                 {
06091                         return node;
06092                 }
06093         }
06094         return NULL;
06095 }
06096 
06097 LLSelectNode* LLObjectSelection::getFirstRootNode(LLSelectedNodeFunctor* func, BOOL non_root_ok)
06098 {
06099         for (root_iterator iter = root_begin(); iter != root_end(); ++iter)
06100         {
06101                 LLSelectNode* node = *iter;
06102                 if (func == NULL || func->apply(node))
06103                 {
06104                         return node;
06105                 }
06106         }
06107         if (non_root_ok)
06108         {
06109                 // Get non root
06110                 return getFirstNode(func);
06111         }
06112         return NULL;
06113 }
06114 
06115 
06116 //-----------------------------------------------------------------------------
06117 // getFirstSelectedObject
06118 //-----------------------------------------------------------------------------
06119 LLViewerObject* LLObjectSelection::getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent)
06120 {
06121         LLSelectNode* res = getFirstNode(func);
06122         if (res && get_parent)
06123         {
06124                 return getSelectedParentObject(res->getObject());
06125         }
06126         else if (res)
06127         {
06128                 return res->getObject();
06129         }
06130         return NULL;
06131 }
06132 
06133 //-----------------------------------------------------------------------------
06134 // getFirstObject()
06135 //-----------------------------------------------------------------------------
06136 LLViewerObject* LLObjectSelection::getFirstObject()
06137 {
06138         LLSelectNode* res = getFirstNode(NULL);
06139         return res ? res->getObject() : NULL;
06140 }
06141 
06142 //-----------------------------------------------------------------------------
06143 // getFirstRootObject()
06144 //-----------------------------------------------------------------------------
06145 LLViewerObject* LLObjectSelection::getFirstRootObject(BOOL non_root_ok)
06146 {
06147         LLSelectNode* res = getFirstRootNode(NULL, non_root_ok);
06148         return res ? res->getObject() : NULL;
06149 }
06150 
06151 //-----------------------------------------------------------------------------
06152 // getFirstMoveableNode()
06153 //-----------------------------------------------------------------------------
06154 LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first)
06155 {
06156         struct f : public LLSelectedNodeFunctor
06157         {
06158                 bool apply(LLSelectNode* node)
06159                 {
06160                         LLViewerObject* obj = node->getObject();
06161                         return obj && obj->permMove();
06162                 }
06163         } func;
06164         LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func);
06165         return res;
06166 }
06167 
06168 //-----------------------------------------------------------------------------
06169 // getFirstCopyableObject()
06170 //-----------------------------------------------------------------------------
06171 LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent)
06172 {
06173         struct f : public LLSelectedNodeFunctor
06174         {
06175                 bool apply(LLSelectNode* node)
06176                 {
06177                         LLViewerObject* obj = node->getObject();
06178                         return obj && obj->permCopy() && !obj->isAttachment();
06179                 }
06180         } func;
06181         return getFirstSelectedObject(&func, get_parent);
06182 }
06183 
06184 //-----------------------------------------------------------------------------
06185 // getFirstDeleteableObject()
06186 //-----------------------------------------------------------------------------
06187 LLViewerObject* LLObjectSelection::getFirstDeleteableObject()
06188 {
06189         //RN: don't currently support deletion of child objects, as that requires separating them first
06190         // then derezzing to trash
06191         
06192         struct f : public LLSelectedNodeFunctor
06193         {
06194                 bool apply(LLSelectNode* node)
06195                 {
06196                         LLViewerObject* obj = node->getObject();
06197                         // you can delete an object if you are the owner
06198                         // or you have permission to modify it.
06199                         if( obj && ( (obj->permModify()) ||
06200                                                  (obj->permYouOwner()) ||
06201                                                  (!obj->permAnyOwner()) ))              // public
06202                         {
06203                                 if( !obj->isAttachment() )
06204                                 {
06205                                         return true;
06206                                 }
06207                         }
06208                         return false;
06209                 }
06210         } func;
06211         LLSelectNode* node = getFirstNode(&func);
06212         return node ? node->getObject() : NULL;
06213 }
06214 
06215 //-----------------------------------------------------------------------------
06216 // getFirstEditableObject()
06217 //-----------------------------------------------------------------------------
06218 LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent)
06219 {
06220         struct f : public LLSelectedNodeFunctor
06221         {
06222                 bool apply(LLSelectNode* node)
06223                 {
06224                         LLViewerObject* obj = node->getObject();
06225                         return obj && obj->permModify();
06226                 }
06227         } func;
06228         return getFirstSelectedObject(&func, get_parent);
06229 }
06230 
06231 //-----------------------------------------------------------------------------
06232 // getFirstMoveableObject()
06233 //-----------------------------------------------------------------------------
06234 LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent)
06235 {
06236         struct f : public LLSelectedNodeFunctor
06237         {
06238                 bool apply(LLSelectNode* node)
06239                 {
06240                         LLViewerObject* obj = node->getObject();
06241                         return obj && obj->permMove();
06242                 }
06243         } func;
06244         return getFirstSelectedObject(&func, get_parent);
06245 }
06246 
06247 //-----------------------------------------------------------------------------
06248 // Position + Rotation update methods called from LLViewerJoystick
06249 //-----------------------------------------------------------------------------
06250 bool LLSelectMgr::selectionMove(const LLVector3& displ,
06251                                   F32 roll, F32 pitch, F32 yaw, U32 update_type)
06252 {
06253         if (update_type == UPD_NONE)
06254         {
06255                 return false;
06256         }
06257         
06258         LLVector3 displ_global;
06259         bool update_success = true;
06260         bool update_position = update_type & UPD_POSITION;
06261         bool update_rotation = update_type & UPD_ROTATION;
06262         const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts");
06263         
06264         if (update_position)
06265         {
06266                 // calculate the distance of the object closest to the camera origin
06267                 F32 min_dist = 1e+30f;
06268                 LLVector3 obj_pos;
06269                 for (LLObjectSelection::root_iterator it = getSelection()->root_begin();
06270                          it != getSelection()->root_end(); ++it)
06271                 {
06272                         obj_pos = (*it)->getObject()->getPositionEdit();
06273                         
06274                         F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin());
06275                         if (obj_dist < min_dist)
06276                         {
06277                                 min_dist = obj_dist;
06278                         }
06279                 }
06280                 
06281                 // factor the distance inside the displacement vector. This will get us
06282                 // equally visible movements for both close and far away selections.
06283                 min_dist = sqrt(min_dist) / 2;
06284                 displ_global.setVec(displ.mV[0]*min_dist, 
06285                                                         displ.mV[1]*min_dist, 
06286                                                         displ.mV[2]*min_dist);
06287 
06288                 // equates to: Displ_global = Displ * M_cam_axes_in_global_frame
06289                 displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global);
06290         }
06291 
06292         LLQuaternion new_rot;
06293         if (update_rotation)
06294         {
06295                 // let's calculate the rotation around each camera axes 
06296                 LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis());
06297                 LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis());
06298                 LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis());
06299                 new_rot.setQuat(qx * qy * qz);
06300         }
06301         
06302         LLViewerObject *obj;
06303         S32 obj_count = getSelection()->getObjectCount();
06304         for (LLObjectSelection::root_iterator it = getSelection()->root_begin();
06305                  it != getSelection()->root_end(); ++it )
06306         {
06307                 obj = (*it)->getObject();
06308                 bool enable_pos = false, enable_rot = false;
06309                 bool perm_move = obj->permMove();
06310                 bool perm_mod = obj->permModify();
06311                 
06312                 LLVector3d sel_center(getSelectionCenterGlobal());
06313                 
06314                 if (update_rotation)
06315                 {
06316                         enable_rot = perm_move 
06317                                 && ((perm_mod && !obj->isAttachment()) || noedit_linked_parts);
06318 
06319                         if (enable_rot)
06320                         {
06321                                 int children_count = obj->getChildren().size();
06322                                 if (obj_count > 1 && children_count > 0)
06323                                 {
06324                                         // for linked sets, rotate around the group center
06325                                         const LLVector3 t(obj->getPositionGlobal() - sel_center);
06326 
06327                                         // Ra = T x R x T^-1
06328                                         LLMatrix4 mt;   mt.setTranslation(t);
06329                                         const LLMatrix4 mnew_rot(new_rot);
06330                                         LLMatrix4 mt_1; mt_1.setTranslation(-t);
06331                                         mt *= mnew_rot;
06332                                         mt *= mt_1;
06333                                         
06334                                         // Rfin = Rcur * Ra
06335                                         obj->setRotation(obj->getRotationEdit() * mt.quaternion());
06336                                         displ_global += mt.getTranslation();
06337                                 }
06338                                 else
06339                                 {
06340                                         obj->setRotation(obj->getRotationEdit() * new_rot);
06341                                 }
06342                         }
06343                         else
06344                         {
06345                                 update_success = false;
06346                         }
06347                 }
06348 
06349                 if (update_position)
06350                 {
06351                         // establish if object can be moved or not
06352                         enable_pos = perm_move && !obj->isAttachment() 
06353                         && (perm_mod || noedit_linked_parts);
06354                         
06355                         if (enable_pos)
06356                         {
06357                                 obj->setPosition(obj->getPositionEdit() + displ_global);
06358                         }
06359                         else
06360                         {
06361                                 update_success = false;
06362                         }
06363                 }
06364                 
06365                 if (enable_pos && enable_rot && obj->mDrawable.notNull())
06366                 {
06367                         gPipeline.markMoved(obj->mDrawable, TRUE);
06368                 }
06369         }
06370         
06371         if (update_position && update_success && obj_count > 1)
06372         {
06373                 updateSelectionCenter();
06374         }
06375         
06376         return update_success;
06377 }
06378 
06379 void LLSelectMgr::sendSelectionMove()
06380 {
06381         LLSelectNode *node = mSelectedObjects->getFirstRootNode();
06382         if (node == NULL)
06383         {
06384                 return;
06385         }
06386         
06387         //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
06388         
06389         U32 update_type = UPD_POSITION | UPD_ROTATION;
06390         LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion();
06391         S32 objects_in_this_packet = 0;
06392 
06393         // apply to linked objects if unable to select their individual parts 
06394         if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode())
06395         {
06396                 // tell simulator to apply to whole linked sets
06397                 update_type |= UPD_LINKED_SETS;
06398         }
06399 
06400         // prepare first bulk message
06401         gMessageSystem->newMessage("MultipleObjectUpdate");
06402         packAgentAndSessionID(&update_type);
06403 
06404         LLViewerObject *obj = NULL;
06405         for (LLObjectSelection::root_iterator it = getSelection()->root_begin();
06406                  it != getSelection()->root_end(); ++it)
06407         {
06408                 obj = (*it)->getObject();
06409 
06410                 // note: following code adapted from sendListToRegions() (@3924)
06411                 last_region = curr_region;
06412                 curr_region = obj->getRegion();
06413 
06414                 // if not simulator or message too big
06415                 if (curr_region != last_region
06416                         || gMessageSystem->isSendFull(NULL)
06417                         || objects_in_this_packet >= MAX_OBJECTS_PER_PACKET)
06418                 {
06419                         // send sim the current message and start new one
06420                         gMessageSystem->sendReliable(last_region->getHost());
06421                         objects_in_this_packet = 0;
06422                         gMessageSystem->newMessage("MultipleObjectUpdate");
06423                         packAgentAndSessionID(&update_type);
06424                 }
06425 
06426                 // add another instance of the body of data
06427                 packMultipleUpdate(*it, &update_type);
06428                 ++objects_in_this_packet;
06429         }
06430 
06431         // flush remaining messages
06432         if (gMessageSystem->getCurrentSendTotal() > 0)
06433         {
06434                 gMessageSystem->sendReliable(curr_region->getHost());
06435         }
06436         else
06437         {
06438                 gMessageSystem->clearMessage();
06439         }
06440 
06441         //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
06442 }

Generated on Fri May 16 08:34:00 2008 for SecondLife by  doxygen 1.5.5