diff options
Diffstat (limited to 'indra/newview/llviewermenu.cpp')
| -rw-r--r-- | indra/newview/llviewermenu.cpp | 460 |
1 files changed, 445 insertions, 15 deletions
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 986d053574..86e3fe6eca 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -33,12 +33,14 @@ #include "llviewermenu.h" // linden library includes +#include "indra_constants.h" #include "llavatarnamecache.h" // IDEVO (I Are Not Men!) #include "llcombobox.h" #include "llcoros.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llinventorypanel.h" +#include "llsidepanelinventory.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llviewereventrecorder.h" @@ -52,6 +54,10 @@ #include "llagentui.h" #include "llagentwearables.h" #include "llagentpilot.h" +// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0 +#include "llattachmentsmgr.h" +// [/SL:KB] +#include "llavataractions.h" #include "llcompilequeue.h" #include "llconsole.h" #include "lldebugview.h" @@ -71,6 +77,7 @@ #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" +#include "llfloaterpreference.h" #include "llfloaterreporter.h" #include "llfloatersearch.h" #include "llfloaterscriptdebug.h" @@ -79,9 +86,8 @@ #include "llfloatertools.h" #include "llfloaterworldmap.h" #include "llfloaterbuildoptions.h" -#include "llavataractions.h" -#include "lllandmarkactions.h" #include "llgroupmgr.h" +#include "lllandmarkactions.h" #include "lltooltip.h" #include "lltoolface.h" #include "llhints.h" @@ -149,6 +155,7 @@ #include "llviewershadermgr.h" #include "gltfscenemanager.h" #include "gltf/asset.h" +#include "rlvcommon.h" using namespace LLAvatarAppearanceDefines; @@ -1004,17 +1011,36 @@ class LLAdvancedToggleFeature : public view_listener_t class LLAdvancedCheckFeature : public view_listener_t { bool handleEvent(const LLSD& userdata) -{ - U32 feature = feature_from_string( userdata.asString() ); - bool new_value = false; + { + U32 feature = feature_from_string( userdata.asString() ); + bool new_value = false; + + if ( feature != 0 ) + { + new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); + } + + return new_value; + } +}; - if ( feature != 0 ) +class LLAdvancedToggleExperiment : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) { - new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); + std::string feature = userdata.asString(); + return false; } +}; - return new_value; -} +class LLAdvancedCheckExperiment : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + bool value = false; + std::string feature = userdata.asString(); + return value; + } }; class LLAdvancedCheckDisplayTextureDensity : public view_listener_t @@ -2232,6 +2258,13 @@ class LLAdvancedRebakeTextures : public view_listener_t }; +// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0 +void handle_refresh_attachments() +{ + LLAttachmentsMgr::instance().refreshAttachments(); +} +// [/SL:KB] + #if 1 //ndef LL_RELEASE_FOR_DOWNLOAD /////////////////////////// // DEBUG AVATAR TEXTURES // @@ -3397,6 +3430,161 @@ bool enable_attachment_touch(const LLUUID& inv_item_id) return false; } +static void copy_text_to_clipboard(const std::string& text) +{ + if (text.empty() || !gViewerWindow || !gViewerWindow->getWindow()) + { + return; + } + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(text)); +} + +static LLViewerObject* selected_pick_object() +{ + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + return selection ? selection->getPrimaryObject() : nullptr; +} + +// Root first, then each non-avatar child in child-list order. That is the +// same order the viewer uses for link numbers (root is link 1). +static void collect_linkset_objects(LLViewerObject* object, std::vector<LLViewerObject*>& links) +{ + links.clear(); + if (!object || object->isAvatar()) + { + return; + } + LLViewerObject* root = object->getRootEdit(); + if (!root || root->isAvatar()) + { + return; + } + root->addThisAndNonJointChildren(links); +} + +static bool object_is_linkset() +{ + std::vector<LLViewerObject*> links; + collect_linkset_objects(selected_pick_object(), links); + return links.size() > 1; +} + +static void handle_object_copy_uuid() +{ + LLViewerObject* object = selected_pick_object(); + if (!object || object->isAvatar()) + { + return; + } + copy_text_to_clipboard(object->getID().asString()); +} + +static void handle_object_copy_linkset_uuids() +{ + std::vector<LLViewerObject*> links; + collect_linkset_objects(selected_pick_object(), links); + if (links.size() < 2) + { + return; + } + + std::string text; + for (LLViewerObject* link : links) + { + if (!link) + { + continue; + } + if (!text.empty()) + { + text += ", "; + } + text += link->getID().asString(); + } + copy_text_to_clipboard(text); +} + +static void append_unique_selected_object(std::vector<LLViewerObject*>& objects, LLViewerObject* object) +{ + if (!object || object->isAvatar()) + { + return; + } + for (LLViewerObject* existing : objects) + { + if (existing == object) + { + return; + } + } + objects.push_back(object); +} + +// Family roots cover shift-selected objects. Individual nodes cover +// Edit Linked Parts, where each prim is selected on its own. +static void collect_multi_selected_objects(std::vector<LLViewerObject*>& objects) +{ + objects.clear(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (!selection) + { + return; + } + + for (LLObjectSelection::root_iterator it = selection->root_begin(); it != selection->root_end(); ++it) + { + append_unique_selected_object(objects, (*it)->getObject()); + } + for (LLObjectSelection::iterator it = selection->begin(); it != selection->end(); ++it) + { + LLSelectNode* node = *it; + if (!node || !node->mIndividualSelection) + { + continue; + } + append_unique_selected_object(objects, node->getObject()); + } +} + +static bool selection_has_multiple_objects() +{ + std::vector<LLViewerObject*> objects; + collect_multi_selected_objects(objects); + return objects.size() > 1; +} + +static void handle_object_copy_selected_uuids() +{ + std::vector<LLViewerObject*> objects; + collect_multi_selected_objects(objects); + if (objects.size() < 2) + { + return; + } + + std::string text; + for (LLViewerObject* object : objects) + { + if (!text.empty()) + { + text += ", "; + } + text += object->getID().asString(); + } + copy_text_to_clipboard(text); +} + +static void handle_avatar_copy_uuid() +{ + LLUUID id = gAgent.getID(); + LLViewerObject* object = selected_pick_object(); + if (object && object->isAvatar()) + { + id = object->getID(); + } + copy_text_to_clipboard(id.asString()); +} + void handle_object_inspect() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); @@ -4054,6 +4242,44 @@ void handle_avatar_eject(const LLSD& avatar_id) } } +void handle_avatar_estate_kick(const LLSD& avatar_id) +{ + LLUUID id = avatar_id.asUUID(); + if (id.isNull()) + { + LLVOAvatar* avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) id = avatar->getID(); + } + if (id.notNull()) + { + LLAvatarActions::estateKickAvatar(id); + } +} + +void handle_avatar_estate_ban(const LLSD& avatar_id) +{ + LLUUID id = avatar_id.asUUID(); + if (id.isNull()) + { + LLVOAvatar* avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) id = avatar->getID(); + } + if (id.notNull()) + { + LLAvatarActions::estateBanAvatar(id); + } +} + +bool enable_estate_eject_ban(const LLSD& avatar_id) +{ + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return false; + if (gAgent.isGodlike()) return true; + return region->getOwner() == gAgent.getID() || region->isEstateManager(); +} + bool enable_freeze_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar @@ -4613,7 +4839,7 @@ void handle_object_sit(LLViewerObject* object, const LLVector3& offset) { // get object selection offset - if (object && object->getPCode() == LL_PCODE_VOLUME) + if (gAgent.isAllowedToSit() && object && object->getPCode() == LL_PCODE_VOLUME) { gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); @@ -4658,6 +4884,51 @@ void handle_object_sit(const LLUUID& object_id) handle_object_sit(obj, offset); } +// Looks for the nearest sittable object -- one whose click-action is set to +// CLICK_ACTION_SIT, the flag content creators set (usually alongside a custom +// llSetSitText() label) to mark a prim as a seat -- within a hard-coded +// multiple of the avatar's height. Used by the game-control "toggle sit" +// action to find something to sit on before falling back to sitting on the +// ground. Returns NULL if nothing qualifies. +LLViewerObject* find_nearby_seat() +{ + if (!isAgentAvatarValid()) + { + return NULL; + } + + constexpr F32 SEAT_SEARCH_RANGE_HEIGHTS = 2.f; + const F32 max_dist = SEAT_SEARCH_RANGE_HEIGHTS * gAgentAvatarp->mBodySize.mV[VZ]; + const LLVector3 agent_pos = gAgentAvatarp->getPositionAgent(); + + LLViewerObject* nearest_seat = NULL; + F32 nearest_dist_squared = max_dist * max_dist; + + S32 num_objects = gObjectList.getNumObjects(); + for (S32 i = 0; i < num_objects; ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (!object || object->isDead() || object->isAttachment()) + { + continue; + } + + if (object->getPCode() != LL_PCODE_VOLUME || object->getClickAction() != CLICK_ACTION_SIT) + { + continue; + } + + F32 dist_squared = dist_vec_squared(agent_pos, object->getPositionAgent()); + if (dist_squared <= nearest_dist_squared) + { + nearest_seat = object; + nearest_dist_squared = dist_squared; + } + } + + return nearest_seat; +} + void near_sit_down_point(bool success, void*) { if (success) @@ -4756,12 +5027,37 @@ class LLViewMouselook : public view_listener_t { bool handleEvent(const LLSD& userdata) { + // When OTS is enabled M toggles OTS mode (shoulder cam). + // When disabled M toggles normal first-person mouselook. + if (gSavedSettings.getBOOL("OTSEnabled")) + { + if (!gAgentCamera.cameraOTS()) + { + gAgentCamera.changeCameraToOTS(); + } + else + { + gAgentCamera.changeCameraFromOTS(); + } + return true; + } + if (!gAgentCamera.cameraMouselook()) { gAgentCamera.changeCameraToMouselook(); } else { + // NaCl: restore FOV on mouselook exit + LLVector3 mlFovValues = gSavedSettings.getVector3("_NACL_MLFovValues"); + F32 cameraAngle = gSavedSettings.getF32("CameraAngle"); + if (mlFovValues.mV[VZ] > 0.0f) + { + mlFovValues.mV[VY] = cameraAngle; + mlFovValues.mV[VZ] = 0.0f; + gSavedSettings.setVector3("_NACL_MLFovValues", mlFovValues); + gSavedSettings.setF32("CameraAngle", mlFovValues.mV[VX]); + } gAgentCamera.changeCameraToDefault(); } return true; @@ -6519,6 +6815,8 @@ void show_debug_menus() gMenuBarView->setItemVisible("Advanced", debug); // gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden + Rlv::Util::menuToggleVisible(); + gMenuBarView->setItemVisible("Debug", qamode); gMenuBarView->setItemEnabled("Debug", qamode); @@ -6750,6 +7048,26 @@ bool handle_zoom_to_object(const LLUUID& object_id) return false; } +void handle_teleport_to_object(LLUUID object_id) +{ + LLViewerObject* object = gObjectList.findObject(object_id); + + if (object) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox bbox = object->getBoundingBoxAgent() ; + + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); + obj_to_cam.normVec(); + + + LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); + + gAgent.teleportViaLocation(object_center_global); + } +} + class LLAvatarInviteToGroup : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -6852,6 +7170,35 @@ class LLAvatarToggleSearch : public view_listener_t } }; +// <FS:CR> Resync Animations +class FSToolsResyncAnimations : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + for (S32 i = 0; i < gObjectList.getNumObjects(); i++) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && + object->isAvatar()) + { + LLVOAvatar* avatarp = (LLVOAvatar*)object; + if (avatarp) + { + for (LLVOAvatar::AnimIterator anim_it = avatarp->mPlayingAnimations.begin(); + anim_it != avatarp->mPlayingAnimations.end(); + anim_it++) + { + avatarp->stopMotion(anim_it->first, true); + avatarp->startMotion(anim_it->first); + } + } + } + } + return true; + } +}; +// </FS:CR> Resync Animations + class LLAvatarResetSkeleton : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -6867,8 +7214,8 @@ class LLAvatarResetSkeleton : public view_listener_t } else { - avatar->resetSkeleton(false); - } + avatar->resetSkeleton(false); + } } return true; } @@ -6933,9 +7280,9 @@ class LLAvatarResetSelfSkeletonAndAnimations : public view_listener_t effectp->setSourceObject(gAgentAvatarp); effectp->setTargetObject((LLViewerObject*)avatar); effectp->setResetAnimations(true); - } - else - { + } + else + { avatar->resetSkeleton(true); } } @@ -7015,6 +7362,59 @@ void handle_give_money_dialog() } } +LLFloaterSidePanelContainer* get_favorite_inventory_folder() +{ + LLUUID folder_id = LLUUID(gSavedPerAccountSettings.getString("FavoriteFolder")); + if (!folder_id.isNull()) + { + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) + { + LLFloaterSidePanelContainer* inventory_container = dynamic_cast<LLFloaterSidePanelContainer*>(*iter++); + if (inventory_container) + { + LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(inventory_container->findChild<LLPanel>("main_panel", true)); + if (sidepanel_inventory) + { + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory && main_inventory->isSingleFolderMode() + && (main_inventory->getCurrentSFVRoot() == folder_id)) + { + return inventory_container; + } + } + } + } + } + + return NULL; +} + +void toggle_favorite_inventory_folder() +{ + LLUUID folder_id = LLUUID(gSavedPerAccountSettings.getString("FavoriteFolder")); + if ((folder_id.isNull()) || (!gInventory.getCategory(folder_id))) + { + LLNotificationsUtil::add("MissingFavoriteFolder"); + return; + } + + LLFloaterSidePanelContainer* inventory_container = get_favorite_inventory_folder(); + if (inventory_container) + { + inventory_container->closeFloater(); + } + else + { + LLPanelMainInventory::newFolderWindow(folder_id); + } +} + +bool favorite_inventory_folder_visible() +{ + return (get_favorite_inventory_folder() != NULL); +} + bool enable_pay_avatar() { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); @@ -7123,6 +7523,13 @@ void handle_hover_height() LLFloaterReg::showInstance("edit_hover_height"); } +// Firestorm port: Quick Preferences floater (hover height, bandwidth) +void handle_quick_prefs() +{ + LLFloaterReg::toggleInstance("quick_prefs"); +} +// End Firestorm port + void handle_edit_physics() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics")); @@ -7862,6 +8269,7 @@ bool enable_detach(const LLSD&) // Only enable detach if all faces of object are selected if (!object || !object->isAttachment() || + object->isLocked() || !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) { return false; @@ -9997,6 +10405,9 @@ void initialize_menus() commit.add("EditShape", boost::bind(&handle_edit_shape)); commit.add("HoverHeight", boost::bind(&handle_hover_height)); commit.add("EditPhysics", boost::bind(&handle_edit_physics)); + commit.add("QuickPrefs", boost::bind(&handle_quick_prefs)); // Firestorm port + commit.add("ToggleAnimationOverride", boost::bind(&LLVOAvatar::toggleAnimationOverride)); + enable.add("AreAnimationsOverridden", boost::bind(&LLVOAvatar::areAnimationsOverridden)); // View menu view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook"); @@ -10120,6 +10531,9 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); + view_listener_t::addMenu(new LLAdvancedToggleExperiment(), "Advanced.ToggleExperiment"); + view_listener_t::addMenu(new LLAdvancedCheckExperiment(), "Advanced.CheckExperiment"); + view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); @@ -10238,6 +10652,9 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures"); +// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0 + commit.add("Advanced.RefreshAttachments", boost::bind(&handle_refresh_attachments)); +// [/SL:KB] view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); // Advanced > Network @@ -10337,6 +10754,9 @@ void initialize_menus() view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD())); + commit.add("Avatar.EstateKick", boost::bind(&handle_avatar_estate_kick, _2)); + commit.add("Avatar.EstateBan", boost::bind(&handle_avatar_estate_ban, _2)); + enable.add("Avatar.EnableEstateEjectBan", boost::bind(&enable_estate_eject_ban, _2)); commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector)); view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM"); view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call"); @@ -10345,6 +10765,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks"); view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch"); + view_listener_t::addMenu(new FSToolsResyncAnimations(), "Tools.ResyncAnimations"); // <FS:CR> Resync Animations view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton"); view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); @@ -10380,6 +10801,12 @@ void initialize_menus() commit.add("Object.Edit", boost::bind(&handle_object_edit)); commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material)); commit.add("Object.Inspect", boost::bind(&handle_object_inspect)); + commit.add("Object.CopyUUID", boost::bind(&handle_object_copy_uuid)); + commit.add("Object.CopyLinksetUUIDs", boost::bind(&handle_object_copy_linkset_uuids)); + enable.add("Object.VisibleCopyLinksetUUIDs", boost::bind(&object_is_linkset)); + commit.add("Object.CopySelectedUUIDs", boost::bind(&handle_object_copy_selected_uuids)); + enable.add("Object.VisibleCopySelectedUUIDs", boost::bind(&selection_has_multiple_objects)); + commit.add("Avatar.CopyUUID", boost::bind(&handle_avatar_copy_uuid)); commit.add("Object.Open", boost::bind(&handle_object_open)); commit.add("Object.Take", boost::bind(&handle_take, false)); commit.add("Object.TakeSeparate", boost::bind(&handle_take, true)); @@ -10446,6 +10873,9 @@ void initialize_menus() commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow)); + commit.add("Inventory.OpenFavoriteFolder", boost::bind(&toggle_favorite_inventory_folder)); + enable.add("Inventory.IsFavoriteFolderOpen", boost::bind(&favorite_inventory_folder_visible)); + enable.add("EnablePayObject", boost::bind(&enable_pay_object)); enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); enable.add("EnableEdit", boost::bind(&enable_object_edit)); |
