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

Generated on Thu Jul 1 06:09:10 2010 for Second Life Viewer by  doxygen 1.4.7