/** * @file llviewermenu.cpp * @brief Builds menus out of items. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2014, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #ifdef INCLUDE_VLD #include "vld.h" #endif #include "llviewermenu.h" // linden library includes #include "llavatarnamecache.h" // IDEVO (I Are Not Men!) #include "llcombobox.h" #include "llcoros.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llviewereventrecorder.h" #include "v4coloru.h" // newview includes #include "llagent.h" #include "llagentaccess.h" #include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentui.h" #include "llagentwearables.h" #include "llagentpilot.h" #include "llavataractions.h" #include "llcompilequeue.h" #include "llconsole.h" #include "lldebugview.h" #include "lldiskcache.h" #include "llenvironment.h" #include "llfilepicker.h" #include "llfirstuse.h" #include "llfloaterabout.h" #include "llfloaterbuy.h" #include "llfloaterbuycontents.h" #include "llbuycurrencyhtml.h" #include "llfloatergodtools.h" #include "llfloaterimcontainer.h" #include "llfloaterland.h" #include "llfloaterimnearbychat.h" #include "llfloaterlandholdings.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" #include "llfloaterpreference.h" #include "llfloaterreporter.h" #include "llfloatersearch.h" #include "llfloaterscriptdebug.h" #include "llfloatersnapshot.h" #include "llfloatertools.h" #include "llfloaterworldmap.h" #include "llfloaterbuildoptions.h" #include "fsyspath.h" #include "llgamecontrol.h" #include "llgroupmgr.h" #include "lllandmarkactions.h" #include "lltooltip.h" #include "lltoolface.h" #include "llhints.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llimview.h" #include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" #include "llluamanager.h" #include "llpanellogin.h" #include "llpanelblockedlist.h" #include "llpanelmaininventory.h" #include "llmarketplacefunctions.h" #include "llmaterialeditor.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" #include "llnavigationbar.h" #include "llparcel.h" #include "llrootview.h" #include "llsceneview.h" #include "llscenemonitor.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" #include "llspellcheckmenuhandler.h" #include "llstatusbar.h" #include "llterrainpaintmap.h" #include "lltextureview.h" #include "lltoolbarview.h" #include "lltoolcomp.h" #include "lltoolmgr.h" #include "lltoolpie.h" #include "lltoolselectland.h" #include "llterrainpaintmap.h" #include "lltrans.h" #include "llviewerdisplay.h" //for gWindowResized #include "llviewergenericmessage.h" #include "llviewerhelp.h" #include "llviewermenufile.h" // init_menu_file() #include "llviewermessage.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" #include "llvlcomposition.h" #include "llvoavatarself.h" #include "llvoicevivox.h" #include "llworld.h" #include "llworldmap.h" #include "pipeline.h" #include "llviewerjoystick.h" #include "llfloatercamera.h" #include "lluilistener.h" #include "llappearancemgr.h" #include "lltrans.h" #include "lltoolgrab.h" #include "llwindow.h" #include "llpathfindingmanager.h" #include "llstartup.h" #include "boost/unordered_map.hpp" #include #include #include #include "llcleanup.h" #include "llviewershadermgr.h" #include "gltfscenemanager.h" #include "gltf/asset.h" #include "rlvcommon.h" using namespace LLAvatarAppearanceDefines; typedef LLPointer LLViewerObjectPtr; static boost::unordered_map sDefaultItemLabels; LLVOAvatar* find_avatar_from_object(LLViewerObject* object); LLVOAvatar* find_avatar_from_object(const LLUUID& object_id); void handle_test_load_url(); // // Evil hackish imported globals extern bool gDebugClicks; extern bool gDebugWindowProc; extern bool gShaderProfileFrame; // // Globals // LLUIListener sUIListener; LLMenuBarGL *gMenuBarView = NULL; LLViewerMenuHolderGL *gMenuHolder = NULL; LLMenuGL *gPopupMenuView = NULL; LLMenuGL *gEditMenu = NULL; LLMenuBarGL *gLoginMenuBarView = NULL; // Pie menus LLContextMenu *gMenuAvatarSelf = NULL; LLContextMenu *gMenuAvatarOther = NULL; LLContextMenu *gMenuObject = NULL; LLContextMenu *gMenuAttachmentSelf = NULL; LLContextMenu *gMenuAttachmentOther = NULL; LLContextMenu *gMenuLand = NULL; LLContextMenu *gMenuMuteParticle = NULL; const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"); LLMenuGL* gAttachSubMenu = NULL; LLMenuGL* gDetachSubMenu = NULL; LLMenuGL* gTakeOffClothes = NULL; LLMenuGL* gDetachAvatarMenu = NULL; LLMenuGL* gDetachHUDAvatarMenu = NULL; LLContextMenu* gAttachScreenPieMenu = NULL; LLContextMenu* gAttachPieMenu = NULL; LLContextMenu* gAttachBodyPartPieMenus[9]; LLContextMenu* gDetachPieMenu = NULL; LLContextMenu* gDetachScreenPieMenu = NULL; LLContextMenu* gDetachAttSelfMenu = NULL; LLContextMenu* gDetachHUDAttSelfMenu = NULL; LLContextMenu* gDetachBodyPartPieMenus[9]; // // Local prototypes // File Menu void handle_compress_image(); void handle_compress_file_test(); // Edit menu void handle_dump_group_info(); void handle_dump_capabilities_info(); // Advanced->Consoles menu void handle_region_dump_settings(); void handle_region_dump_temp_asset_data(); void handle_region_clear_temp_asset_data(); // Object pie menu bool sitting_on_selection(); // buy and take alias into the same UI positions, so these // declarations handle this mess. bool is_selection_buy_not_take(); S32 selection_price(); bool enable_take(); void handle_object_show_inspector(); void handle_avatar_show_inspector(); bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle); bool confirm_take_separate(const LLSD ¬ification, const LLSD &response, LLObjectSelectionHandle selection_handle); void handle_buy_object(LLSaleInfo sale_info); void handle_buy_contents(LLSaleInfo sale_info); // Land pie menu void near_sit_down_point(bool success, void*); // Debug menu void handle_visual_leak_detector_toggle(); void handle_rebake_textures(); bool check_admin_override(); void handle_admin_override_toggle(); #ifdef TOGGLE_HACKED_GODLIKE_VIEWER void handle_toggle_hacked_godmode(); bool check_toggle_hacked_godmode(); bool enable_toggle_hacked_godmode(); #endif void toggle_show_xui_names(); bool check_show_xui_names(); // Debug UI void handle_buy_currency_test(); void handle_god_mode(); // God menu void handle_leave_god_mode(); void handle_reset_view(); void handle_object_owner_self(); void handle_object_owner_permissive(); void handle_object_lock(); void handle_object_asset_ids(); void force_take_copy(); void handle_force_parcel_owner_to_me(); void handle_force_parcel_to_content(); void handle_claim_public_land(); void handle_god_request_avatar_geometry(); // Hack for easy testing of new avatar geometry void reload_vertex_shader(); void handle_disconnect_viewer(); void force_error_breakpoint(); void force_error_llerror(); void force_error_llerror_msg(); void force_error_bad_memory_access(); void force_error_infinite_loop(); void force_error_software_exception(); void force_error_os_exception(); void force_error_driver_crash(); void force_error_coroutine_crash(); void force_error_thread_crash(); void handle_force_delete(); void print_object_info(); void print_agent_nvpairs(); void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status); void dump_select_mgr(); void dump_inventory(); void toggle_visibility(LLView* viewp); bool get_visibility(LLView* viewp); // Avatar Pie menu void request_friendship(const LLUUID& agent_id); // Tools menu void handle_selected_texture_info(); void handle_selected_material_info(); void handle_dump_followcam(); void handle_viewer_enable_message_log(); void handle_viewer_disable_message_log(); bool enable_buy_land(); // Help menu void handle_test_male(); void handle_test_female(); void handle_dump_attachments(); void handle_dump_avatar_local_textures(); void handle_debug_avatar_textures(); void handle_grab_baked_texture(EBakedTextureIndex baked_tex_index); bool enable_grab_baked_texture(EBakedTextureIndex baked_tex_index); void handle_dump_region_object_cache(); void handle_reset_interest_lists(); bool enable_save_into_task_inventory(); bool enable_detach(const LLSD& = LLSD()); void menu_toggle_attached_lights(); void menu_toggle_attached_particles(); class LLMenuParcelObserver : public LLParcelObserver { public: LLMenuParcelObserver(); ~LLMenuParcelObserver(); void changed() override; private: LLHandle mLandBuyHandle; LLHandle mLandBuyPassHandle; }; static LLMenuParcelObserver* gMenuParcelObserver = NULL; LLMenuParcelObserver::LLMenuParcelObserver() { mLandBuyHandle = gMenuLand->getChild("Land Buy")->getHandle(); mLandBuyPassHandle = gMenuLand->getChild("Land Buy Pass")->getHandle(); LLViewerParcelMgr::getInstance()->addObserver(this); } LLMenuParcelObserver::~LLMenuParcelObserver() { LLViewerParcelMgr::getInstance()->removeObserver(this); } void LLMenuParcelObserver::changed() { LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(); if (gMenuLand && parcel) { if (!mLandBuyPassHandle.isDead()) { LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(); static_cast(mLandBuyPassHandle.get())->setEnabled(LLPanelLandGeneral::enableBuyPass(nullptr) && parcel->getOwnerID() != gAgentID); } if (!mLandBuyHandle.isDead()) { bool buyable = enable_buy_land(); static_cast(mLandBuyHandle.get())->setEnabled(buyable); } } } void initialize_menus(); //----------------------------------------------------------------------------- // Initialize main menus // // HOW TO NAME MENUS: // // First Letter Of Each Word Is Capitalized, Even At Or And // // Items that lead to dialog boxes end in "..." // // Break up groups of more than 6 items with separators //----------------------------------------------------------------------------- void set_merchant_SLM_menu(); class LLSLMMenuUpdater { public: LLSLMMenuUpdater(); ~LLSLMMenuUpdater() = default; void setMerchantMenu(); void checkMerchantStatus(bool force); private: LLHandle mMarketplaceListingsItem; }; static LLSLMMenuUpdater* gSLMMenuUpdater = NULL; LLSLMMenuUpdater::LLSLMMenuUpdater() { mMarketplaceListingsItem = gMenuHolder->getChild("MarketplaceListings")->getHandle(); } void LLSLMMenuUpdater::setMerchantMenu() { // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool if(!mMarketplaceListingsItem.isDead()) { mMarketplaceListingsItem.get()->setVisible(true); } LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); gToolBarView->enableCommand(command->id(), true); const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplacelistings_id.isNull()) { U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); bool is_merchant = mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT || mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT; if (is_merchant) { gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MARKETPLACE_LISTINGS); LL_WARNS("SLM") << "Creating the marketplace listings folder for a merchant" << LL_ENDL; } } } void LLSLMMenuUpdater::checkMerchantStatus(bool force) { if (force) { // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); } // Hide SLM related menu item if(!mMarketplaceListingsItem.isDead()) { mMarketplaceListingsItem.get()->setVisible(false); } // Also disable the toolbar button for Marketplace Listings LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); gToolBarView->enableCommand(command->id(), false); // Launch an SLM test connection to get the merchant status LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu)); } void set_merchant_SLM_menu() { if (gSLMMenuUpdater) gSLMMenuUpdater->setMerchantMenu(); } void check_merchant_status(bool force) { if (gSLMMenuUpdater) gSLMMenuUpdater->checkMerchantStatus(force); } void init_menus() { // Initialize actions initialize_menus(); /// /// Popup menu /// /// The popup menu is now populated by the show_context_menu() /// method. LLMenuGL::Params menu_params; menu_params.name = "Popup"; menu_params.visible = false; gPopupMenuView = LLUICtrlFactory::create(menu_params); gMenuHolder->addChild( gPopupMenuView ); /// /// Context menus /// const widget_registry_t& registry = LLViewerMenuHolderGL::child_registry_t::instance(); gEditMenu = LLUICtrlFactory::createFromFile("menu_edit.xml", gMenuHolder, registry); gMenuAvatarSelf = LLUICtrlFactory::createFromFile( "menu_avatar_self.xml", gMenuHolder, registry); gMenuAvatarOther = LLUICtrlFactory::createFromFile( "menu_avatar_other.xml", gMenuHolder, registry); gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); gMenuObject = LLUICtrlFactory::createFromFile( "menu_object.xml", gMenuHolder, registry); gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); gAttachPieMenu = gMenuHolder->getChild("Object Attach"); gMenuAttachmentSelf = LLUICtrlFactory::createFromFile( "menu_attachment_self.xml", gMenuHolder, registry); gMenuAttachmentOther = LLUICtrlFactory::createFromFile( "menu_attachment_other.xml", gMenuHolder, registry); gDetachHUDAttSelfMenu = gMenuHolder->getChild("Detach Self HUD", true); gDetachAttSelfMenu = gMenuHolder->getChild("Detach Self", true); gMenuLand = LLUICtrlFactory::createFromFile( "menu_land.xml", gMenuHolder, registry); gMenuMuteParticle = LLUICtrlFactory::createFromFile( "menu_mute_particle.xml", gMenuHolder, registry); /// /// set up the colors /// LLUIColor context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor"); gMenuAvatarSelf->setBackgroundColor( context_menu_color ); gMenuAvatarOther->setBackgroundColor( context_menu_color ); gMenuObject->setBackgroundColor( context_menu_color ); gMenuAttachmentSelf->setBackgroundColor( context_menu_color ); gMenuAttachmentOther->setBackgroundColor( context_menu_color ); gMenuLand->setBackgroundColor( context_menu_color ); LLUIColor color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" ); gPopupMenuView->setBackgroundColor( color ); // If we are not in production, use a different color to make it apparent. if (LLGridManager::getInstance()->isInProductionGrid()) { color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); } else { color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT)); gMenuBarView->setBackgroundColor( color ); menu_bar_holder->addChild(gMenuBarView); gViewerWindow->setMenuBackgroundColor(false, LLGridManager::getInstance()->isInProductionGrid()); // *TODO:Also fix cost in llfolderview.cpp for Inventory menus const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", true); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", true); gDetachAvatarMenu = gMenuHolder->getChild("Avatar Detach", true); gDetachHUDAvatarMenu = gMenuHolder->getChild("Avatar Detach HUD", true); // Don't display the Memory console menu if the feature is turned off LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild("Memory", true); if (memoryMenu) { memoryMenu->setVisible(false); } gMenuBarView->createJumpKeys(); // Let land based option enable when parcel changes gMenuParcelObserver = new LLMenuParcelObserver(); gSLMMenuUpdater = new LLSLMMenuUpdater(); gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gLoginMenuBarView->arrangeAndClear(); LLRect menuBarRect = gLoginMenuBarView->getRect(); menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight()); gLoginMenuBarView->setRect(menuBarRect); gLoginMenuBarView->setBackgroundColor( color ); menu_bar_holder->addChild(gLoginMenuBarView); // tooltips are on top of EVERYTHING, including menus gViewerWindow->getRootView()->sendChildToFront(gToolTipView); } /////////////////// // SHOW CONSOLES // /////////////////// class LLAdvancedToggleConsole : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string console_type = userdata.asString(); if ("texture" == console_type) { toggle_visibility(gTextureView); } else if ("debug" == console_type) { toggle_visibility(gDebugView->mDebugConsolep); } else if ("fast timers" == console_type) { LLFloaterReg::toggleInstance("block_timers"); } else if ("scene view" == console_type) { toggle_visibility(gSceneView); } else if ("scene monitor" == console_type) { toggle_visibility(gSceneMonitorView); } return true; } }; class LLAdvancedCheckConsole : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string console_type = userdata.asString(); bool new_value = false; if ("texture" == console_type) { new_value = get_visibility(gTextureView); } else if ("debug" == console_type) { new_value = get_visibility(gDebugView->mDebugConsolep); } else if ("fast timers" == console_type) { new_value = LLFloaterReg::instanceVisible("block_timers"); } else if ("scene view" == console_type) { new_value = get_visibility(gSceneView); } else if ("scene monitor" == console_type) { new_value = get_visibility(gSceneMonitorView); } return new_value; } }; ////////////////////////// // DUMP INFO TO CONSOLE // ////////////////////////// class LLAdvancedDumpInfoToConsole : public view_listener_t { bool handleEvent(const LLSD& userdata) { gDebugView->mDebugConsolep->setVisible(true); std::string info_type = userdata.asString(); if ("region" == info_type) { handle_region_dump_settings(); } else if ("group" == info_type) { handle_dump_group_info(); } else if ("capabilities" == info_type) { handle_dump_capabilities_info(); } return true; } }; ////////////// // HUD INFO // ////////////// class LLAdvancedToggleHUDInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string info_type = userdata.asString(); if ("camera" == info_type) { gDisplayCameraPos = !(gDisplayCameraPos); } else if ("wind" == info_type) { gDisplayWindInfo = !(gDisplayWindInfo); } else if ("fov" == info_type) { gDisplayFOV = !(gDisplayFOV); } else if ("badge" == info_type) { gDisplayBadge = !(gDisplayBadge); } return true; } }; class LLAdvancedCheckHUDInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string info_type = userdata.asString(); bool new_value = false; if ("camera" == info_type) { new_value = gDisplayCameraPos; } else if ("wind" == info_type) { new_value = gDisplayWindInfo; } else if ("fov" == info_type) { new_value = gDisplayFOV; } else if ("badge" == info_type) { new_value = gDisplayBadge; } return new_value; } }; /////////////////////// // CLEAR GROUP CACHE // /////////////////////// class LLAdvancedClearGroupCache : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLGroupMgr::debugClearAllGroups(nullptr); return true; } }; ///////////////// // RENDER TYPE // ///////////////// U32 render_type_from_string(std::string_view render_type) { if ("simple" == render_type) { return LLPipeline::RENDER_TYPE_SIMPLE; } if ("materials" == render_type) { return LLPipeline::RENDER_TYPE_MATERIALS; } else if ("alpha" == render_type) { return LLPipeline::RENDER_TYPE_ALPHA; } else if ("alpha_mask" == render_type) { return LLPipeline::RENDER_TYPE_ALPHA_MASK; } else if ("fullbright_alpha_mask" == render_type) { return LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK; } else if ("fullbright" == render_type) { return LLPipeline::RENDER_TYPE_FULLBRIGHT; } else if ("glow" == render_type) { return LLPipeline::RENDER_TYPE_GLOW; } else if ("tree" == render_type) { return LLPipeline::RENDER_TYPE_TREE; } else if ("character" == render_type) { return LLPipeline::RENDER_TYPE_AVATAR; } else if ("controlAV" == render_type) // Animesh { return LLPipeline::RENDER_TYPE_CONTROL_AV; } else if ("surfacePatch" == render_type) { return LLPipeline::RENDER_TYPE_TERRAIN; } else if ("sky" == render_type) { return LLPipeline::RENDER_TYPE_SKY; } else if ("water" == render_type) { return LLPipeline::RENDER_TYPE_WATER; } else if ("volume" == render_type) { return LLPipeline::RENDER_TYPE_VOLUME; } else if ("grass" == render_type) { return LLPipeline::RENDER_TYPE_GRASS; } else if ("clouds" == render_type) { return LLPipeline::RENDER_TYPE_CLOUDS; } else if ("particles" == render_type) { return LLPipeline::RENDER_TYPE_PARTICLES; } else if ("bump" == render_type) { return LLPipeline::RENDER_TYPE_BUMP; } else if ("pbr" == render_type) { return LLPipeline::RENDER_TYPE_GLTF_PBR; } else { return 0; } } class LLAdvancedToggleRenderType : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 render_type = render_type_from_string( userdata.asString() ); if ( render_type != 0 ) { LLPipeline::toggleRenderTypeControl( render_type ); } return true; } }; class LLAdvancedCheckRenderType : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 render_type = render_type_from_string( userdata.asString() ); bool new_value = false; if ( render_type != 0 ) { new_value = LLPipeline::hasRenderTypeControl( render_type ); } return new_value; } }; ///////////// // FEATURE // ///////////// U32 feature_from_string(std::string_view feature) { if ("ui" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_UI; } else if ("selected" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED; } else if ("highlighted" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED; } else if ("dynamic textures" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES; } else if ("foot shadows" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS; } else if ("fog" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_FOG; } else if ("fr info" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO; } else if ("flexible" == feature) { return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE; } else { return 0; } }; class LLAdvancedToggleFeature : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 feature = feature_from_string( userdata.asString() ); if ( feature != 0 ) { LLPipeline::toggleRenderDebugFeature( feature ); } return true; } }; class LLAdvancedCheckFeature : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 feature = feature_from_string( userdata.asString() ); bool new_value = false; if ( feature != 0 ) { new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); } return new_value; } }; class LLAdvancedToggleExperiment : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string feature = userdata.asString(); if (feature == "GameControl") { LLGameControl::setEnabled(! LLGameControl::isEnabled()); LLFloaterPreference::refreshInstance(); return true; } return false; } }; class LLAdvancedCheckExperiment : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool value = false; std::string feature = userdata.asString(); if (feature == "GameControl") { value = LLGameControl::isEnabled(); } return value; } }; class LLAdvancedCheckDisplayTextureDensity : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string mode = userdata.asString(); if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { return mode == "none"; } if (mode == "current") { return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT; } else if (mode == "desired") { return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED; } else if (mode == "full") { return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL; } return false; } }; class LLAdvancedSetDisplayTextureDensity : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string mode = userdata.asString(); if (mode == "none") { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); } LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; } else if (mode == "current") { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); } LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT; } else if (mode == "desired") { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); } gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true); LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED; } else if (mode == "full") { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); } LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL; } return true; } }; ////////////////// // INFO DISPLAY // ////////////////// U64 info_display_from_string(std::string_view info_display) { if ("verify" == info_display) { return LLPipeline::RENDER_DEBUG_VERIFY; } else if ("bboxes" == info_display) { return LLPipeline::RENDER_DEBUG_BBOXES; } else if ("normals" == info_display) { return LLPipeline::RENDER_DEBUG_NORMALS; } else if ("points" == info_display) { return LLPipeline::RENDER_DEBUG_POINTS; } else if ("octree" == info_display) { return LLPipeline::RENDER_DEBUG_OCTREE; } else if ("nodes" == info_display) { return LLPipeline::RENDER_DEBUG_NODES; } else if ("shadow frusta" == info_display) { return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA; } else if ("physics shapes" == info_display) { return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES; } else if ("occlusion" == info_display) { return LLPipeline::RENDER_DEBUG_OCCLUSION; } else if ("render batches" == info_display) { return LLPipeline::RENDER_DEBUG_BATCH_SIZE; } else if ("update type" == info_display) { return LLPipeline::RENDER_DEBUG_UPDATE_TYPE; } else if ("texture anim" == info_display) { return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM; } else if ("texture priority" == info_display) { return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY; } else if ("texture area" == info_display) { return LLPipeline::RENDER_DEBUG_TEXTURE_AREA; } else if ("face area" == info_display) { return LLPipeline::RENDER_DEBUG_FACE_AREA; } else if ("lod info" == info_display) { return LLPipeline::RENDER_DEBUG_LOD_INFO; } else if ("lights" == info_display) { return LLPipeline::RENDER_DEBUG_LIGHTS; } else if ("particles" == info_display) { return LLPipeline::RENDER_DEBUG_PARTICLES; } else if ("composition" == info_display) { return LLPipeline::RENDER_DEBUG_COMPOSITION; } else if ("avatardrawinfo" == info_display) { return (LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO); } else if ("glow" == info_display) { return LLPipeline::RENDER_DEBUG_GLOW; } else if ("collision skeleton" == info_display) { return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME; } else if ("joints" == info_display) { return LLPipeline::RENDER_DEBUG_AVATAR_JOINTS; } else if ("raycast" == info_display) { return LLPipeline::RENDER_DEBUG_RAYCAST; } else if ("agent target" == info_display) { return LLPipeline::RENDER_DEBUG_AGENT_TARGET; } else if ("sculpt" == info_display) { return LLPipeline::RENDER_DEBUG_SCULPTED; } else if ("wind vectors" == info_display) { return LLPipeline::RENDER_DEBUG_WIND_VECTORS; } else if ("texel density" == info_display) { return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY; } else if ("triangle count" == info_display) { return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT; } else if ("impostors" == info_display) { return LLPipeline::RENDER_DEBUG_IMPOSTORS; } else if ("reflection probes" == info_display) { return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES; } else if ("probe updates" == info_display) { return LLPipeline::RENDER_DEBUG_PROBE_UPDATES; } else { LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL; return 0; } }; class LLAdvancedToggleInfoDisplay : public view_listener_t { bool handleEvent(const LLSD& userdata) { U64 info_display = info_display_from_string( userdata.asString() ); LL_INFOS("ViewerMenu") << "toggle " << userdata.asString() << LL_ENDL; if ( info_display != 0 ) { LLPipeline::toggleRenderDebug( info_display ); } return true; } }; class LLAdvancedCheckInfoDisplay : public view_listener_t { bool handleEvent(const LLSD& userdata) { U64 info_display = info_display_from_string( userdata.asString() ); bool new_value = false; if ( info_display != 0 ) { new_value = LLPipeline::toggleRenderDebugControl( info_display ); } return new_value; } }; /////////////////////////// //// RANDOMIZE FRAMERATE // /////////////////////////// class LLAdvancedToggleRandomizeFramerate : public view_listener_t { bool handleEvent(const LLSD& userdata) { gRandomizeFramerate = !(gRandomizeFramerate); return true; } }; class LLAdvancedCheckRandomizeFramerate : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gRandomizeFramerate; return new_value; } }; /////////////////////////// //// PERIODIC SLOW FRAME // /////////////////////////// class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t { bool handleEvent(const LLSD& userdata) { gPeriodicSlowFrame = !(gPeriodicSlowFrame); return true; } }; class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gPeriodicSlowFrame; return new_value; } }; /////////////////////////// // SELECTED TEXTURE INFO // // /////////////////////////// class LLAdvancedSelectedTextureInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_selected_texture_info(); return true; } }; ////////////////////// // TOGGLE WIREFRAME // ////////////////////// class LLAdvancedToggleWireframe : public view_listener_t { bool handleEvent(const LLSD& userdata) { gUseWireframe = !(gUseWireframe); return true; } }; class LLAdvancedCheckWireframe : public view_listener_t { bool handleEvent(const LLSD& userdata) { return gUseWireframe; } }; ////////////////////////// // DUMP SCRIPTED CAMERA // ////////////////////////// class LLAdvancedDumpScriptedCamera : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_dump_followcam(); return true; } }; ////////////////////////////// // DUMP REGION OBJECT CACHE // ////////////////////////////// class LLAdvancedDumpRegionObjectCache : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_dump_region_object_cache(); return true; } }; class LLAdvancedToggleInterestList360Mode : public view_listener_t { public: bool handleEvent(const LLSD &userdata) { // Toggle the mode - regions will get updated if (gAgent.getInterestListMode() == IL_MODE_360) { gAgent.changeInterestListMode(IL_MODE_DEFAULT); } else { gAgent.changeInterestListMode(IL_MODE_360); } return true; } }; class LLAdvancedCheckInterestList360Mode : public view_listener_t { bool handleEvent(const LLSD& userdata) { return (gAgent.getInterestListMode() == IL_MODE_360); } }; class LLAdvancedToggleStatsRecorder : public view_listener_t { bool handleEvent(const LLSD &userdata) { if (LLViewerStatsRecorder::instance().isEnabled()) { // Turn off both recording and logging LLViewerStatsRecorder::instance().enableObjectStatsRecording(false); } else { // Turn on both recording and logging LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true); } return true; } }; class LLAdvancedCheckStatsRecorder : public view_listener_t { bool handleEvent(const LLSD &userdata) { // Use the logging state as the indicator of whether the stats recorder is on return LLViewerStatsRecorder::instance().isLogging(); } }; class LLAdvancedResetInterestLists : public view_listener_t { bool handleEvent(const LLSD &userdata) { // Reset all region interest lists handle_reset_interest_lists(); return true; } }; ///////////// // TERRAIN // ///////////// class LLAdvancedRebuildTerrain : public view_listener_t { bool handleEvent(const LLSD& userdata) { gPipeline.rebuildTerrain(); return true; } }; class LLAdvancedTerrainCreateLocalPaintMap : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerRegion* region = gAgent.getRegion(); if (!region) { LL_WARNS() << "Agent not in a region" << LL_ENDL; return false; } // This calls gLocalTerrainMaterials.setPaintType // It also ensures the terrain bake shader is compiled (handleSetShaderChanged), so call this first // *TODO: Fix compile errors in shader so it can be used for all platforms. Then we can unhide the shader from behind this setting and remove the hook to handleSetShaderChanged. This advanced setting is intended to be used as a local setting for testing terrain, not a feature flag, but it is currently used like a feature flag as a temporary hack. // *TODO: Ideally we would call setPaintType *after* the paint map is well-defined. The terrain draw pool should be able to handle an undefined paint map in the meantime. gSavedSettings.setBOOL("LocalTerrainPaintEnabled", true); U16 dim = (U16)gSavedSettings.getU32("TerrainPaintResolution"); // Ensure a reasonable image size of power two const U32 max_resolution = gSavedSettings.getU32("RenderMaxTextureResolution"); dim = llclamp(dim, 16, max_resolution); dim = 1 << U32(std::ceil(std::log2(dim))); // TODO: Could probably get away with not using image raw here, now that we aren't writing bits via the CPU (see load_exr for example) LLPointer image_raw = new LLImageRaw(dim,dim,3); LLPointer tex = LLViewerTextureManager::getLocalTexture(image_raw.get(), true); const bool success = LLTerrainPaintMap::bakeHeightNoiseIntoPBRPaintMapRGB(*region, *tex); // If baking the paintmap failed, set the paintmap to nullptr. This // causes LLDrawPoolTerrain to use a blank paintmap instead. if (!success) { tex = nullptr; } gLocalTerrainMaterials.setPaintMap(tex); return true; } }; class LLAdvancedTerrainEditLocalPaintMap : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerTexture* tex = gLocalTerrainMaterials.getPaintMap(); if (!tex) { LL_WARNS() << "No local paint map available to edit" << LL_ENDL; return false; } LLTerrainBrushQueue& brush_queue = gLocalTerrainMaterials.getBrushQueue(); LLTerrainPaintQueue& paint_request_queue = gLocalTerrainMaterials.getPaintRequestQueue(); const LLViewerRegion* region = gAgent.getRegion(); if (!region) { LL_WARNS() << "No current region for calculating paint operations" << LL_ENDL; return false; } // TODO: Create the brush // Just a dab for now LLTerrainBrush::ptr_t brush = std::make_shared(); brush->mBrushSize = 16.0f; brush->mPath.emplace_back(17.0f, 17.0f); brush->mPathOffset = 0; brush->mPathEnd = true; brush_queue.enqueue(brush); LLTerrainPaintQueue brush_as_paint_queue = LLTerrainPaintMap::convertBrushQueueToPaintRGB(*region, *tex, brush_queue); //paint_send_queue.enqueue(brush_as_paint_queue); // TODO: What was this line for? (it might also be a leftover line from an unfinished edit) // TODO: Keep this around for later testing (i.e. when reducing framebuffer size and the offsets that requires) #if 0 // Enqueue a paint // Modifies a subsection of the region paintmap with the material in // the last slot. // It is currently the responsibility of the paint queue to convert // incoming bits to the right bit depth for the paintmap (this could // change in the future). LLTerrainPaint::ptr_t paint = std::make_shared(); const U16 width = 33; paint->mStartX = 1; paint->mStartY = 1; paint->mWidthX = width; paint->mWidthY = width; constexpr U8 bit_depth = 5; paint->mBitDepth = bit_depth; constexpr U8 max_value = (1 << bit_depth) - 1; const size_t pixel_count = width * width; const U8 components = LLTerrainPaint::RGBA; paint->mComponents = components; paint->mData.resize(components * pixel_count); for (size_t h = 0; h < paint->mWidthY; ++h) { for (size_t w = 0; w < paint->mWidthX; ++w) { const size_t pixel = (h * paint->mWidthX) + w; // Solid blue color paint->mData[(components*pixel) + components - 2] = max_value; // blue //// Alpha grid: 1.0 if odd for either dimension, 0.0 otherwise //const U8 alpha = U8(F32(max_value) * F32(bool(w % 2) || bool(h % 2))); //paint->mData[(components*pixel) + components - 1] = alpha; // alpha // Alpha "frame" const bool edge = w == 0 || h == 0 || w == (paint->mWidthX - 1) || h == (paint->mWidthY - 1); const bool near_edge_frill = ((w == 1 || w == (paint->mWidthX - 2)) && (h % 2 == 0)) || ((h == 1 || h == (paint->mWidthY - 2)) && (w % 2 == 0)); const U8 alpha = U8(F32(max_value) * F32(edge || near_edge_frill)); paint->mData[(components*pixel) + components - 1] = alpha; // alpha } } paint_request_queue.enqueue(paint); #endif // Apply the paint queues ad-hoc right here for now. // *TODO: Eventually the paint queue(s) should be applied at a // predictable time in the viewer frame loop. // TODO: In hindsight... maybe we *should* bind the paintmap to the render buffer. That makes a lot more sense, and we wouldn't have to reduce its resolution by settling for the bake buffer. If we do that, make a comment above convertPaintQueueRGBAToRGB that the texture is modified! LLTerrainPaintQueue paint_send_queue = LLTerrainPaintMap::convertPaintQueueRGBAToRGB(*tex, paint_request_queue); LLTerrainPaintQueue& paint_map_queue = gLocalTerrainMaterials.getPaintMapQueue(); paint_map_queue.enqueue(paint_send_queue); LLTerrainPaintMap::applyPaintQueueRGB(*tex, paint_map_queue); return true; } }; class LLAdvancedTerrainDeleteLocalPaintMap : public view_listener_t { bool handleEvent(const LLSD& userdata) { // This calls gLocalTerrainMaterials.setPaintType gSavedSettings.setBOOL("LocalTerrainPaintEnabled", false); gLocalTerrainMaterials.setPaintMap(nullptr); return true; } }; ///////////// class LLAdvancedBuyCurrencyTest : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_buy_currency_test(); return true; } }; ///////////////////// // DUMP SELECT MGR // ///////////////////// class LLAdvancedDumpSelectMgr : public view_listener_t { bool handleEvent(const LLSD& userdata) { dump_select_mgr(); return true; } }; //////////////////// // DUMP INVENTORY // //////////////////// class LLAdvancedDumpInventory : public view_listener_t { bool handleEvent(const LLSD& userdata) { dump_inventory(); return true; } }; //////////////////////////////// // PRINT SELECTED OBJECT INFO // //////////////////////////////// class LLAdvancedPrintSelectedObjectInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { print_object_info(); return true; } }; ////////////////////// // PRINT AGENT INFO // ////////////////////// class LLAdvancedPrintAgentInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { print_agent_nvpairs(); return true; } }; ////////////////// // DEBUG CLICKS // ////////////////// class LLAdvancedToggleDebugClicks : public view_listener_t { bool handleEvent(const LLSD& userdata) { gDebugClicks = !(gDebugClicks); return true; } }; class LLAdvancedCheckDebugClicks : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gDebugClicks; return new_value; } }; ///////////////// // DEBUG VIEWS // ///////////////// class LLAdvancedToggleDebugViews : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLView::sDebugRects = !(LLView::sDebugRects); return true; } }; class LLAdvancedCheckDebugViews : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLView::sDebugRects; return new_value; } }; /////////////////// // DEBUG UNICODE // /////////////////// class LLAdvancedToggleDebugUnicode : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLView::sDebugUnicode = !(LLView::sDebugUnicode); return true; } }; class LLAdvancedCheckDebugUnicode : public view_listener_t { bool handleEvent(const LLSD& userdata) { return LLView::sDebugUnicode; } }; ////////////////// // DEBUG CAMERA // ////////////////// class LLAdvancedToggleDebugCamera : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLView::sDebugCamera = !(LLView::sDebugCamera); LLFloaterCamera::onDebugCameraToggled(); return true; } }; class LLAdvancedCheckDebugCamera : public view_listener_t { bool handleEvent(const LLSD& userdata) { return LLView::sDebugCamera; } }; /////////////////////// // XUI NAME TOOLTIPS // /////////////////////// class LLAdvancedToggleXUINameTooltips : public view_listener_t { bool handleEvent(const LLSD& userdata) { toggle_show_xui_names(); return true; } }; class LLAdvancedCheckXUINameTooltips : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = check_show_xui_names(); return new_value; } }; //////////////////////// // DEBUG MOUSE EVENTS // //////////////////////// class LLAdvancedToggleDebugMouseEvents : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling); return true; } }; class LLAdvancedCheckDebugMouseEvents : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLView::sDebugMouseHandling; return new_value; } }; //////////////// // DEBUG KEYS // //////////////// class LLAdvancedToggleDebugKeys : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLView::sDebugKeys = !(LLView::sDebugKeys); return true; } }; class LLAdvancedCheckDebugKeys : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLView::sDebugKeys; return new_value; } }; /////////////////////// // DEBUG WINDOW PROC // /////////////////////// class LLAdvancedToggleDebugWindowProc : public view_listener_t { bool handleEvent(const LLSD& userdata) { gDebugWindowProc = !(gDebugWindowProc); return true; } }; class LLAdvancedCheckDebugWindowProc : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gDebugWindowProc; return new_value; } }; // ------------------------------XUI MENU --------------------------- class LLAdvancedSendTestIms : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLIMModel::instance().testMessages(); return true; } }; /////////////// // XUI NAMES // /////////////// class LLAdvancedToggleXUINames : public view_listener_t { bool handleEvent(const LLSD& userdata) { toggle_show_xui_names(); return true; } }; class LLAdvancedCheckXUINames : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = check_show_xui_names(); return new_value; } }; //////////////////////// // GRAB BAKED TEXTURE // //////////////////////// class LLAdvancedGrabBakedTexture : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string texture_type = userdata.asString(); if ("iris" == texture_type) { handle_grab_baked_texture(BAKED_EYES); } else if ("head" == texture_type) { handle_grab_baked_texture(BAKED_HEAD); } else if ("upper" == texture_type) { handle_grab_baked_texture(BAKED_UPPER); } else if ("lower" == texture_type) { handle_grab_baked_texture(BAKED_LOWER); } else if ("skirt" == texture_type) { handle_grab_baked_texture(BAKED_SKIRT); } else if ("hair" == texture_type) { handle_grab_baked_texture(BAKED_HAIR); } return true; } }; class LLAdvancedEnableGrabBakedTexture : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string texture_type = userdata.asString(); bool new_value = false; if ("iris" == texture_type) { new_value = enable_grab_baked_texture(BAKED_EYES); } else if ("head" == texture_type) { new_value = enable_grab_baked_texture(BAKED_HEAD); } else if ("upper" == texture_type) { new_value = enable_grab_baked_texture(BAKED_UPPER); } else if ("lower" == texture_type) { new_value = enable_grab_baked_texture(BAKED_LOWER); } else if ("skirt" == texture_type) { new_value = enable_grab_baked_texture(BAKED_SKIRT); } else if ("hair" == texture_type) { new_value = enable_grab_baked_texture(BAKED_HAIR); } return new_value; } }; /////////////////////// // APPEARANCE TO XML // /////////////////////// class LLAdvancedEnableAppearanceToXML : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (obj && obj->isAnimatedObject() && obj->getControlAvatar()) { return gSavedSettings.getBOOL("DebugAnimatedObjects"); } else if (obj && obj->isAttachment() && obj->getAvatar()) { return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); } else if (obj && obj->isAvatar()) { // This has to be a non-control avatar, because control avs are invisible and unclickable. return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); } else { return false; } } }; class LLAdvancedAppearanceToXML : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string emptyname; LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); LLVOAvatar *avatar = NULL; if (obj) { if (obj->isAvatar()) { avatar = obj->asAvatar(); } else { // If there is a selection, find the associated // avatar. Normally there's only one obvious choice. But // what should be returned if the object is in an attached // animated object? getAvatar() will give the skeleton of // the animated object. getAvatarAncestor() will give the // actual human-driven avatar. avatar = obj->getAvatar(); } } else { // If no selection, use the self avatar. avatar = gAgentAvatarp; } if (avatar) { avatar->dumpArchetypeXML(emptyname); } return true; } }; /////////////////////////////// // TOGGLE CHARACTER GEOMETRY // /////////////////////////////// class LLAdvancedToggleCharacterGeometry : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_god_request_avatar_geometry(); return true; } }; ///////////////////////////// // TEST MALE / TEST FEMALE // ///////////////////////////// class LLAdvancedTestMale : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_test_male(); return true; } }; class LLAdvancedTestFemale : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_test_female(); return true; } }; class LLAdvancedForceParamsToDefault : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLAgent::clearVisualParams(nullptr); return true; } }; ////////////////////////// // ANIMATION SPEED // ////////////////////////// // Utility function to set all AV time factors to the same global value static void set_all_animation_time_factors(F32 time_factor) { LLMotionController::setCurrentTimeFactor(time_factor); for (LLCharacter* character : LLCharacter::sInstances) { character->setAnimTimeFactor(time_factor); } } class LLAdvancedAnimTenFaster : public view_listener_t { bool handleEvent(const LLSD& userdata) { //LL_INFOS() << "LLAdvancedAnimTenFaster" << LL_ENDL; F32 time_factor = LLMotionController::getCurrentTimeFactor(); time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed set_all_animation_time_factors(time_factor); return true; } }; class LLAdvancedAnimTenSlower : public view_listener_t { bool handleEvent(const LLSD& userdata) { //LL_INFOS() << "LLAdvancedAnimTenSlower" << LL_ENDL; F32 time_factor = LLMotionController::getCurrentTimeFactor(); time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed set_all_animation_time_factors(time_factor); return true; } }; class LLAdvancedAnimResetAll : public view_listener_t { bool handleEvent(const LLSD& userdata) { set_all_animation_time_factors(1.f); return true; } }; ////////////////////////// // RELOAD VERTEX SHADER // ////////////////////////// class LLAdvancedReloadVertexShader : public view_listener_t { bool handleEvent(const LLSD& userdata) { reload_vertex_shader(); return true; } }; //////////////////// // ANIMATION INFO // //////////////////// class LLAdvancedToggleAnimationInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug); return true; } }; class LLAdvancedCheckAnimationInfo : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLVOAvatar::sShowAnimationDebug; return new_value; } }; ////////////////// // SHOW LOOK AT // ////////////////// class LLAdvancedToggleShowLookAt : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt); return true; } }; class LLAdvancedCheckShowLookAt : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLHUDEffectLookAt::sDebugLookAt; return new_value; } }; /////////////////// // SHOW POINT AT // /////////////////// class LLAdvancedToggleShowPointAt : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt); return true; } }; class LLAdvancedCheckShowPointAt : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLHUDEffectPointAt::sDebugPointAt; return new_value; } }; ///////////////////////// // DEBUG JOINT UPDATES // ///////////////////////// class LLAdvancedToggleDebugJointUpdates : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug); return true; } }; class LLAdvancedCheckDebugJointUpdates : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLVOAvatar::sJointDebug; return new_value; } }; ///////////////// // DISABLE LOD // ///////////////// class LLAdvancedToggleDisableLOD : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD); return true; } }; class LLAdvancedCheckDisableLOD : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLViewerJoint::sDisableLOD; return new_value; } }; ///////////////////////// // DEBUG CHARACTER VIS // ///////////////////////// class LLAdvancedToggleDebugCharacterVis : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible); return true; } }; class LLAdvancedCheckDebugCharacterVis : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLVOAvatar::sDebugInvisible; return new_value; } }; ////////////////////// // DUMP ATTACHMENTS // ////////////////////// class LLAdvancedDumpAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_dump_attachments(); return true; } }; ///////////////////// // REBAKE TEXTURES // ///////////////////// class LLAdvancedRebakeTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_rebake_textures(); return true; } }; #if 1 //ndef LL_RELEASE_FOR_DOWNLOAD /////////////////////////// // DEBUG AVATAR TEXTURES // /////////////////////////// class LLAdvancedDebugAvatarTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgent.isGodlike()) { handle_debug_avatar_textures(); } return true; } }; //////////////////////////////// // DUMP AVATAR LOCAL TEXTURES // //////////////////////////////// class LLAdvancedDumpAvatarLocalTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { #ifndef LL_RELEASE_FOR_DOWNLOAD handle_dump_avatar_local_textures(); #endif return true; } }; #endif ///////////////// // MESSAGE LOG // ///////////////// class LLAdvancedEnableMessageLog : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_viewer_enable_message_log(); return true; } }; class LLAdvancedDisableMessageLog : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_viewer_disable_message_log(); return true; } }; ///////////////// // DROP PACKET // ///////////////// class LLAdvancedDropPacket : public view_listener_t { bool handleEvent(const LLSD& userdata) { gMessageSystem->mPacketRing.dropPackets(1); return true; } }; ////////////////////// // PURGE DISK CACHE // ////////////////////// class LLAdvancedPurgeDiskCache : public view_listener_t { bool handleEvent(const LLSD& userdata) { LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); llassert_always(main_queue); llassert_always(general_queue); main_queue->postTo( general_queue, []() // Work done on general queue { LLDiskCache::getInstance()->purge(); // Nothing needed to return }, [](){}); // Callback to main thread is empty as there is nothing left to do return true; } }; //////////////////////// // PURGE SHADER CACHE // //////////////////////// class LLAdvancedPurgeShaderCache : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerShaderMgr::instance()->clearShaderCache(); LLViewerShaderMgr::instance()->setShaders(); return true; } }; //////////////////// // EVENT Recorder // /////////////////// class LLAdvancedViewerEventRecorder : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string command = userdata.asString(); if ("start playback" == command) { LL_INFOS() << "Event Playback starting" << LL_ENDL; LLViewerEventRecorder::instance().playbackRecording(); LL_INFOS() << "Event Playback completed" << LL_ENDL; } else if ("stop playback" == command) { // Future } else if ("start recording" == command) { LLViewerEventRecorder::instance().setEventLoggingOn(); LL_INFOS() << "Event recording started" << LL_ENDL; } else if ("stop recording" == command) { LLViewerEventRecorder::instance().setEventLoggingOff(); LL_INFOS() << "Event recording stopped" << LL_ENDL; } return true; } }; ///////////////// // AGENT PILOT // ///////////////// class LLAdvancedAgentPilot : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string command = userdata.asString(); if ("start playback" == command) { gAgentPilot.setNumRuns(-1); gAgentPilot.startPlayback(); } else if ("stop playback" == command) { gAgentPilot.stopPlayback(); } else if ("start record" == command) { gAgentPilot.startRecord(); } else if ("stop record" == command) { gAgentPilot.stopRecord(); } return true; } }; ////////////////////// // AGENT PILOT LOOP // ////////////////////// class LLAdvancedToggleAgentPilotLoop : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgentPilot.setLoop(!gAgentPilot.getLoop()); return true; } }; class LLAdvancedCheckAgentPilotLoop : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gAgentPilot.getLoop(); return new_value; } }; ///////////////////////// // SHOW OBJECT UPDATES // ///////////////////////// class LLAdvancedToggleShowObjectUpdates : public view_listener_t { bool handleEvent(const LLSD& userdata) { gShowObjectUpdates = !(gShowObjectUpdates); return true; } }; class LLAdvancedCheckShowObjectUpdates : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gShowObjectUpdates; return new_value; } }; //////////////////// // COMPRESS IMAGE // //////////////////// class LLAdvancedCompressImage : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_compress_image(); return true; } }; //////////////////////// // COMPRESS FILE TEST // //////////////////////// class LLAdvancedCompressFileTest : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_compress_file_test(); return true; } }; ///////////////////////// // SHOW DEBUG SETTINGS // ///////////////////////// class LLAdvancedShowDebugSettings : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterReg::showInstance("settings_debug",userdata); return true; } }; //////////////////////// // VIEW ADMIN OPTIONS // //////////////////////// class LLAdvancedEnableViewAdminOptions : public view_listener_t { bool handleEvent(const LLSD& userdata) { // Don't enable in god mode since the admin menu is shown anyway. // Only enable if the user has set the appropriate debug setting. bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu"); return new_value; } }; class LLAdvancedToggleViewAdminOptions : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_admin_override_toggle(); return true; } }; class LLAdvancedToggleVisualLeakDetector : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_visual_leak_detector_toggle(); return true; } }; class LLAdvancedCheckViewAdminOptions : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = check_admin_override() || gAgent.isGodlike(); return new_value; } }; ////////////////// // ADMIN STATUS // ////////////////// class LLAdvancedRequestAdminStatus : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_god_mode(); return true; } }; class LLAdvancedLeaveAdminStatus : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_leave_god_mode(); return true; } }; ////////////////////////// // Advanced > Debugging // ////////////////////////// class LLAdvancedForceErrorBreakpoint : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_breakpoint(); return true; } }; class LLAdvancedForceErrorLlerror : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_llerror(); return true; } }; class LLAdvancedForceErrorLlerrorMsg: public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_llerror_msg(); return true; } }; class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_bad_memory_access(); return true; } }; class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLCoros::instance().launch( "AdvancedForceErrorBadMemoryAccessCoro", [](){ // Wait for one mainloop() iteration, letting the enclosing // handleEvent() method return. llcoro::suspend(); force_error_bad_memory_access(); }); return true; } }; class LLAdvancedForceErrorInfiniteLoop : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_infinite_loop(); return true; } }; class LLAdvancedForceErrorSoftwareException : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_software_exception(); return true; } }; class LLAdvancedForceOSException: public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_os_exception(); return true; } }; class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLCoros::instance().launch( "AdvancedForceErrorSoftwareExceptionCoro", [](){ // Wait for one mainloop() iteration, letting the enclosing // handleEvent() method return. llcoro::suspend(); force_error_software_exception(); }); return true; } }; class LLAdvancedForceErrorDriverCrash : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_driver_crash(); return true; } }; class LLAdvancedForceErrorCoroutineCrash : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_coroutine_crash(); return true; } }; class LLAdvancedForceErrorThreadCrash : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_error_thread_crash(); return true; } }; class LLAdvancedForceErrorDisconnectViewer : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_disconnect_viewer(); return true; } }; #ifdef TOGGLE_HACKED_GODLIKE_VIEWER class LLAdvancedHandleToggleHackedGodmode : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_toggle_hacked_godmode(); return true; } }; class LLAdvancedCheckToggleHackedGodmode : public view_listener_t { bool handleEvent(const LLSD& userdata) { check_toggle_hacked_godmode(); return true; } }; class LLAdvancedEnableToggleHackedGodmode : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = enable_toggle_hacked_godmode(); return new_value; } }; #endif // ////------------------------------------------------------------------- //// Advanced menu ////------------------------------------------------------------------- ////////////////// // DEVELOP MENU // ////////////////// class LLDevelopCheckLoggingLevel : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 level = userdata.asInteger(); return (static_cast(level) == LLError::getDefaultLevel()); } }; class LLDevelopSetLoggingLevel : public view_listener_t { bool handleEvent(const LLSD& userdata) { U32 level = userdata.asInteger(); LLError::setDefaultLevel(static_cast(level)); return true; } }; ////////////////// // ADMIN MENU // ////////////////// // Admin > Object class LLAdminForceTakeCopy : public view_listener_t { bool handleEvent(const LLSD& userdata) { force_take_copy(); return true; } }; class LLAdminHandleObjectOwnerSelf : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_object_owner_self(); return true; } }; class LLAdminHandleObjectOwnerPermissive : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_object_owner_permissive(); return true; } }; class LLAdminHandleForceDelete : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_force_delete(); return true; } }; class LLAdminHandleObjectLock : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_object_lock(); return true; } }; class LLAdminHandleObjectAssetIDs: public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_object_asset_ids(); return true; } }; //Admin >Parcel class LLAdminHandleForceParcelOwnerToMe: public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_force_parcel_owner_to_me(); return true; } }; class LLAdminHandleForceParcelToContent: public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_force_parcel_to_content(); return true; } }; class LLAdminHandleClaimPublicLand: public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_claim_public_land(); return true; } }; // Admin > Region class LLAdminHandleRegionDumpTempAssetData: public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_region_dump_temp_asset_data(); return true; } }; //Admin (Top Level) class LLAdminOnSaveState: public view_listener_t { bool handleEvent(const LLSD& userdata) { LLPanelRegionTools::onSaveState(nullptr); return true; } }; //----------------------------------------------------------------------------- // cleanup_menus() //----------------------------------------------------------------------------- void cleanup_menus() { delete gSLMMenuUpdater; gSLMMenuUpdater = nullptr; delete gMenuParcelObserver; gMenuParcelObserver = NULL; delete gMenuAvatarSelf; gMenuAvatarSelf = NULL; delete gMenuAvatarOther; gMenuAvatarOther = NULL; delete gMenuObject; gMenuObject = NULL; delete gMenuAttachmentSelf; gMenuAttachmentSelf = NULL; delete gMenuAttachmentOther; gMenuAttachmentOther = NULL; delete gMenuLand; gMenuLand = NULL; delete gMenuMuteParticle; gMenuMuteParticle = NULL; delete gMenuBarView; gMenuBarView = NULL; delete gPopupMenuView; gPopupMenuView = NULL; delete gMenuHolder; gMenuHolder = NULL; } //----------------------------------------------------------------------------- // Object pie menu //----------------------------------------------------------------------------- class LLObjectReportAbuse : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (objectp) { LLFloaterReporter::showFromObject(objectp->getID()); } return true; } }; // Enabled it you clicked an object class LLObjectEnableReportAbuse : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; return new_value; } }; void handle_object_touch() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return; LLPickInfo pick = LLToolPie::getInstance()->getPick(); // *NOTE: Hope the packets arrive safely and in order or else // there will be some problems. // *TODO: Just fix this bad assumption. send_ObjectGrab_message(object, pick, LLVector3::zero); send_ObjectDeGrab_message(object, pick); } void handle_object_show_original() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) { return; } LLViewerObject *parent = (LLViewerObject*)object->getParent(); while (parent) { if(parent->isAvatar()) { break; } object = parent; parent = (LLViewerObject*)parent->getParent(); } if (!object || object->isAvatar()) { return; } show_item_original(object->getAttachmentItemID()); } static void init_default_item_label(LLUICtrl* ctrl) { const std::string& item_name = ctrl->getName(); boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); if (it == sDefaultItemLabels.end()) { // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value // (doesn't seem to matter much ATM). LLStringExplicit default_label = ctrl->getValue().asString(); if (!default_label.empty()) { sDefaultItemLabels.insert(std::pair(item_name, default_label)); } } } static LLStringExplicit get_default_item_label(const std::string& item_name) { LLStringExplicit res(""); boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); if (it != sDefaultItemLabels.end()) { res = it->second; } return res; } bool enable_object_touch(LLUICtrl* ctrl) { bool new_value = false; LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (obj) { LLViewerObject* parent = (LLViewerObject*)obj->getParent(); new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch()); } init_default_item_label(ctrl); // Update label based on the node touch name if available. LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { ctrl->setValue(node->mTouchName); } else { ctrl->setValue(get_default_item_label(ctrl->getName())); } return new_value; }; //void label_touch(std::string& label, void*) //{ // LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); // if (node && node->mValid && !node->mTouchName.empty()) // { // label.assign(node->mTouchName); // } // else // { // label.assign("Touch"); // } //} void handle_object_open() { LLFloaterReg::showInstance("openobject"); } bool enable_object_inspect() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLViewerObject* selected_objectp = selection->getFirstRootObject(); return selected_objectp != NULL; } struct LLSelectedTEGetmatIdAndPermissions : public LLSelectedTEFunctor { LLSelectedTEGetmatIdAndPermissions() : mCanCopy(true) , mCanModify(true) , mCanTransfer(true) , mHasNonPbrFaces(false) {} bool apply(LLViewerObject* objectp, S32 te_index) { mCanCopy &= (bool)objectp->permCopy(); mCanTransfer &= (bool)objectp->permTransfer(); mCanModify &= (bool)objectp->permModify(); LLUUID mat_id = objectp->getRenderMaterialID(te_index); if (mat_id.notNull()) { mMaterialId = mat_id; } else { mHasNonPbrFaces = true; } return true; } bool mCanCopy; bool mCanModify; bool mCanTransfer; bool mHasNonPbrFaces; LLUUID mMaterialId; }; bool enable_object_edit_gltf_material() { if (!LLMaterialEditor::capabilitiesAvailable()) { return false; } LLSelectedTEGetmatIdAndPermissions func; LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); return func.mCanModify && !func.mHasNonPbrFaces; } bool enable_object_open() { // Look for contents in root object, which is all the LLFloaterOpenObject // understands. LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!obj) return false; LLViewerObject* root = obj->getRootEdit(); if (!root) return false; return root->allowOpen(); } class LLViewJoystickFlycam : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_toggle_flycam(); return true; } }; class LLViewCheckJoystickFlycam : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); return new_value; } }; void handle_toggle_flycam() { LLViewerJoystick::getInstance()->toggleFlycam(); } class LLObjectBuild : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) { // zoom in if we're looking at the avatar gAgentCamera.setFocusOnAvatar(false, ANIMATE); gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgentCamera.cameraZoomIn(0.666f); gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); gViewerWindow->moveCursorToCenter(); } else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); // Could be first use //LLFirstUse::useBuild(); return true; } }; void update_camera() { LLViewerParcelMgr::getInstance()->deselectLand(); if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) { LLFloaterTools::sPreviousFocusOnAvatar = true; LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) { // always freeze camera in space, even if camera doesn't move // so, for example, follow cam scripts can't affect you when in build mode gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null); gAgentCamera.setFocusOnAvatar(false, ANIMATE); } else { gAgentCamera.setFocusOnAvatar(false, ANIMATE); LLViewerObject* selected_objectp = selection->getFirstRootObject(); if (selected_objectp) { // zoom in on object center instead of where we clicked, as we need to see the manipulator handles gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID()); gAgentCamera.cameraZoomIn(0.666f); gAgentCamera.cameraOrbitOver(30.f * DEG_TO_RAD); gViewerWindow->moveCursorToCenter(); } } } } void handle_object_edit() { update_camera(); LLFloaterReg::showInstance("build"); LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); LLViewerJoystick::getInstance()->moveObjects(true); LLViewerJoystick::getInstance()->setNeedsReset(true); // Could be first use //LLFirstUse::useBuild(); return; } void handle_object_edit_gltf_material() { if (!LLFloaterReg::instanceVisible("build")) { handle_object_edit(); // does update_camera(); } else { update_camera(); LLViewerJoystick::getInstance()->moveObjects(true); LLViewerJoystick::getInstance()->setNeedsReset(true); } LLMaterialEditor::loadLive(); } void handle_attachment_edit(const LLUUID& inv_item_id) { if (isAgentAvatarValid()) { if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id)) { LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj); handle_object_edit(); } } } void handle_attachment_touch(const LLUUID& inv_item_id) { if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) ) { if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id))) { LLSelectMgr::getInstance()->deselectAll(); LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj); if (!LLToolMgr::getInstance()->inBuildMode()) { struct SetTransient : public LLSelectedNodeFunctor { bool apply(LLSelectNode* node) { node->setTransient(true); return true; } } f; sel->applyToNodes(&f); } handle_object_touch(); } } } bool enable_attachment_touch(const LLUUID& inv_item_id) { if (isAgentAvatarValid()) { const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)); return (attach_obj) && (attach_obj->flagHandleTouch()); } return false; } void handle_object_inspect() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLViewerObject* selected_objectp = selection->getFirstRootObject(); if (selected_objectp) { LLFloaterReg::showInstance("task_properties"); } /* // Old floater properties LLFloaterReg::showInstance("inspect", LLSD()); */ } //--------------------------------------------------------------------------- // Land pie menu //--------------------------------------------------------------------------- class LLLandBuild : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerParcelMgr::getInstance()->deselectLand(); if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) { // zoom in if we're looking at the avatar gAgentCamera.setFocusOnAvatar(false, ANIMATE); gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgentCamera.cameraZoomIn(0.666f); gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); gViewerWindow->moveCursorToCenter(); } else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { // otherwise just move focus gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); // Could be first use //LLFirstUse::useBuild(); return true; } }; class LLLandBuyPass : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLPanelLandGeneral::onClickBuyPass((void *)false); return true; } }; class LLLandEnableBuyPass : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLPanelLandGeneral::enableBuyPass(nullptr); return new_value; } }; bool enable_object_edit() { if (!isAgentAvatarValid()) return false; // *HACK: The new "prelude" Help Islands have a build sandbox area, // so users need the Edit and Create pie menu options when they are // there. Eventually this needs to be replaced with code that only // lets you edit objects if you have permission to do so (edit perms, // group edit, god). See also lltoolbar.cpp. JC bool enable = false; if (gAgent.inPrelude()) { enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() || LLSelectMgr::getInstance()->getSelection()->isAttachment(); } else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound()) { enable = true; } return enable; } bool enable_mute_particle() { const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID(); } bool enable_object_select_in_pathfinding_linksets() { return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); } bool visible_object_select_in_pathfinding_linksets() { return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); } bool enable_object_select_in_pathfinding_characters() { return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); } bool enable_os_exception() { #if LL_DARWIN return true; #else return false; #endif } bool enable_gltf() { static LLCachedControl enablegltf(gSavedSettings, "GLTFEnabled", false); static LLCachedControl can_use(gSavedSettings, "RenderCanUseGLTFPBROpaqueShaders", true); return enablegltf && can_use; } bool enable_gltf_save_as() { if (enable_gltf()) { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); if (obj) { if (obj->mGLTFAsset && obj->mGLTFAsset->isLocalPreview()) { return true; } LLPermissions* permissions = LLSelectMgr::getInstance()->findObjectPermissions(obj); if (permissions) { return permissions->allowExportBy(gAgent.getID()); } } } return false; } bool enable_gltf_upload() { return enable_gltf_save_as(); } bool enable_terrain_local_paintmap() { static LLCachedControl can_use_shaders(gSavedSettings, "RenderCanUseTerrainBakeShaders", true); return can_use_shaders; } class LLSelfRemoveAllAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar(); return true; } }; class LLSelfEnableRemoveAllAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = false; if (isAgentAvatarValid()) { for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; if (attachment->getNumObjects() > 0) { new_value = true; break; } } } return new_value; } }; bool enable_has_attachments() { return false; } //--------------------------------------------------------------------------- // Avatar pie menu //--------------------------------------------------------------------------- //void handle_follow(void *userdata) //{ // // follow a given avatar by ID // LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); // if (objectp) // { // gAgent.startFollowPilot(objectp->getID()); // } //} bool enable_object_mute() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return false; LLVOAvatar* avatar = find_avatar_from_object(object); if (avatar) { // It's an avatar LLNameValue *lastname = avatar->getNVPair("LastName"); bool is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); bool is_self = avatar->isSelf(); return !is_linden && !is_self; } else { // Just a regular object return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && !LLMuteList::getInstance()->isMuted(object->getID()); } } bool enable_object_unmute() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return false; LLVOAvatar* avatar = find_avatar_from_object(object); if (avatar) { // It's an avatar LLNameValue *lastname = avatar->getNVPair("LastName"); bool is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); bool is_self = avatar->isSelf(); return !is_linden && !is_self; } else { // Just a regular object return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && LLMuteList::getInstance()->isMuted(object->getID());; } } // 0 = normal, 1 = always, 2 = never class LLAvatarCheckImpostorMode : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return false; LLVOAvatar* avatar = find_avatar_from_object(object); if (!avatar) return false; U32 mode = userdata.asInteger(); switch (mode) { case 0: return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_RENDER_NORMALLY); case 1: return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER); case 2: return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER); case 4: return (avatar->getVisualMuteSettings() != LLVOAvatar::AV_RENDER_NORMALLY); default: return false; } } // handleEvent() }; // 0 = normal, 1 = always, 2 = never class LLAvatarSetImpostorMode : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return false; LLVOAvatar* avatar = find_avatar_from_object(object); if (!avatar) return false; U32 mode = userdata.asInteger(); switch (mode) { case 0: avatar->setVisualMuteSettings(LLVOAvatar::AV_RENDER_NORMALLY); break; case 1: avatar->setVisualMuteSettings(LLVOAvatar::AV_DO_NOT_RENDER); break; case 2: avatar->setVisualMuteSettings(LLVOAvatar::AV_ALWAYS_RENDER); break; default: return false; } LLVOAvatar::cullAvatarsByPixelArea(); return true; } // handleEvent() }; class LLObjectMute : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (!object) return true; LLUUID id; std::string name; LLMute::EType type; LLVOAvatar* avatar = find_avatar_from_object(object); if (avatar) { avatar->mNeedsImpostorUpdate = true; avatar->mLastImpostorUpdateReason = 9; id = avatar->getID(); LLNameValue *firstname = avatar->getNVPair("FirstName"); LLNameValue *lastname = avatar->getNVPair("LastName"); if (firstname && lastname) { name = LLCacheName::buildFullName( firstname->getString(), lastname->getString()); } type = LLMute::AGENT; } else { // it's an object id = object->getID(); LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node) { name = node->mName; } type = LLMute::OBJECT; } LLMute mute(id, name, type); if (LLMuteList::getInstance()->isMuted(mute.mID)) { LLMuteList::getInstance()->remove(mute); } else { LLMuteList::getInstance()->add(mute); LLPanelBlockedList::showPanelAndSelect(mute.mID); } return true; } }; bool handle_go_to() { // try simulator autopilot std::vector strings; std::string val; LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; val = llformat("%g", pos.mdV[VX]); strings.push_back(val); val = llformat("%g", pos.mdV[VY]); strings.push_back(val); val = llformat("%g", pos.mdV[VZ]); strings.push_back(val); send_generic_message("autopilot", strings); LLViewerParcelMgr::getInstance()->deselectLand(); if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera")) { gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID()); } else { // Snap camera back to behind avatar gAgentCamera.setFocusOnAvatar(true, ANIMATE); } // Could be first use //LLFirstUse::useGoTo(); return true; } class LLGoToObject : public view_listener_t { bool handleEvent(const LLSD& userdata) { return handle_go_to(); } }; class LLAvatarReportAbuse : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) { LLFloaterReporter::showFromObject(avatar->getID()); } return true; } }; //--------------------------------------------------------------------------- // Parcel freeze, eject, etc. //--------------------------------------------------------------------------- bool callback_freeze(const LLSD& notification, const LLSD& response) { LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option || 1 == option) { U32 flags = 0x0; if (1 == option) { // unfreeze flags |= 0x1; } LLMessageSystem* msg = gMessageSystem; LLViewerObject* avatar = gObjectList.findObject(avatar_id); if (avatar) { msg->newMessage("FreezeUser"); msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("Data"); msg->addUUID("TargetID", avatar_id ); msg->addU32("Flags", flags ); msg->sendReliable( avatar->getRegion()->getHost() ); } } return false; } void handle_avatar_freeze(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar LLVOAvatar* avatar = NULL; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); } else { avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); } if( avatar ) { std::string fullname = avatar->getFullname(); LLSD payload; payload["avatar_id"] = avatar->getID(); if (!fullname.empty()) { LLSD args; args["AVATAR_NAME"] = fullname; LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, callback_freeze); } else { LLNotificationsUtil::add("FreezeAvatar", LLSD(), payload, callback_freeze); } } } class LLAvatarVisibleDebug : public view_listener_t { bool handleEvent(const LLSD& userdata) { return gAgent.isGodlike(); } }; class LLAvatarDebug : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if( avatar ) { if (avatar->isSelf()) { ((LLVOAvatarSelf *)avatar)->dumpLocalTextures(); } LL_INFOS() << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << LL_ENDL; std::vector strings; strings.push_back(avatar->getID().asString()); LLUUID invoice; send_generic_message("dumptempassetdata", strings, invoice); LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) ); } return true; } }; bool callback_eject(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (2 == option) { // Cancel button. return false; } LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean(); if (0 == option) { // Eject button LLMessageSystem* msg = gMessageSystem; LLViewerObject* avatar = gObjectList.findObject(avatar_id); if (avatar) { U32 flags = 0x0; msg->newMessage("EjectUser"); msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID() ); msg->addUUID("SessionID", gAgent.getSessionID() ); msg->nextBlock("Data"); msg->addUUID("TargetID", avatar_id ); msg->addU32("Flags", flags ); msg->sendReliable( avatar->getRegion()->getHost() ); } } else if (ban_enabled) { // This is tricky. It is similar to say if it is not an 'Eject' button, // and it is also not an 'Cancle' button, and ban_enabled==ture, // it should be the 'Eject and Ban' button. LLMessageSystem* msg = gMessageSystem; LLViewerObject* avatar = gObjectList.findObject(avatar_id); if (avatar) { U32 flags = 0x1; msg->newMessage("EjectUser"); msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID() ); msg->addUUID("SessionID", gAgent.getSessionID() ); msg->nextBlock("Data"); msg->addUUID("TargetID", avatar_id ); msg->addU32("Flags", flags ); msg->sendReliable( avatar->getRegion()->getHost() ); } } return false; } void handle_avatar_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar LLVOAvatar* avatar = NULL; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); } else { avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); } if( avatar ) { LLSD payload; payload["avatar_id"] = avatar->getID(); std::string fullname = avatar->getFullname(); const LLVector3d& pos = avatar->getPositionGlobal(); LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED)) { payload["ban_enabled"] = true; if (!fullname.empty()) { LLSD args; args["AVATAR_NAME"] = fullname; LLNotificationsUtil::add("EjectAvatarFullname", args, payload, callback_eject); } else { LLNotificationsUtil::add("EjectAvatarFullname", LLSD(), payload, callback_eject); } } else { payload["ban_enabled"] = false; if (!fullname.empty()) { LLSD args; args["AVATAR_NAME"] = fullname; LLNotificationsUtil::add("EjectAvatarFullnameNoBan", args, payload, callback_eject); } else { LLNotificationsUtil::add("EjectAvatarNoBan", LLSD(), payload, callback_eject); } } } } bool my_profile_visible() { LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID); return floaterp && floaterp->isInVisibleChain(); } bool picks_tab_visible() { return my_profile_visible() && LLAvatarActions::isPickTabSelected(gAgentID); } bool enable_freeze_eject(const LLSD& avatar_id) { // Use avatar_id if available, otherwise default to right-click avatar LLVOAvatar* avatar = NULL; if (avatar_id.asUUID().notNull()) { avatar = find_avatar_from_object(avatar_id.asUUID()); } else { avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); } if (!avatar) return false; // Gods can always freeze if (gAgent.isGodlike()) return true; // Estate owners / managers can freeze // Parcel owners can also freeze const LLVector3& pos = avatar->getPositionRegion(); const LLVector3d& pos_global = avatar->getPositionGlobal(); LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); LLViewerRegion* region = avatar->getRegion(); if (!region) return false; bool new_value = region->isOwnedSelf(pos); if (!new_value || region->isOwnedGroup(pos)) { new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); } return new_value; } bool callback_leave_group(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_LeaveGroupRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_GroupData); msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); gAgent.sendReliableMessage(); } return false; } void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt) { LLAggregatePermissions::EValue val = ag_perm.getValue(bit); std::string buffer; switch(val) { case LLAggregatePermissions::AP_NONE: buffer = llformat( "* %s None\n", txt); break; case LLAggregatePermissions::AP_SOME: buffer = llformat( "* %s Some\n", txt); break; case LLAggregatePermissions::AP_ALL: buffer = llformat( "* %s All\n", txt); break; case LLAggregatePermissions::AP_EMPTY: default: break; } string.append(buffer); } bool enable_buy_object() { // In order to buy, there must only be 1 purchaseable object in // the selection manager. if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false; LLViewerObject* obj = NULL; LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if(node) { obj = node->getObject(); if(!obj) return false; if( for_sale_selection(node) ) { // *NOTE: Is this needed? This checks to see if anyone owns the // object, dating back to when we had "public" objects owned by // no one. JC if(obj->permAnyOwner()) return true; } } return false; } // Note: This will only work if the selected object's data has been // received by the viewer and cached in the selection manager. void handle_buy_object(LLSaleInfo sale_info) { if(!LLSelectMgr::getInstance()->selectGetAllRootsValid()) { LLNotificationsUtil::add("UnableToBuyWhileDownloading"); return; } LLUUID owner_id; std::string owner_name; bool owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); if (!owners_identical) { LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners"); return; } LLPermissions perm; bool valid = LLSelectMgr::getInstance()->selectGetPermissions(perm); LLAggregatePermissions ag_perm; valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm); if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID())) { LLNotificationsUtil::add("ObjectNotForSale"); return; } LLFloaterBuy::show(sale_info); } void handle_buy_contents(LLSaleInfo sale_info) { LLFloaterBuyContents::show(sale_info); } void handle_region_dump_temp_asset_data() { LL_INFOS() << "Dumping temporary asset data to simulator logs" << LL_ENDL; std::vector strings; LLUUID invoice; send_generic_message("dumptempassetdata", strings, invoice); } void handle_region_clear_temp_asset_data() { LL_INFOS() << "Clearing temporary asset data" << LL_ENDL; std::vector strings; LLUUID invoice; send_generic_message("cleartempassetdata", strings, invoice); } void handle_region_dump_settings() { LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) { LL_INFOS() << "Damage: " << (regionp->getAllowDamage() ? "on" : "off") << LL_ENDL; LL_INFOS() << "Landmark: " << (regionp->getAllowLandmark() ? "on" : "off") << LL_ENDL; LL_INFOS() << "SetHome: " << (regionp->getAllowSetHome() ? "on" : "off") << LL_ENDL; LL_INFOS() << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << LL_ENDL; LL_INFOS() << "SunFixed: " << (regionp->getSunFixed() ? "on" : "off") << LL_ENDL; LL_INFOS() << "BlockFly: " << (regionp->getBlockFly() ? "on" : "off") << LL_ENDL; LL_INFOS() << "AllowP2P: " << (regionp->getAllowDirectTeleport() ? "on" : "off") << LL_ENDL; LL_INFOS() << "Water: " << (regionp->getWaterHeight()) << LL_ENDL; } } void handle_dump_group_info() { gAgent.dumpGroupInfo(); } void handle_dump_capabilities_info() { LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) { regionp->logActiveCapabilities(); } } void handle_dump_region_object_cache() { LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) { regionp->dumpCache(); } } void handle_reset_interest_lists() { // Check all regions and reset their interest list for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion *regionp = *iter; if (regionp && regionp->isAlive() && regionp->capabilitiesReceived()) { regionp->resetInterestList(); } } } void handle_dump_focus() { LLUICtrl *ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL; } class LLSelfStandUp : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgent.standUp(); return true; } }; bool enable_standup_self() { return isAgentAvatarValid() && gAgentAvatarp->isSitting(); } class LLSelfSitDown : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgent.sitDown(); return true; } }; bool show_sitdown_self() { return isAgentAvatarValid() && !gAgentAvatarp->isSitting(); } bool enable_sitdown_self() { return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); } class LLSelfToggleSitStand : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (isAgentAvatarValid()) { if (gAgentAvatarp->isSitting()) { gAgent.standUp(); } else { gAgent.sitDown(); } } return true; } }; bool enable_sit_stand() { return enable_sitdown_self() || enable_standup_self(); } bool enable_fly_land() { return gAgent.getFlying() || LLAgent::enableFlying(); } class LLCheckPanelPeopleTab : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string panel_name = userdata.asString(); LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); if(panel && panel->isInVisibleChain()) { return true; } return false; } }; // Toggle one of "People" panel tabs in side tray. class LLTogglePanelPeopleTab : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string panel_name = userdata.asString(); LLSD param; param["people_panel_tab_name"] = panel_name; if ( panel_name == "friends_panel" || panel_name == "groups_panel" || panel_name == "nearby_panel" || panel_name == "blocked_panel") { return togglePeoplePanel(panel_name, param); } else { return false; } } static bool togglePeoplePanel(const std::string& panel_name, const LLSD& param) { LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); if(!panel) return false; if (panel->isInVisibleChain()) { LLFloaterReg::hideInstance("people"); } else { LLFloaterSidePanelContainer::showPanel("people", "panel_people", param) ; } return true; } }; bool check_admin_override() { return gAgent.getAdminOverride(); } void handle_admin_override_toggle() { gAgent.setAdminOverride(!gAgent.getAdminOverride()); // The above may have affected which debug menus are visible show_debug_menus(); } void handle_visual_leak_detector_toggle() { static bool vld_enabled = false; if ( vld_enabled ) { #ifdef INCLUDE_VLD // only works for debug builds (hard coded into vld.h) #ifdef _DEBUG // start with Visual Leak Detector turned off VLDDisable(); #endif // _DEBUG #endif // INCLUDE_VLD vld_enabled = false; } else { #ifdef INCLUDE_VLD // only works for debug builds (hard coded into vld.h) #ifdef _DEBUG // start with Visual Leak Detector turned off VLDEnable(); #endif // _DEBUG #endif // INCLUDE_VLD vld_enabled = true; }; } void handle_god_mode() { gAgent.requestEnterGodMode(); } void handle_leave_god_mode() { gAgent.requestLeaveGodMode(); } void set_god_level(U8 god_level) { U8 old_god_level = gAgent.getGodLevel(); gAgent.setGodLevel( god_level ); LLViewerParcelMgr::getInstance()->notifyObservers(); // God mode changes region visibility LLWorldMap::getInstance()->reloadItems(true); // inventory in items may change in god mode gObjectList.dirtyAllObjectInventory(); if(gViewerWindow) { gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT, LLGridManager::getInstance()->isInProductionGrid()); } LLSD args; if(god_level > GOD_NOT) { args["LEVEL"] = llformat("%d",(S32)god_level); LLNotificationsUtil::add("EnteringGodMode", args); } else { args["LEVEL"] = llformat("%d",(S32)old_god_level); LLNotificationsUtil::add("LeavingGodMode", args); } // changing god-level can affect which menus we see show_debug_menus(); // changing god-level can invalidate search results LLFloaterSearch *search = dynamic_cast(LLFloaterReg::getInstance("search")); if (search) { search->godLevelChanged(god_level); } } #ifdef TOGGLE_HACKED_GODLIKE_VIEWER void handle_toggle_hacked_godmode() { gHackGodmode = !gHackGodmode; set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT); } bool check_toggle_hacked_godmode() { return gHackGodmode; } bool enable_toggle_hacked_godmode() { return !LLGridManager::getInstance()->isInProductionGrid(); } #endif void process_grant_godlike_powers(LLMessageSystem* msg, void**) { LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); LLUUID session_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID())) { U8 god_level; msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level); set_god_level(god_level); } else { LL_WARNS() << "Grant godlike for wrong agent " << agent_id << LL_ENDL; } } bool is_agent_mappable(const LLUUID& agent_id) { const LLRelationship* buddy_info = NULL; bool is_friend = LLAvatarActions::isFriend(agent_id); if (is_friend) buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id); return (buddy_info && buddy_info->isOnline() && buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) ); } // Enable a menu item when you don't have someone's card. class LLAvatarEnableAddFriend : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID()); return new_value; } }; void request_friendship(const LLUUID& dest_id) { LLViewerObject* dest = gObjectList.findObject(dest_id); if(dest && dest->isAvatar()) { std::string full_name; LLNameValue* nvfirst = dest->getNVPair("FirstName"); LLNameValue* nvlast = dest->getNVPair("LastName"); if(nvfirst && nvlast) { full_name = LLCacheName::buildFullName( nvfirst->getString(), nvlast->getString()); } if (!full_name.empty()) { LLAvatarActions::requestFriendshipDialog(dest_id, full_name); } else { LLNotificationsUtil::add("CantOfferFriendship"); } } } class LLEditEnableCustomizeAvatar : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gAgentWearables.areWearablesLoaded(); return new_value; } }; class LLEnableEditShape : public view_listener_t { bool handleEvent(const LLSD& userdata) { return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); } }; class LLEnableHoverHeight : public view_listener_t { bool handleEvent(const LLSD& userdata) { return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled(); } }; class LLEnableEditPhysics : public view_listener_t { bool handleEvent(const LLSD& userdata) { //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); return true; } }; bool is_object_sittable() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (object && object->getPCode() == LL_PCODE_VOLUME) { return true; } else { return false; } } // only works on pie menu void handle_object_sit(LLViewerObject* object, const LLVector3& offset) { // get object selection offset if (object && object->getPCode() == LL_PCODE_VOLUME) { gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlockFast(_PREHASH_TargetObject); gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); gMessageSystem->addVector3Fast(_PREHASH_Offset, offset); object->getRegion()->sendReliableMessage(); } } void handle_object_sit_or_stand() { LLPickInfo pick = LLToolPie::getInstance()->getPick(); LLViewerObject *object = pick.getObject(); if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) { return; } if (sitting_on_selection()) { gAgent.standUp(); return; } handle_object_sit(object, pick.mObjectOffset); } void handle_object_sit(const LLUUID& object_id) { LLViewerObject* obj = gObjectList.findObject(object_id); if (!obj) { return; } LLVector3 offset(0, 0, 0); handle_object_sit(obj, offset); } void near_sit_down_point(bool success, void*) { if (success) { gAgent.setFlying(false); gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); } } class LLLandSit : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgent.isSitting()) { gAgent.standUp(); } LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; LLQuaternion target_rot; if (isAgentAvatarValid()) { target_rot = gAgentAvatarp->getRotation(); } else { target_rot = gAgent.getFrameAgent().getQuaternion(); } gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f); return true; } }; class LLLandCanSit : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; return !posGlobal.isExactlyZero(); // valid position, not beyond draw distance } }; //------------------------------------------------------------------- // Help menu functions //------------------------------------------------------------------- // // Major mode switching // void reset_view_final(bool proceed); void handle_reset_view() { if (gAgentCamera.cameraCustomizeAvatar()) { // switching to outfit selector should automagically save any currently edited wearable LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } gAgentCamera.setFocusOnAvatar(true, false, false); reset_view_final(true); LLFloaterCamera::resetCameraMode(); } class LLViewResetView : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_reset_view(); return true; } }; // Note: extra parameters allow this function to be called from dialog. void reset_view_final(bool proceed) { if( !proceed ) { return; } gAgentCamera.resetView(true, true); gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); } class LLViewLookAtLastChatter : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgentCamera.lookAtLastChat(); return true; } }; class LLViewMouselook : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (!gAgentCamera.cameraMouselook()) { gAgentCamera.changeCameraToMouselook(); } else { gAgentCamera.changeCameraToDefault(); } return true; } }; class LLViewDefaultUISize : public view_listener_t { bool handleEvent(const LLSD& userdata) { gSavedSettings.setF32("UIScaleFactor", 1.0f); gSavedSettings.setBOOL("UIAutoScale", false); gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); return true; } }; class LLViewToggleUI : public view_listener_t { bool handleEvent(const LLSD& userdata) { if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) { LLNotification::Params params("ConfirmHideUI"); params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); LLSD substitutions; #if LL_DARWIN substitutions["SHORTCUT"] = "Cmd+Shift+U"; #else substitutions["SHORTCUT"] = "Ctrl+Shift+U"; #endif params.substitutions = substitutions; if (!gSavedSettings.getBOOL("HideUIControls")) { // hiding, so show notification LLNotifications::instance().add(params); } else { LLNotifications::instance().forceResponse(params, 0); } } return true; } void confirm(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) // OK { gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls")); LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls")); gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls")); } } }; void handle_object_owner_permissive() { // only send this if they're a god. if(gAgent.isGodlike()) { // do the objects. LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, true, PERM_ALL, true); LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, true, PERM_ALL, true); } } void handle_object_owner_self() { // only send this if they're a god. if(gAgent.isGodlike()) { LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), true); } } // Shortcut to set owner permissions to not editable. void handle_object_lock() { LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, false, PERM_MODIFY); } void handle_object_asset_ids() { // only send this if they're a god. if (gAgent.isGodlike()) { LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids"); } } void handle_force_parcel_owner_to_me() { LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() ); } void handle_force_parcel_to_content() { LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent(); } void handle_claim_public_land() { if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion()) { LLNotificationsUtil::add("ClaimPublicLand"); return; } LLVector3d west_south_global; LLVector3d east_north_global; LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global); LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global); LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global); LLMessageSystem* msg = gMessageSystem; msg->newMessage("GodlikeMessage"); msg->nextBlock("AgentData"); msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used msg->nextBlock("MethodData"); msg->addString("Method", "claimpublicland"); msg->addUUID("Invoice", LLUUID::null); std::string buffer; buffer = llformat( "%f", west_south.mV[VX]); msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); buffer = llformat( "%f", west_south.mV[VY]); msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); buffer = llformat( "%f", east_north.mV[VX]); msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); buffer = llformat( "%f", east_north.mV[VY]); msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); gAgent.sendReliableMessage(); } // HACK for easily testing new avatar geometry void handle_god_request_avatar_geometry() { if (gAgent.isGodlike()) { LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", ""); } } static bool get_derezzable_objects( EDeRezDestination dest, std::string& error, LLViewerRegion*& first_region, std::vector* derez_objectsp, bool only_check = false) { bool found = false; LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); if (derez_objectsp) derez_objectsp->reserve(selection->getRootObjectCount()); // Check conditions that we can't deal with, building a list of // everything that we'll actually be derezzing. for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin(); iter != selection->valid_root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); LLViewerRegion* region = object->getRegion(); if (!first_region) { first_region = region; } else { if(region != first_region) { // Derez doesn't work at all if the some of the objects // are in regions besides the first object selected. // ...crosses region boundaries error = "AcquireErrorObjectSpan"; break; } } if (object->isAvatar()) { // ...don't acquire avatars continue; } // If AssetContainers are being sent back, they will appear as // boxes in the owner's inventory. if (object->getNVPair("AssetContainer") && dest != DRD_RETURN_TO_OWNER) { // this object is an asset container, derez its contents, not it LL_WARNS() << "Attempt to derez deprecated AssetContainer object type not supported." << LL_ENDL; /* object->requestInventory(container_inventory_arrived, (void *)(bool)(DRD_TAKE_INTO_AGENT_INVENTORY == dest)); */ continue; } bool can_derez_current = false; switch(dest) { case DRD_TAKE_INTO_AGENT_INVENTORY: case DRD_TRASH: if (!object->isPermanentEnforced() && ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)))) { can_derez_current = true; } break; case DRD_RETURN_TO_OWNER: if(!object->isAttachment()) { can_derez_current = true; } break; default: if((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permCopy()) || gAgent.isGodlike()) { can_derez_current = true; } break; } if(can_derez_current) { found = true; if (only_check) // one found, no need to traverse to the end break; if (derez_objectsp) derez_objectsp->push_back(object); } } return found; } static bool can_derez(EDeRezDestination dest) { LLViewerRegion* first_region = NULL; std::string error; return get_derezzable_objects(dest, error, first_region, NULL, true); } static void derez_objects( EDeRezDestination dest, const LLUUID& dest_id, LLViewerRegion*& first_region, std::string& error, std::vector* objectsp) { std::vector derez_objects; if (!objectsp) // if objects to derez not specified { // get them from selection if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false)) { LL_WARNS() << "No objects to derez" << LL_ENDL; return; } objectsp = &derez_objects; } if(gAgentCamera.cameraMouselook()) { gAgentCamera.changeCameraToDefault(); } // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per // root. I lopped off a few (33) to provide a bit // pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs. // This gives us a maximum of 63500 root objects - which should // satisfy anybody. const S32 MAX_ROOTS_PER_PACKET = 250; const S32 MAX_PACKET_COUNT = 254; F32 packets = ceil((F32)objectsp->size() / (F32)MAX_ROOTS_PER_PACKET); if(packets > (F32)MAX_PACKET_COUNT) { error = "AcquireErrorTooManyObjects"; } if(error.empty() && objectsp->size() > 0) { U8 d = (U8)dest; LLUUID tid; tid.generate(); U8 packet_count = (U8)packets; S32 object_index = 0; S32 objects_in_packet = 0; LLMessageSystem* msg = gMessageSystem; for(U8 packet_number = 0; packet_number < packet_count; ++packet_number) { msg->newMessageFast(_PREHASH_DeRezObject); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_AgentBlock); msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); msg->addU8Fast(_PREHASH_Destination, d); msg->addUUIDFast(_PREHASH_DestinationID, dest_id); msg->addUUIDFast(_PREHASH_TransactionID, tid); msg->addU8Fast(_PREHASH_PacketCount, packet_count); msg->addU8Fast(_PREHASH_PacketNumber, packet_number); objects_in_packet = 0; while((object_index < objectsp->size()) && (objects_in_packet++ < MAX_ROOTS_PER_PACKET)) { LLViewerObject* object = objectsp->at(object_index++); msg->nextBlockFast(_PREHASH_ObjectData); msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); // VEFFECT: DerezObject LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, true); effectp->setPositionGlobal(object->getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); } msg->sendReliable(first_region->getHost()); } make_ui_sound("UISndObjectRezOut"); // Busy count decremented by inventory update, so only increment // if will be causing an update. if (dest != DRD_RETURN_TO_OWNER) { gViewerWindow->getWindow()->incBusyCount(); } } else if(!error.empty()) { LLNotificationsUtil::add(error); } } static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) { LLViewerRegion* first_region = NULL; std::string error; derez_objects(dest, dest_id, first_region, error, NULL); } static void derez_objects_separate(EDeRezDestination dest, const LLUUID &dest_id) { std::vector derez_object_list; std::string error; LLViewerRegion* first_region = NULL; if (!get_derezzable_objects(dest, error, first_region, &derez_object_list, false)) { LL_WARNS() << "No objects to derez" << LL_ENDL; return; } for (LLViewerObject *opjectp : derez_object_list) { std::vector buf_list; buf_list.push_back(opjectp); derez_objects(dest, dest_id, first_region, error, &buf_list); } } void handle_take_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); } void handle_take_separate_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); derez_objects_separate(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); } void handle_link_objects() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) { LLFloaterReg::toggleInstanceOrBringToFront("places"); } else { LLSelectMgr::getInstance()->linkObjects(); } } // You can return an object to its owner if it is on your land. class LLObjectReturn : public view_listener_t { public: LLObjectReturn() : mFirstRegion() {} private: bool handleEvent(const LLSD& userdata) { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects); LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); return true; } bool onReturnToOwner(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { // Ignore category ID for this derez destination. derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects); } mReturnableObjects.clear(); mError.clear(); mFirstRegion = NULL; // drop reference to current selection mObjectSelection = NULL; return false; } LLObjectSelectionHandle mObjectSelection; std::vector mReturnableObjects; std::string mError; LLViewerRegion* mFirstRegion; }; // Allow return to owner if one or more of the selected items is // over land you own. class LLObjectEnableReturn : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) { // Do not enable if nothing selected return false; } #ifdef HACKED_GODLIKE_VIEWER bool new_value = true; #else bool new_value = false; if (gAgent.isGodlike()) { new_value = true; } else { new_value = can_derez(DRD_RETURN_TO_OWNER); } #endif return new_value; } }; void force_take_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id); } void handle_take(bool take_separate) { // we want to use the folder this was derezzed from if it's // available. Otherwise, derez to the normal place. if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) { return; } bool you_own_everything = true; bool locked_but_takeable_object = false; LLUUID category_id; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); if(object) { if(!object->permYouOwner()) { you_own_everything = false; } if(!object->permMove()) { locked_but_takeable_object = true; } } if(node->mFolderID.notNull()) { if(category_id.isNull()) { category_id = node->mFolderID; } else if(category_id != node->mFolderID) { // we have found two potential destinations. break out // now and send to the default location. category_id.setNull(); break; } } } if(category_id.notNull()) { // there is an unambiguous destination. See if this agent has // such a location and it is not in the trash or library if(!gInventory.getCategory(category_id)) { // nope, set to NULL. category_id.setNull(); } if(category_id.notNull()) { // check trash const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash)) { category_id.setNull(); } // check library if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID())) { category_id.setNull(); } // check inbox const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); if (category_id == inbox_id || gInventory.isObjectDescendentOf(category_id, inbox_id)) { category_id.setNull(); } } } if(category_id.isNull()) { category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); } LLSD payload; payload["folder_id"] = category_id; LLNotification::Params params("ConfirmObjectTakeLock"); params.payload(payload); // MAINT-290 // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened params.functor.function([take_separate](const LLSD ¬ification, const LLSD &response) { if (take_separate) { confirm_take_separate(notification, response, LLSelectMgr::instance().getSelection()); } else { confirm_take(notification, response, LLSelectMgr::instance().getSelection()); } }); if (locked_but_takeable_object || !you_own_everything) { if(locked_but_takeable_object && you_own_everything) { params.name("ConfirmObjectTakeLock"); } else if(!locked_but_takeable_object && !you_own_everything) { params.name("ConfirmObjectTakeNoOwn"); } else { params.name("ConfirmObjectTakeLockNoOwn"); } LLNotifications::instance().add(params); } else { LLNotifications::instance().forceResponse(params, 0); } } void handle_object_show_inspector() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLViewerObject* objectp = selection->getFirstRootObject(true); if (!objectp) { return; } LLSD params; params["object_id"] = objectp->getID(); LLFloaterReg::showInstance("inspect_object", params); } void handle_avatar_show_inspector() { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) { LLSD params; params["avatar_id"] = avatar->getID(); LLFloaterReg::showInstance("inspect_avatar", params); } } bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(enable_take() && (option == 0)) { derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID()); } return false; } bool confirm_take_separate(const LLSD ¬ification, const LLSD &response, LLObjectSelectionHandle selection_handle) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (enable_take() && (option == 0)) { derez_objects_separate(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID()); } return false; } // You can take an item when it is public and transferrable, or when // you own it. We err on the side of enabling the item when at least // one item selected can be copied to inventory. bool enable_take() { if (sitting_on_selection()) { return false; } for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); if (object->isAvatar()) { // ...don't acquire avatars continue; } #ifdef HACKED_GODLIKE_VIEWER return true; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (!LLGridManager::getInstance()->isInProductionGrid() && gAgent.isGodlike()) { return true; } # endif if(!object->isPermanentEnforced() && ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) || (node->mPermissions->getOwner() == gAgent.getID()))) { return !object->isAttachment(); } #endif } return false; } void handle_buy_or_take() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) { return; } if (is_selection_buy_not_take()) { S32 total_price = selection_price(); if (total_price <= gStatusBar->getBalance() || total_price == 0) { handle_buy(); } else { LLStringUtil::format_map_t args; args["AMOUNT"] = llformat("%d", total_price); LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price ); } } else { handle_take(); } } bool visible_buy_object() { return is_selection_buy_not_take() && enable_buy_object(); } bool visible_take_object() { return !is_selection_buy_not_take() && enable_take(); } bool is_multiple_selection() { return (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1); } bool is_single_selection() { return !is_multiple_selection(); } bool enable_take_objects() { return visible_take_object() && is_multiple_selection(); } bool tools_visible_buy_object() { return is_selection_buy_not_take(); } bool tools_visible_take_object() { return !is_selection_buy_not_take(); } class LLToolsEnableBuyOrTake : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool is_buy = is_selection_buy_not_take(); bool new_value = is_buy ? enable_buy_object() : enable_take(); return new_value; } }; // This is a small helper function to determine if we have a buy or a // take in the selection. This method is to help with the aliasing // problems of putting buy and take in the same pie menu space. After // a fair amont of discussion, it was determined to prefer buy over // take. The reasoning follows from the fact that when users walk up // to buy something, they will click on one or more items. Thus, if // anything is for sale, it becomes a buy operation, and the server // will group all of the buy items, and copyable/modifiable items into // one package and give the end user as much as the permissions will // allow. If the user wanted to take something, they will select fewer // and fewer items until only 'takeable' items are left. The one // exception is if you own everything in the selection that is for // sale, in this case, you can't buy stuff from yourself, so you can // take it. // return value = true if selection is a 'buy'. // false if selection is a 'take' bool is_selection_buy_not_take() { for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* obj = node->getObject(); if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) { // you do not own the object and it is for sale, thus, // it's a buy return true; } } return false; } S32 selection_price() { S32 total_price = 0; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* obj = node->getObject(); if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) { // you do not own the object and it is for sale. // Add its price. total_price += node->mSaleInfo.getSalePrice(); } } return total_price; } /* bool callback_show_buy_currency(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { LL_INFOS() << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << LL_ENDL; LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")); } return false; } */ void show_buy_currency(const char* extra) { // Don't show currency web page for branded clients. /* std::ostringstream mesg; if (extra != NULL) { mesg << extra << "\n \n"; } mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?"; */ LLSD args; if (extra != NULL) { args["EXTRA"] = extra; } LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency); } void handle_buy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; LLSaleInfo sale_info; bool valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); if (!valid) return; S32 price = sale_info.getSalePrice(); if (price > 0 && price > gStatusBar->getBalance()) { LLStringUtil::format_map_t args; args["AMOUNT"] = llformat("%d", price); LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price ); return; } if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS) { handle_buy_contents(sale_info); } else { handle_buy_object(sale_info); } } bool anyone_copy_selection(LLSelectNode* nodep) { bool perm_copy = (bool)(nodep->getObject()->permCopy()); bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY); return perm_copy && all_copy; } bool for_sale_selection(LLSelectNode* nodep) { return nodep->mSaleInfo.isForSale() && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER && (nodep->mPermissions->getMaskOwner() & PERM_COPY || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY); } bool sitting_on_selection() { LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (!node) { return false; } if (!node->mValid) { return false; } LLViewerObject* root_object = node->getObject(); if (!root_object) { return false; } // Need to determine if avatar is sitting on this object if (!isAgentAvatarValid()) return false; return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object); } class LLToolsSaveToObjectInventory : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if(node && (node->mValid) && (!node->mFromTaskID.isNull())) { // *TODO: check to see if the fromtaskid object exists. derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID); } return true; } }; class LLToolsEnablePathfinding : public view_listener_t { bool handleEvent(const LLSD& userdata) { return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); } }; class LLToolsEnablePathfindingView : public view_listener_t { bool handleEvent(const LLSD& userdata) { return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); } }; class LLToolsDoPathfindingRebakeRegion : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL); if (hasPathfinding) { LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); } return hasPathfinding; } }; class LLToolsEnablePathfindingRebakeRegion : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool returnValue = false; if (LLNavigationBar::instanceExists()) { returnValue = LLNavigationBar::getInstance()->isRebakeNavMeshAvailable(); } return returnValue; } }; // Round the position of all root objects to the grid class LLToolsSnapObjectXY : public view_listener_t { bool handleEvent(const LLSD& userdata) { F64 snap_size = (F64)gSavedSettings.getF32("GridResolution"); for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* obj = node->getObject(); if (obj->permModify()) { LLVector3d pos_global = obj->getPositionGlobal(); F64 round_x = fmod(pos_global.mdV[VX], snap_size); if (round_x < snap_size * 0.5) { // closer to round down pos_global.mdV[VX] -= round_x; } else { // closer to round up pos_global.mdV[VX] -= round_x; pos_global.mdV[VX] += snap_size; } F64 round_y = fmod(pos_global.mdV[VY], snap_size); if (round_y < snap_size * 0.5) { pos_global.mdV[VY] -= round_y; } else { pos_global.mdV[VY] -= round_y; pos_global.mdV[VY] += snap_size; } obj->setPositionGlobal(pos_global, false); } } LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); return true; } }; // Determine if the option to cycle between linked prims is shown class LLToolsEnableSelectNextPart : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = (!LLSelectMgr::getInstance()->getSelection()->isEmpty() && (gSavedSettings.getBOOL("EditLinkedParts") || LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool())); return new_value; } }; // Cycle selection through linked children or/and faces in selected object. // FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse // resis. Need link position added to sim messages to address this. class LLToolsSelectNextPartFace : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool cycle_faces = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); bool cycle_linked = gSavedSettings.getBOOL("EditLinkedParts"); if (!cycle_faces && !cycle_linked) { // Nothing to do return true; } bool fwd = (userdata.asString() == "next"); bool prev = (userdata.asString() == "previous"); bool ifwd = (userdata.asString() == "includenext"); bool iprev = (userdata.asString() == "includeprevious"); LLViewerObject* to_select = NULL; bool restart_face_on_part = !cycle_faces; S32 new_te = 0; if (cycle_faces) { // Cycle through faces of current selection, if end is reached, swithc to next part (if present) LLSelectNode* nodep = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); if (!nodep) return false; to_select = nodep->getObject(); if (!to_select) return false; S32 te_count = to_select->getNumTEs(); S32 selected_te = nodep->getLastOperatedTE(); if (fwd || ifwd) { if (selected_te < 0) { new_te = 0; } else if (selected_te + 1 < te_count) { // select next face new_te = selected_te + 1; } else { // restart from first face on next part restart_face_on_part = true; } } else if (prev || iprev) { if (selected_te > te_count) { new_te = te_count - 1; } else if (selected_te - 1 >= 0) { // select previous face new_te = selected_te - 1; } else { // restart from last face on next part restart_face_on_part = true; } } } S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); if (cycle_linked && object_count && restart_face_on_part) { LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (selected && selected->getRootEdit()) { LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); children.push_front(selected->getRootEdit()); // need root in the list too for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter) { if ((*iter)->isSelected()) { if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include { to_select = *iter; if (fwd) { // stop searching if going forward; repeat to get last hit if backward break; } } else if ((object_count == 1) || (ifwd || iprev)) // single selection or include { if (fwd || ifwd) { ++iter; while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected()))) { ++iter; // skip sitting avatars and selected if include } } else // backward { iter = (iter == children.begin() ? children.end() : iter); --iter; while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected()))) { --iter; // skip sitting avatars and selected if include } } iter = (iter == children.end() ? children.begin() : iter); to_select = *iter; break; } } } } } if (to_select) { if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) { gFocusMgr.setKeyboardFocus(nullptr); // force edit toolbox to commit any changes } if (fwd || prev) { LLSelectMgr::getInstance()->deselectAll(); } if (cycle_faces) { if (restart_face_on_part) { if (fwd || ifwd) { new_te = 0; } else { new_te = to_select->getNumTEs() - 1; } } LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te); LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false); } else { LLSelectMgr::getInstance()->selectObjectOnly(to_select); } return true; } return true; } }; class LLToolsStopAllAnimations : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgent.stopCurrentAnimations(); return true; } }; class LLToolsReleaseKeys : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgent.forceReleaseControls(); return true; } }; class LLToolsEnableReleaseKeys : public view_listener_t { bool handleEvent(const LLSD& userdata) { return gAgent.anyControlGrabbed(); } }; class LLEditEnableCut : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut(); return new_value; } }; class LLEditCut : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLEditMenuHandler::gEditMenuHandler) { LLEditMenuHandler::gEditMenuHandler->cut(); } return true; } }; class LLEditEnableCopy : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy(); return new_value; } }; class LLEditCopy : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLEditMenuHandler::gEditMenuHandler) { LLEditMenuHandler::gEditMenuHandler->copy(); } return true; } }; class LLEditEnablePaste : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste(); return new_value; } }; class LLEditPaste : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLEditMenuHandler::gEditMenuHandler) { LLEditMenuHandler::gEditMenuHandler->paste(); } return true; } }; class LLEditEnableDelete : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); return new_value; } }; class LLEditDelete : public view_listener_t { bool handleEvent(const LLSD& userdata) { // If a text field can do a deletion, it gets precedence over deleting // an object in the world. if (LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) { LLEditMenuHandler::gEditMenuHandler->doDelete(); } // and close any pie/context menus when done gMenuHolder->hideMenus(); // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete gMenuObject->hide(); return true; } }; void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param) { const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) { return; } U32 index = 0; if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) { return; } spellcheck_handler->replaceWithSuggestion(index); } bool visible_spellcheck_suggestion(LLUICtrl* ctrl, const LLSD& param) { LLMenuItemGL* item = dynamic_cast(ctrl); const LLContextMenu* menu = (item) ? dynamic_cast(item->getParent()) : NULL; const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) { return false; } U32 index = 0; if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) { return false; } item->setLabel(spellcheck_handler->getSuggestion(index)); return true; } void handle_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) { const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) ) { spellcheck_handler->addToDictionary(); } } bool enable_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) { const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); } void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl) { const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) ) { spellcheck_handler->addToIgnore(); } } bool enable_spellcheck_add_to_ignore(const LLUICtrl* ctrl) { const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); } bool enable_object_return() { return (!LLSelectMgr::getInstance()->getSelection()->isEmpty() && (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER))); } bool enable_object_delete() { bool new_value = #ifdef HACKED_GODLIKE_VIEWER true; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER (!LLGridManager::getInstance()->isInProductionGrid() && gAgent.isGodlike()) || # endif LLSelectMgr::getInstance()->canDoDelete(); #endif return new_value; } class LLObjectsReturnPackage { public: LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(nullptr) {}; ~LLObjectsReturnPackage() { mObjectSelection.clear(); mReturnableObjects.clear(); mError.clear(); mFirstRegion = NULL; }; LLObjectSelectionHandle mObjectSelection; std::vector mReturnableObjects; std::string mError; LLViewerRegion *mFirstRegion; }; static void return_objects(LLObjectsReturnPackage *objectsReturnPackage, const LLSD& notification, const LLSD& response) { if (LLNotificationsUtil::getSelectedOption(notification, response) == 0) { // Ignore category ID for this derez destination. derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, objectsReturnPackage->mFirstRegion, objectsReturnPackage->mError, &objectsReturnPackage->mReturnableObjects); } delete objectsReturnPackage; } void handle_object_return() { if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) { LLObjectsReturnPackage *objectsReturnPackage = new LLObjectsReturnPackage(); objectsReturnPackage->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. get_derezzable_objects(DRD_RETURN_TO_OWNER, objectsReturnPackage->mError, objectsReturnPackage->mFirstRegion, &objectsReturnPackage->mReturnableObjects); LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&return_objects, objectsReturnPackage, _1, _2)); } } void handle_object_delete() { if (LLSelectMgr::getInstance()) { LLSelectMgr::getInstance()->doDelete(); } // and close any pie/context menus when done gMenuHolder->hideMenus(); // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete gMenuObject->hide(); return; } void handle_force_delete() { LLSelectMgr::getInstance()->selectForceDelete(); } class LLViewEnableJoystickFlycam : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled")); return new_value; } }; class LLViewEnableLastChatter : public view_listener_t { bool handleEvent(const LLSD& userdata) { // *TODO: add check that last chatter is in range bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull()); return new_value; } }; class LLEditEnableDeselect : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect(); return new_value; } }; class LLEditDeselect : public view_listener_t { bool handleEvent(const LLSD& userdata) { if( LLEditMenuHandler::gEditMenuHandler ) { LLEditMenuHandler::gEditMenuHandler->deselect(); } return true; } }; class LLEditEnableSelectAll : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll(); return new_value; } }; class LLEditSelectAll : public view_listener_t { bool handleEvent(const LLSD& userdata) { if( LLEditMenuHandler::gEditMenuHandler ) { LLEditMenuHandler::gEditMenuHandler->selectAll(); } return true; } }; class LLEditEnableUndo : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo(); return new_value; } }; class LLEditUndo : public view_listener_t { bool handleEvent(const LLSD& userdata) { if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() ) { LLEditMenuHandler::gEditMenuHandler->undo(); } return true; } }; class LLEditEnableRedo : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo(); return new_value; } }; class LLEditRedo : public view_listener_t { bool handleEvent(const LLSD& userdata) { if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() ) { LLEditMenuHandler::gEditMenuHandler->redo(); } return true; } }; void print_object_info() { LLSelectMgr::getInstance()->selectionDump(); } void print_agent_nvpairs() { LLViewerObject *objectp; LL_INFOS() << "Agent Name Value Pairs" << LL_ENDL; objectp = gObjectList.findObject(gAgentID); if (objectp) { objectp->printNameValuePairs(); } else { LL_INFOS() << "Can't find agent object" << LL_ENDL; } LL_INFOS() << "Camera at " << gAgentCamera.getCameraPositionGlobal() << LL_ENDL; } void show_debug_menus() { // this might get called at login screen where there is no menu so only toggle it if one exists if ( gMenuBarView ) { bool debug = gSavedSettings.getBOOL("UseDebugMenus"); bool qamode = gSavedSettings.getBOOL("QAMode"); 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); gMenuBarView->setItemVisible("Develop", qamode); gMenuBarView->setItemEnabled("Develop", qamode); // Server ('Admin') menu hidden when not in godmode. const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride())); gMenuBarView->setItemVisible("Admin", show_server_menu); gMenuBarView->setItemEnabled("Admin", show_server_menu); } if (gLoginMenuBarView) { bool debug = gSavedSettings.getBOOL("UseDebugMenus"); gLoginMenuBarView->setItemVisible("Debug", debug); gLoginMenuBarView->setItemEnabled("Debug", debug); } } void toggle_debug_menus() { bool visible = ! gSavedSettings.getBOOL("UseDebugMenus"); gSavedSettings.setBOOL("UseDebugMenus", visible); show_debug_menus(); } class LLCommunicateNearbyChat : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance(); LLFloaterIMNearbyChat* floater_nearby = LLFloaterReg::getTypedInstance("nearby_chat"); if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff() && im_box->getSelectedSession() == LLUUID() && im_box->getConversationListItemSize() > 1) { im_box->selectNextorPreviousConversation(false); } else { LLFloaterReg::toggleInstanceOrBringToFront("nearby_chat"); } return true; } }; class LLWorldSetHomeLocation : public view_listener_t { bool handleEvent(const LLSD& userdata) { // we just send the message and let the server check for failure cases // server will echo back a "Home position set." alert if it succeeds // and the home location screencapture happens when that alert is recieved gAgent.setStartPosition(START_LOCATION_ID_HOME); return true; } }; class LLWorldLindenHome : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url"); LLWeb::loadURL(url); return true; } }; class LLWorldTeleportHome : public view_listener_t { bool handleEvent(const LLSD& userdata) { gAgent.teleportHome(); return true; } }; class LLWorldAlwaysRun : public view_listener_t { bool handleEvent(const LLSD& userdata) { // as well as altering the default walk-vs-run state, // we also change the *current* walk-vs-run state. if (gAgent.getAlwaysRun()) { gAgent.clearAlwaysRun(); gAgent.clearRunning(); } else { gAgent.setAlwaysRun(); gAgent.setRunning(); } // tell the simulator. gAgent.sendWalkRun(gAgent.getAlwaysRun()); // Update Movement Controls according to AlwaysRun mode LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun()); return true; } }; class LLWorldCheckAlwaysRun : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gAgent.getAlwaysRun(); return new_value; } }; class LLWorldSetAway : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgent.getAFK()) { gAgent.clearAFK(); } else { gAgent.setAFK(); } return true; } }; class LLWorldSetDoNotDisturb : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgent.isDoNotDisturb()) { gAgent.setDoNotDisturb(false); } else { gAgent.setDoNotDisturb(true); LLNotificationsUtil::add("DoNotDisturbModeSet"); } return true; } }; class LLWorldCreateLandmark : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterReg::showInstance("add_landmark"); return true; } }; class LLWorldPlaceProfile : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent")); return true; } }; void handle_look_at_selection(const LLSD& param) { const F32 PADDING_FACTOR = 1.75f; bool zoom = (param.asString() == "zoom"); if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) { gAgentCamera.setFocusOnAvatar(false, ANIMATE); LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent(); obj_to_cam.normVec(); LLUUID object_id; if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) { object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID; } if (zoom) { // Make sure we are not increasing the distance between the camera and object LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal(); distance = llmin(distance, (F32) orig_distance.length()); gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); } else { gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); } } } void handle_zoom_to_object(const LLUUID& object_id) { const F32 PADDING_FACTOR = 2.f; LLViewerObject* object = gObjectList.findObject(object_id); if (object) { gAgentCamera.setFocusOnAvatar(false, ANIMATE); LLBBox bbox = object->getBoundingBoxAgent() ; F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); obj_to_cam.normVec(); LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), object_center_global, object_id ); } } class LLAvatarInviteToGroup : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) { LLAvatarActions::inviteToGroup(avatar->getID()); } return true; } }; class LLAvatarAddFriend : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar && !LLAvatarActions::isFriend(avatar->getID())) { request_friendship(avatar->getID()); } return true; } }; class LLAvatarToggleMyProfile : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloater* instance = LLAvatarActions::getProfileFloater(gAgent.getID()); if (LLFloater::isMinimized(instance)) { instance->setMinimized(false); instance->setFocus(true); } else if (!LLFloater::isShown(instance)) { LLAvatarActions::showProfile(gAgent.getID()); } else if (!instance->hasFocus() && !instance->getIsChrome()) { instance->setFocus(true); } else { instance->closeFloater(); } return true; } }; class LLAvatarTogglePicks : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloater * instance = LLAvatarActions::getProfileFloater(gAgent.getID()); if (LLFloater::isMinimized(instance) || (instance && !instance->hasFocus() && !instance->getIsChrome())) { instance->setMinimized(false); instance->setFocus(true); LLAvatarActions::showPicks(gAgent.getID()); } else if (picks_tab_visible()) { instance->closeFloater(); } else { LLAvatarActions::showPicks(gAgent.getID()); } return true; } }; class LLAvatarToggleSearch : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloater* instance = LLFloaterReg::findInstance("search"); if (LLFloater::isMinimized(instance)) { instance->setMinimized(false); instance->setFocus(true); } else if (!LLFloater::isShown(instance)) { LLFloaterReg::showInstance("search"); } else if (!instance->hasFocus() && !instance->getIsChrome()) { instance->setFocus(true); } else { instance->closeFloater(); } return true; } }; class LLAvatarResetSkeleton : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { avatar->resetSkeleton(false); } return true; } }; class LLAvatarEnableResetSkeleton : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { return true; } return false; } }; class LLAvatarResetSkeletonAndAnimations : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { avatar->resetSkeleton(true); } return true; } }; class LLAvatarResetSelfSkeleton : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { avatar->resetSkeleton(false); } else { gAgentAvatarp->resetSkeleton(false); } return true; } }; class LLAvatarResetSelfSkeletonAndAnimations : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) { avatar->resetSkeleton(true); } else { gAgentAvatarp->resetSkeleton(true); } return true; } }; class LLAvatarAddContact : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) { create_inventory_callingcard(avatar->getID()); } return true; } }; bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { gAgent.setDoNotDisturb(false); } LLViewerObject* objectp = selection->getPrimaryObject(); // Show avatar's name if paying attachment if (objectp && objectp->isAttachment()) { while (objectp && !objectp->isAvatar()) { objectp = (LLViewerObject*)objectp->getParent(); } } if (objectp) { if (objectp->isAvatar()) { const bool is_group = false; LLFloaterPayUtil::payDirectly(&give_money, objectp->getID(), is_group); } else { LLFloaterPayUtil::payViaObject(&give_money, selection); } } return false; } void handle_give_money_dialog() { LLNotification::Params params("DoNotDisturbModePay"); params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); if (gAgent.isDoNotDisturb()) { // warn users of being in do not disturb mode during a transaction LLNotifications::instance().add(params); } else { LLNotifications::instance().forceResponse(params, 1); } } bool enable_pay_avatar() { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); LLVOAvatar* avatar = find_avatar_from_object(obj); return (avatar != NULL); } bool enable_pay_object() { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if( object ) { LLViewerObject *parent = (LLViewerObject *)object->getParent(); if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) { return true; } } return false; } bool enable_object_stand_up() { // 'Object Stand Up' menu item is enabled when agent is sitting on selection return sitting_on_selection(); } bool enable_object_sit(LLUICtrl* ctrl) { // 'Object Sit' menu item is enabled when agent is not sitting on selection bool sitting_on_sel = sitting_on_selection(); if (!sitting_on_sel) { // init default labels init_default_item_label(ctrl); // Update label LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mSitName.empty()) { ctrl->setValue(node->mSitName); } else { ctrl->setValue(get_default_item_label(ctrl->getName())); } } return !sitting_on_sel && is_object_sittable(); } void dump_select_mgr() { LLSelectMgr::getInstance()->dump(); } void dump_inventory() { gInventory.dumpInventory(); } void handle_dump_followcam() { LLFollowCamMgr::getInstance()->dump(); } void handle_viewer_enable_message_log() { gMessageSystem->startLogging(); } void handle_viewer_disable_message_log() { gMessageSystem->stopLogging(); } void handle_customize_avatar() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } void handle_edit_outfit() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); } void handle_now_wearing() { LLSidepanelAppearance *panel_appearance = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); if (panel_appearance && panel_appearance->isInVisibleChain() && panel_appearance->isCOFPanelVisible()) { LLFloaterReg::findInstance("appearance")->closeFloater(); return; } LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "now_wearing")); } void handle_edit_shape() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape")); } void handle_hover_height() { LLFloaterReg::showInstance("edit_hover_height"); } void handle_edit_physics() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics")); } void handle_report_abuse() { // Prevent menu from appearing in screen shot. gMenuHolder->hideMenus(); LLFloaterReporter::showFromMenu(COMPLAINT_REPORT); } void handle_buy_currency() { LLBuyCurrencyHTML::openCurrencyFloater(); } class LLFloaterVisible : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string floater_name = userdata.asString(); bool new_value = false; { new_value = LLFloaterReg::instanceVisible(floater_name); } return new_value; } }; class LLShowHelp : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string help_topic = userdata.asString(); LLViewerHelp* vhelp = LLViewerHelp::getInstance(); vhelp->showTopic(help_topic); return true; } }; class LLToggleHelp : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser")); if (help_browser && help_browser->isInVisibleChain()) { help_browser->closeFloater(); } else { std::string help_topic = userdata.asString(); LLViewerHelp* vhelp = LLViewerHelp::getInstance(); vhelp->showTopic(help_topic); } return true; } }; class LLToggleSpeak : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVoiceClient::getInstance()->toggleUserPTTState(); return true; } }; class LLShowSidetrayPanel : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string floater_name = userdata.asString(); LLPanel* panel = LLFloaterSidePanelContainer::getPanel(floater_name); if (panel) { if (panel->isInVisibleChain()) { LLFloaterReg::getInstance(floater_name)->closeFloater(); } else { LLFloaterReg::getInstance(floater_name)->openFloater(); } } return true; } }; class LLSidetrayPanelVisible : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string floater_name = userdata.asString(); // Toggle the panel if (LLFloaterReg::getInstance(floater_name)->isInVisibleChain()) { return true; } else { return false; } } }; bool callback_show_url(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { LLWeb::loadURL(notification["payload"]["url"].asString()); } return false; } class LLPromptShowURL : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string param = userdata.asString(); std::string::size_type offset = param.find(","); if (offset != param.npos) { std::string alert = param.substr(0, offset); std::string url = param.substr(offset+1); if (LLWeb::useExternalBrowser(url)) { LLSD payload; payload["url"] = url; LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url); } else { LLWeb::loadURL(url); } } else { LL_INFOS() << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << LL_ENDL; } return true; } }; bool callback_show_file(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { LLWeb::loadURL(notification["payload"]["url"]); } return false; } class LLPromptShowFile : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string param = userdata.asString(); std::string::size_type offset = param.find(","); if (offset != param.npos) { std::string alert = param.substr(0, offset); std::string file = param.substr(offset+1); LLSD payload; payload["url"] = file; LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file); } else { LL_INFOS() << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << LL_ENDL; } return true; } }; class LLShowAgentProfile : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLUUID agent_id; if (userdata.asString() == "agent") { agent_id = gAgent.getID(); } else if (userdata.asString() == "hit object") { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (objectp) { agent_id = objectp->getID(); } } else { agent_id = userdata.asUUID(); } LLVOAvatar* avatar = find_avatar_from_object(agent_id); if (avatar) { LLAvatarActions::showProfile(avatar->getID()); } return true; } }; class LLShowAgentProfilePicks : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLAvatarActions::showPicks(gAgent.getID()); return true; } }; class LLToggleAgentProfile : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLUUID agent_id; if (userdata.asString() == "agent") { agent_id = gAgent.getID(); } else if (userdata.asString() == "hit object") { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (objectp) { agent_id = objectp->getID(); } } else { agent_id = userdata.asUUID(); } LLVOAvatar* avatar = find_avatar_from_object(agent_id); if (avatar) { if (!LLAvatarActions::profileVisible(avatar->getID())) { LLAvatarActions::showProfile(avatar->getID()); } else { LLAvatarActions::hideProfile(avatar->getID()); } } return true; } }; class LLLandEdit : public view_listener_t { bool handleEvent(const LLSD& userdata) { if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) { // zoom in if we're looking at the avatar gAgentCamera.setFocusOnAvatar(false, ANIMATE); gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gAgentCamera.cameraOrbitOver( F_PI * 0.25f ); gViewerWindow->moveCursorToCenter(); } else if ( gSavedSettings.getBOOL("EditCameraMovement") ) { gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); gViewerWindow->moveCursorToCenter(); } LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal ); LLFloaterReg::showInstance("build"); // Switch to land edit toolset LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() ); return true; } }; class LLMuteParticle : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID; if (id.notNull()) { LLAvatarName av_name; LLAvatarNameCache::get(id, &av_name); LLMute mute(id, av_name.getUserName(), LLMute::AGENT); if (LLMuteList::getInstance()->isMuted(mute.mID)) { LLMuteList::getInstance()->remove(mute); } else { LLMuteList::getInstance()->add(mute); LLPanelBlockedList::showPanelAndSelect(mute.mID); } } return true; } }; class LLWorldEnableBuyLand : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel( LLViewerParcelMgr::getInstance()->selectionEmpty() ? LLViewerParcelMgr::getInstance()->getAgentParcel() : LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false); return new_value; } }; bool enable_buy_land() { return LLViewerParcelMgr::getInstance()->canAgentBuyParcel( LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false); } void handle_buy_land() { LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance(); if (vpm->selectionEmpty()) { vpm->selectParcelAt(gAgent.getPositionGlobal()); } vpm->startBuyLand(); } class LLObjectAttachToAvatar : public view_listener_t { public: LLObjectAttachToAvatar(bool replace) : mReplace(replace) {} static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; } private: bool handleEvent(const LLSD& userdata) { setObjectSelection(LLSelectMgr::getInstance()->getSelection()); LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject(); if (selectedObject) { S32 index = userdata.asInteger(); LLViewerJointAttachment* attachment_point = NULL; if (index > 0) attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); confirmReplaceAttachment(0, attachment_point); } return true; } static void onNearAttachObject(bool success, void *user_data); void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point); class CallbackData : public LLSelectionCallbackData { public: CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {} LLViewerJointAttachment* mAttachmentPoint; bool mReplace; }; protected: static LLObjectSelectionHandle sObjectSelection; bool mReplace; }; LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection; // static void LLObjectAttachToAvatar::onNearAttachObject(bool success, void *user_data) { if (!user_data) return; CallbackData* cb_data = static_cast(user_data); if (success) { const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint; U8 attachment_id = 0; if (attachment) { for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) { if (iter->second == attachment) { attachment_id = iter->first; break; } } } else { // interpret 0 as "default location" attachment_id = 0; } LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace); } LLObjectAttachToAvatar::setObjectSelection(nullptr); delete cb_data; } // static void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point) { if (option == 0/*YES*/) { LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); if (selectedObject) { const F32 MIN_STOP_DISTANCE = 1.f; // meters const F32 ARM_LENGTH = 0.5f; // meters const F32 SCALE_FUDGE = 1.5f; F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH; if (stop_distance < MIN_STOP_DISTANCE) { stop_distance = MIN_STOP_DISTANCE; } LLVector3 walkToSpot = selectedObject->getPositionAgent(); // make sure we stop in front of the object LLVector3 delta = walkToSpot - gAgent.getPositionAgent(); delta.normVec(); delta = delta * 0.5f; walkToSpot -= delta; // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak. CallbackData* user_data = new CallbackData(attachment_point, mReplace); gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance); gAgentCamera.clearFocusObject(); } } } void callback_attachment_drop(const LLSD& notification, const LLSD& response) { // Ensure user confirmed the drop S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) return; // Called when the user clicked on an object attached to them // and selected "Drop". LLUUID object_id = notification["payload"]["object_id"].asUUID(); LLViewerObject *object = gObjectList.findObject(object_id); if (!object) { LL_WARNS() << "handle_drop_attachment() - no object to drop" << LL_ENDL; return; } LLViewerObject *parent = (LLViewerObject*)object->getParent(); while (parent) { if(parent->isAvatar()) { break; } object = parent; parent = (LLViewerObject*)parent->getParent(); } if (!object) { LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; return; } if (object->isAvatar()) { LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; return; } // reselect the object LLSelectMgr::getInstance()->selectObjectAndFamily(object); LLSelectMgr::getInstance()->sendDropAttachment(); return; } class LLAttachmentDrop : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLSD payload; LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (object) { payload["object_id"] = object->getID(); } else { LL_WARNS() << "Drop object not found" << LL_ENDL; return true; } LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop); return true; } }; // called from avatar pie menu class LLAttachmentDetachFromPoint : public view_listener_t { bool handleEvent(const LLSD& user_data) { uuid_vec_t ids_to_remove; const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL); if (attachment->getNumObjects() > 0) { for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin(); iter != attachment->mAttachedObjects.end(); iter++) { LLViewerObject *attached_object = iter->get(); ids_to_remove.push_back(attached_object->getAttachmentItemID()); } } if (!ids_to_remove.empty()) { LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); } return true; } }; static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data) { std::string label; LLMenuItemGL* menu = dynamic_cast(ctrl); if (menu) { const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL); if (attachment) { label = data["label"].asString(); for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { const LLViewerObject* attached_object = attachment_iter->get(); if (attached_object) { LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID()); if (itemp) { label += std::string(" (") + itemp->getName() + std::string(")"); break; } } } } menu->setLabel(label); } return true; } class LLAttachmentDetach : public view_listener_t { bool handleEvent(const LLSD& userdata) { // Called when the user clicked on an object attached to them // and selected "Detach". LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLViewerObject *object = selection->getPrimaryObject(); if (!object) { LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; return true; } struct f: public LLSelectedObjectFunctor { f() : mAvatarsInSelection(false) {} virtual bool apply(LLViewerObject* objectp) { if (!objectp) { return false; } if (objectp->isAvatar()) { mAvatarsInSelection = true; return false; } LLViewerObject* parent = (LLViewerObject*)objectp->getParent(); while (parent) { if(parent->isAvatar()) { break; } objectp = parent; parent = (LLViewerObject*)parent->getParent(); } // std::set to avoid dupplicate 'roots' from linksets mRemoveSet.insert(objectp->getAttachmentItemID()); return true; } bool mAvatarsInSelection; uuid_set_t mRemoveSet; } func; // Probbly can run applyToRootObjects instead, // but previous version of this code worked for any selected object selection->applyToObjects(&func); if (func.mAvatarsInSelection) { // Not possible under normal circumstances // Either avatar selection is ON or has to do with animeshes // Better stop this than mess something LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; return true; } if (func.mRemoveSet.empty()) { LL_WARNS() << "handle_detach() - no valid attachments in selection to detach" << LL_ENDL; return true; } uuid_vec_t detach_list(func.mRemoveSet.begin(), func.mRemoveSet.end()); LLAppearanceMgr::instance().removeItemsFromAvatar(detach_list); return true; } }; //Adding an observer for a Jira 2422 and needs to be a fetch observer //for Jira 3119 class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver { public: LLWornItemFetchedObserver(const LLUUID& worn_item_id) : LLInventoryFetchItemsObserver(worn_item_id) {} virtual ~LLWornItemFetchedObserver() {} protected: virtual void done() { gMenuAttachmentSelf->buildDrawLabels(); gInventory.removeObserver(this); delete this; } }; // You can only drop items on parcels where you can build. class LLAttachmentEnableDrop : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); //Add an inventory observer to only allow dropping the newly attached item //once it exists in your inventory. Look at Jira 2422. //-jwolk // A bug occurs when you wear/drop an item before it actively is added to your inventory // if this is the case (you're on a slow sim, etc.) a copy of the object, // well, a newly created object with the same properties, is placed // in your inventory. Therefore, we disable the drop option until the // item is in your inventory LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); LLViewerJointAttachment* attachment = NULL; LLInventoryItem* item = NULL; // Do not enable drop if all faces of object are not enabled if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) { S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState()); attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); if (attachment) { for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { // make sure item is in your inventory (it could be a delayed attach message being sent from the sim) // so check to see if the item is in the inventory already item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID()); if (!item) { // Item does not exist, make an observer to enable the pie menu // when the item finishes fetching worst case scenario // if a fetch is already out there (being sent from a slow sim) // we refetch and there are 2 fetches LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID()); worn_item_fetched->startFetch(); gInventory.addObserver(worn_item_fetched); } } } } //now check to make sure that the item is actually in the inventory before we enable dropping it bool new_value = enable_detach() && can_build && item; return new_value; } }; bool enable_detach(const LLSD&) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); // Only enable detach if all faces of object are selected if (!object || !object->isAttachment() || !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) { return false; } // Find the avatar who owns this attachment LLViewerObject* avatar = object; while (avatar) { // ...if it's you, good to detach if (avatar->getID() == gAgent.getID()) { return true; } avatar = (LLViewerObject*)avatar->getParent(); } return false; } class LLAttachmentEnableDetach : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = enable_detach(); return new_value; } }; // Used to tell if the selected object can be attached to your avatar. bool object_selected_and_point_valid() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); for (LLObjectSelection::root_iterator iter = selection->root_begin(); iter != selection->root_end(); iter++) { LLSelectNode* node = *iter; LLViewerObject* object = node->getObject(); LLViewerObject::const_child_list_t& child_list = object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* child = *iter; if (child->isAvatar()) { return false; } } } return (selection->getRootObjectCount() == 1) && (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && selection->getFirstRootObject()->permYouOwner() && selection->getFirstRootObject()->flagObjectMove() && !selection->getFirstRootObject()->flagObjectPermanent() && !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); } bool object_is_wearable() { if (!isAgentAvatarValid()) { return false; } if (!object_selected_and_point_valid()) { return false; } if (sitting_on_selection()) { return false; } if (!gAgentAvatarp->canAttachMoreObjects()) { return false; } LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) { LLSelectNode* node = *iter; if (node->mPermissions->getOwner() == gAgent.getID()) { return true; } } return false; } class LLAttachmentPointFilled : public view_listener_t { bool handleEvent(const LLSD& user_data) { bool enable = false; LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger()); if (found_it != gAgentAvatarp->mAttachmentPoints.end()) { enable = found_it->second->getNumObjects() > 0; } return enable; } }; class LLAvatarSendIM : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if(avatar) { LLAvatarActions::startIM(avatar->getID()); } return true; } }; class LLAvatarCall : public view_listener_t { static LLVOAvatar* findAvatar() { return find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); } bool handleEvent(const LLSD& userdata) { if (LLVOAvatar* avatar = findAvatar()) { LLAvatarActions::startCall(avatar->getID()); } return true; } public: static bool isAvailable() { if (LLVOAvatar* avatar = findAvatar()) { return LLAvatarActions::canCallTo(avatar->getID()); } return LLAvatarActions::canCall(); } }; namespace { struct QueueObjects : public LLSelectedNodeFunctor { bool scripted; bool modifiable; LLFloaterScriptQueue* mQueue; QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(false), modifiable(false) {} virtual bool apply(LLSelectNode* node) { LLViewerObject* obj = node->getObject(); if (!obj) { return true; } scripted = obj->flagScripted(); modifiable = obj->permModify(); if( scripted && modifiable ) { mQueue->addObject(obj->getID(), node->mName); return false; } else { return true; // fail: stop applying } } }; } bool queue_actions(LLFloaterScriptQueue* q, const std::string& msg) { QueueObjects func(q); LLSelectMgr *mgr = LLSelectMgr::getInstance(); LLObjectSelectionHandle selectHandle = mgr->getSelection(); bool fail = selectHandle->applyToNodes(&func); if(fail) { if ( !func.scripted ) { std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts"; LLNotificationsUtil::add(noscriptmsg); } else if ( !func.modifiable ) { std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission"; LLNotificationsUtil::add(nomodmsg); } else { LL_ERRS() << "Bad logic." << LL_ENDL; } q->closeFloater(); } else { if (!q->start()) { LL_WARNS() << "Unexpected script compile failure." << LL_ENDL; } } return !fail; } class LLToolsSelectedScriptAction : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string action = userdata.asString(); bool mono = false; std::string msg, name; std::string title; if (action == "compile mono") { name = "compile_queue"; mono = true; msg = "Recompile"; title = LLTrans::getString("CompileQueueTitle"); } if (action == "compile lsl") { name = "compile_queue"; msg = "Recompile"; title = LLTrans::getString("CompileQueueTitle"); } else if (action == "reset") { name = "reset_queue"; msg = "Reset"; title = LLTrans::getString("ResetQueueTitle"); } else if (action == "start") { name = "start_queue"; msg = "SetRunning"; title = LLTrans::getString("RunQueueTitle"); } else if (action == "stop") { name = "stop_queue"; msg = "SetRunningNot"; title = LLTrans::getString("NotRunQueueTitle"); } LLUUID id; id.generate(); LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance(name, LLSD(id)); if (queue) { queue->setMono(mono); if (queue_actions(queue, msg)) { queue->setTitle(title); } } else { LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; } return true; } }; void handle_selected_texture_info() { for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) { LLSelectNode* node = *iter; std::string msg; msg.assign("Texture info for: "); msg.append(node->mName); U8 te_count = node->getObject()->getNumTEs(); // map from texture ID to list of faces using it typedef std::map< LLUUID, std::vector > map_t; map_t faces_per_texture; for (U8 i = 0; i < te_count; i++) { if (!node->isTESelected(i)) continue; LLViewerTexture* img = node->getObject()->getTEImage(i); LLUUID image_id = img->getID(); faces_per_texture[image_id].push_back(i); } // Per-texture, dump which faces are using it. map_t::iterator it; for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it) { U8 te = it->second[0]; LLViewerTexture* img = node->getObject()->getTEImage(te); S32 height = img->getHeight(); S32 width = img->getWidth(); S32 components = img->getComponents(); msg.append(llformat("\n%dx%d %s on face ", width, height, (components == 4 ? "alpha" : "opaque"))); for (U8 i = 0; i < it->second.size(); ++i) { msg.append( llformat("%d ", (S32)(it->second[i]))); } } LLSD args; args["MESSAGE"] = msg; LLNotificationsUtil::add("SystemMessage", args); } } void handle_selected_material_info() { for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) { LLSelectNode* node = *iter; std::string msg; msg.assign("Material info for: \n"); msg.append(node->mName); U8 te_count = node->getObject()->getNumTEs(); // map from material ID to list of faces using it typedef std::map > map_t; map_t faces_per_material; for (U8 i = 0; i < te_count; i++) { if (!node->isTESelected(i)) continue; const LLMaterialID& material_id = node->getObject()->getTE(i)->getMaterialID(); faces_per_material[material_id].push_back(i); } // Per-material, dump which faces are using it. map_t::iterator it; for (it = faces_per_material.begin(); it != faces_per_material.end(); ++it) { const LLMaterialID& material_id = it->first; msg += llformat("%s on face ", material_id.asString().c_str()); for (U8 i = 0; i < it->second.size(); ++i) { msg.append( llformat("%d ", (S32)(it->second[i]))); } msg.append("\n"); } LLSD args; args["MESSAGE"] = msg; LLNotificationsUtil::add("SystemMessage", args); } } void handle_test_male() { LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit"); //gGestureList.requestResetFromServer( true ); } void handle_test_female() { LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit"); //gGestureList.requestResetFromServer( false ); } void handle_dump_attachments() { if (!isAgentAvatarValid()) return; for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; S32 key = curiter->first; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { LLViewerObject *attached_object = attachment_iter->get(); bool visible = (attached_object != NULL && attached_object->mDrawable.notNull() && !attached_object->mDrawable->isRenderType(0)); LLVector3 pos; if (visible) pos = attached_object->mDrawable->getPosition(); LL_INFOS() << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID() << (attached_object ? " present " : " absent ") << (visible ? "visible " : "invisible ") << " at " << pos << " and " << (visible ? attached_object->getPosition() : LLVector3::zero) << LL_ENDL; } } } // these are used in the gl menus to set control values, generically. class LLToggleControl : public view_listener_t { protected: bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); bool checked = gSavedSettings.getBOOL( control_name ); gSavedSettings.setBOOL( control_name, !checked ); return true; } }; class LLCheckControl : public view_listener_t { bool handleEvent( const LLSD& userdata) { std::string callback_data = userdata.asString(); bool new_value = gSavedSettings.getBOOL(callback_data); return new_value; } }; // not so generic class LLAdvancedCheckRenderShadowOption: public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); S32 current_shadow_level = gSavedSettings.getS32(control_name); if (current_shadow_level == 0) // is off { return false; } else // is on { return true; } } }; class LLAdvancedClickRenderShadowOption: public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); S32 current_shadow_level = gSavedSettings.getS32(control_name); if (current_shadow_level == 0) // upgrade to level 2 { gSavedSettings.setS32(control_name, 2); } else // downgrade to level 0 { gSavedSettings.setS32(control_name, 0); } return true; } }; class LLAdvancedClickRenderProfile: public view_listener_t { bool handleEvent(const LLSD& userdata) { gShaderProfileFrame = true; return true; } }; F32 gpu_benchmark(); class LLAdvancedClickRenderBenchmark: public view_listener_t { bool handleEvent(const LLSD& userdata) { gpu_benchmark(); return true; } }; void hdri_preview(); class LLAdvancedClickHDRIPreview: public view_listener_t { bool handleEvent(const LLSD& userdata) { // open personal lighting floater when previewing an HDRI (keeps HDRI from implicitly unloading when opening build tools) LLFloaterReg::showInstance("env_adjust_snapshot"); hdri_preview(); return true; } }; class LLAdvancedClickGLTFOpen: public view_listener_t { bool handleEvent(const LLSD& userdata) { static LLCachedControl can_use_shaders(gSavedSettings, "RenderCanUseGLTFPBROpaqueShaders", true); if (can_use_shaders) { LL::GLTFSceneManager::instance().load(); } else { LLNotificationsUtil::add("NoSupportGLTFShader"); } return true; } }; class LLAdvancedClickGLTFSaveAs : public view_listener_t { bool handleEvent(const LLSD& userdata) { LL::GLTFSceneManager::instance().saveAs(); return true; } }; class LLAdvancedClickGLTFUpload: public view_listener_t { bool handleEvent(const LLSD& userdata) { LL::GLTFSceneManager::instance().uploadSelection(); return true; } }; class LLAdvancedClickGLTFEdit : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterReg::showInstance("gltf_asset_editor"); return true; } }; class LLAdvancedClickResizeWindow : public view_listener_t { bool handleEvent(const LLSD& userdata) { S32 w = 0; S32 h = 0; sscanf(userdata.asString().c_str(), "%dx%d", &w, &h); if (w > 0 && h > 0) { gViewerWindow->getWindow()->setSize(LLCoordWindow(w, h)); } return true; } }; // these are used in the gl menus to set control values that require shader recompilation class LLToggleShaderControl : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); bool checked = gSavedSettings.getBOOL( control_name ); gSavedSettings.setBOOL( control_name, !checked ); LLPipeline::refreshCachedSettings(); LLViewerShaderMgr::instance()->setShaders(); return !checked; } }; void menu_toggle_attached_lights() { LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); } void menu_toggle_attached_particles() { LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); } class LLAdvancedHandleAttachedLightParticles: public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); // toggle the control gSavedSettings.setBOOL(control_name, !gSavedSettings.getBOOL(control_name)); // update internal flags if (control_name == "RenderAttachedLights") { menu_toggle_attached_lights(); } else if (control_name == "RenderAttachedParticles") { menu_toggle_attached_particles(); } return true; } }; class LLSomethingSelected : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty()); return new_value; } }; class LLSomethingSelectedNoHUD : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD); return new_value; } }; static bool is_editable_selected() { return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); } class LLEditableSelected : public view_listener_t { bool handleEvent(const LLSD& userdata) { return is_editable_selected(); } }; class LLEditableSelectedMono : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = false; LLViewerRegion* region = gAgent.getRegion(); if(region && gMenuHolder) { bool have_cap = (! region->getCapability("UpdateScriptTask").empty()); new_value = is_editable_selected() && have_cap; } return new_value; } }; bool enable_object_take_copy() { bool all_valid = false; if (LLSelectMgr::getInstance()) { if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 0) { all_valid = true; #ifndef HACKED_GODLIKE_VIEWER # ifdef TOGGLE_HACKED_GODLIKE_VIEWER if (LLGridManager::getInstance()->isInProductionGrid() || !gAgent.isGodlike()) # endif { struct f : public LLSelectedObjectFunctor { virtual bool apply(LLViewerObject* obj) { return (!obj->permCopy() || obj->isAttachment()); } } func; const bool firstonly = true; bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); all_valid = !any_invalid; } #endif // HACKED_GODLIKE_VIEWER } } return all_valid; } bool enable_take_copy_objects() { return enable_object_take_copy() && is_multiple_selection(); } class LLHasAsset : public LLInventoryCollectFunctor { public: LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(false) {} virtual ~LLHasAsset() {} virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); bool hasAsset() const { return mHasAsset; } protected: LLUUID mAssetID; bool mHasAsset; }; bool LLHasAsset::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if(item && item->getAssetUUID() == mAssetID) { mHasAsset = true; } return false; } bool enable_save_into_task_inventory() { LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if(node && (node->mValid) && (!node->mFromTaskID.isNull())) { // *TODO: check to see if the fromtaskid object exists. LLViewerObject* obj = node->getObject(); if( obj && !obj->isAttachment() ) { return true; } } return false; } class LLToolsEnableSaveToObjectInventory : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = enable_save_into_task_inventory(); return new_value; } }; class LLToggleHowTo : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLFloaterReg::toggleInstanceOrBringToFront("guidebook"); return true; } }; class LLViewEnableMouselook : public view_listener_t { bool handleEvent(const LLSD& userdata) { // You can't go directly from customize avatar to mouselook. // TODO: write code with appropriate dialogs to handle this transition. bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime")); return new_value; } }; class LLToolsEnableToolNotPie : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() ); return new_value; } }; class LLWorldEnableCreateLandmark : public view_listener_t { bool handleEvent(const LLSD& userdata) { return !LLLandmarkActions::landmarkAlreadyExists(); } }; class LLWorldEnableSetHomeLocation : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gAgent.isGodlike() || (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome()); return new_value; } }; class LLWorldEnableTeleportHome : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLViewerRegion* regionp = gAgent.getRegion(); bool agent_on_prelude = (regionp && regionp->isPrelude()); bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude; return enable_teleport_home; } }; bool enable_god_full() { return gAgent.getGodLevel() >= GOD_FULL; } bool enable_god_liaison() { return gAgent.getGodLevel() >= GOD_LIAISON; } bool is_god_customer_service() { return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE; } bool enable_god_basic() { return gAgent.getGodLevel() > GOD_NOT; } void toggle_show_xui_names() { gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames")); } bool check_show_xui_names() { return gSavedSettings.getBOOL("DebugShowXUINames"); } class LLToolsSelectOnlyMyObjects : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool cur_val = gSavedSettings.getBOOL("SelectOwnedOnly"); gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val ); return true; } }; class LLToolsSelectOnlyMovableObjects : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool cur_val = gSavedSettings.getBOOL("SelectMovableOnly"); gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val ); return true; } }; class LLToolsSelectInvisibleObjects : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool cur_val = gSavedSettings.getBOOL("SelectInvisibleObjects"); gSavedSettings.setBOOL("SelectInvisibleObjects", !cur_val); return true; } }; class LLToolsSelectReflectionProbes: public view_listener_t { bool handleEvent(const LLSD& userdata) { bool cur_val = gSavedSettings.getBOOL("SelectReflectionProbes"); gSavedSettings.setBOOL("SelectReflectionProbes", !cur_val); return true; } }; class LLToolsSelectBySurrounding : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive; gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive); return true; } }; class LLToolsShowHiddenSelection : public view_listener_t { bool handleEvent(const LLSD& userdata) { // TomY TODO Merge these LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections; gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections); return true; } }; class LLToolsShowSelectionLightRadius : public view_listener_t { bool handleEvent(const LLSD& userdata) { // TomY TODO merge these LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius; gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius); return true; } }; class LLToolsEditLinkedParts : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool select_individuals = !gSavedSettings.getBOOL("EditLinkedParts"); gSavedSettings.setBOOL( "EditLinkedParts", select_individuals ); if (select_individuals) { LLSelectMgr::getInstance()->demoteSelectionToIndividuals(); } else { LLSelectMgr::getInstance()->promoteSelectionToRoot(); } return true; } }; void reload_vertex_shader() { //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP } void handle_dump_avatar_local_textures() { gAgentAvatarp->dumpLocalTextures(); } void handle_dump_timers() { LLTrace::BlockTimer::dumpCurTimes(); } void handle_debug_avatar_textures() { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (objectp) { LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) ); } } void handle_grab_baked_texture(EBakedTextureIndex baked_tex_index) { if (!isAgentAvatarValid()) return; const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index); LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << LL_ENDL; LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE; LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE; const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type)); if(folder_id.notNull()) { std::string name; name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; LLUUID item_id; item_id.generate(); LLPermissions perm; perm.init(gAgentID, gAgentID, LLUUID::null, LLUUID::null); U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER; perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); time_t creation_date_now = time_corrected(); LLPointer item = new LLViewerInventoryItem(item_id, folder_id, perm, asset_id, asset_type, inv_type, name, LLStringUtil::null, LLSaleInfo::DEFAULT, LLInventoryItemFlags::II_FLAGS_NONE, creation_date_now); item->updateServer(true); gInventory.updateItem(item); gInventory.notifyObservers(); // Show the preview panel for textures to let // user know that the image is now in inventory. LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); if(active_panel) { LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); active_panel->setSelection(item_id, TAKE_FOCUS_NO); active_panel->openSelected(); //LLFloaterInventory::dumpSelectionInformation((void*)view); // restore keyboard focus gFocusMgr.setKeyboardFocus(focus_ctrl); } } else { LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; } } bool enable_grab_baked_texture(EBakedTextureIndex baked_tex_index) { if (isAgentAvatarValid()) { return gAgentAvatarp->canGrabBakedTexture(baked_tex_index); } return false; } // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. // Returns NULL on failure. LLVOAvatar* find_avatar_from_object(LLViewerObject* object) { if (object) { if( object->isAttachment() ) { do { object = (LLViewerObject*) object->getParent(); } while( object && !object->isAvatar() ); } else if( !object->isAvatar() ) { object = NULL; } } return (LLVOAvatar*) object; } // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. // Returns NULL on failure. LLVOAvatar* find_avatar_from_object(const LLUUID& object_id) { return find_avatar_from_object( gObjectList.findObject(object_id) ); } void handle_disconnect_viewer() { LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect")); } void force_error_breakpoint() { LLAppViewer::instance()->forceErrorBreakpoint(); } void force_error_llerror() { LLAppViewer::instance()->forceErrorLLError(); } void force_error_llerror_msg() { LLAppViewer::instance()->forceErrorLLErrorMsg(); } void force_error_bad_memory_access() { LLAppViewer::instance()->forceErrorBadMemoryAccess(); } void force_error_infinite_loop() { LLAppViewer::instance()->forceErrorInfiniteLoop(); } void force_error_software_exception() { LLAppViewer::instance()->forceErrorSoftwareException(); } void force_error_os_exception() { LLAppViewer::instance()->forceErrorOSSpecificException(); } void force_error_driver_crash() { LLAppViewer::instance()->forceErrorDriverCrash(); } void force_error_coroutine_crash() { LLAppViewer::instance()->forceErrorCoroutineCrash(); } void force_error_thread_crash() { LLAppViewer::instance()->forceErrorThreadCrash(); } class LLToolsUseSelectionForGrid : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLSelectMgr::getInstance()->clearGridObjects(); struct f : public LLSelectedObjectFunctor { virtual bool apply(LLViewerObject* objectp) { LLSelectMgr::getInstance()->addGridObject(objectp); return true; } } func; LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT); return true; } }; void handle_test_load_url() { LLWeb::loadURL(""); LLWeb::loadURL("hacker://www.google.com/"); LLWeb::loadURL("http"); LLWeb::loadURL("http://www.google.com/"); } // // LLViewerMenuHolderGL // static LLDefaultChildRegistry::Register r("menu_holder"); LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p) : LLMenuHolderGL(p) {} bool LLViewerMenuHolderGL::hideMenus() { bool handled = false; if (LLMenuHolderGL::hideMenus()) { handled = true; } // drop pie menu selection mParcelSelection = nullptr; mObjectSelection = nullptr; if (gMenuBarView) { gMenuBarView->clearHoverItem(); gMenuBarView->resetMenuTrigger(); } return handled; } void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle selection) { mParcelSelection = selection; } void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle selection) { mObjectSelection = selection; } const LLRect LLViewerMenuHolderGL::getMenuRect() const { return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT); } void handle_web_browser_test(const LLSD& param) { std::string url = param.asString(); if (url.empty()) { url = "about:blank"; } LLWeb::loadURLInternal(url); } bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) // YES { //clear cache LLAppViewer::instance()->purgeCacheImmediate(); } return false; } void handle_cache_clear_immediately() { LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); } void handle_web_content_test(const LLSD& param) { std::string url = param.asString(); LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true); } void handle_show_url(const LLSD& param) { std::string url = param.asString(); if (LLWeb::useExternalBrowser(url)) { LLWeb::loadURLExternal(url); } else { LLWeb::loadURLInternal(url); } } void handle_report_bug(const LLSD& param) { std::string url = gSavedSettings.getString("ReportBugURL"); LLWeb::loadURLExternal(url); } void handle_buy_currency_test() { std::string url = "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]"; LLStringUtil::format_map_t replace; replace["[AGENT_ID]"] = gAgent.getID().asString(); replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString(); replace["[LANGUAGE]"] = LLUI::getLanguage(); LLStringUtil::format(url, replace); LL_INFOS() << "buy currency url " << url << LL_ENDL; LLFloaterReg::showInstance("buy_currency_html", LLSD(url)); } // SUNSHINE CLEANUP - is only the request update at the end needed now? void handle_rebake_textures() { if (!isAgentAvatarValid()) return; // Slam pending upload count to "unstick" things bool slam_for_debug = true; gAgentAvatarp->forceBakeAllTextures(slam_for_debug); if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) { LLAppearanceMgr::instance().requestServerAppearanceUpdate(); } } void toggle_visibility(LLView* viewp) { viewp->setVisible(!viewp->getVisible()); } bool get_visibility(LLView* viewp) { return viewp->getVisible(); } class LLViewShowHoverTips : public view_listener_t { bool handleEvent(const LLSD& userdata) { gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips")); return true; } }; class LLViewCheckShowHoverTips : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = gSavedSettings.getBOOL("ShowHoverTips"); return new_value; } }; class LLViewHighlightTransparent : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; // invisible objects skip building their render batches unless sShowDebugAlpha is true, so rebuild batches whenever toggling this flag gPipeline.rebuildDrawInfo(); return true; } }; class LLViewCheckHighlightTransparent : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLDrawPoolAlpha::sShowDebugAlpha; return new_value; } }; class LLViewBeaconWidth : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string width = userdata.asString(); if(width == "1") { gSavedSettings.setS32("DebugBeaconLineWidth", 1); } else if(width == "4") { gSavedSettings.setS32("DebugBeaconLineWidth", 4); } else if(width == "16") { gSavedSettings.setS32("DebugBeaconLineWidth", 16); } else if(width == "32") { gSavedSettings.setS32("DebugBeaconLineWidth", 32); } return true; } }; class LLViewToggleBeacon : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string beacon = userdata.asString(); if (beacon == "scriptsbeacon") { LLPipeline::toggleRenderScriptedBeacons(); gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); // toggle the other one off if it's on if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) { LLPipeline::toggleRenderScriptedTouchBeacons(); gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); } } else if (beacon == "physicalbeacon") { LLPipeline::toggleRenderPhysicalBeacons(); gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons() ); } else if (beacon == "moapbeacon") { LLPipeline::toggleRenderMOAPBeacons(); gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons() ); } else if (beacon == "soundsbeacon") { LLPipeline::toggleRenderSoundBeacons(); gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons() ); } else if (beacon == "particlesbeacon") { LLPipeline::toggleRenderParticleBeacons(); gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons() ); } else if (beacon == "scripttouchbeacon") { LLPipeline::toggleRenderScriptedTouchBeacons(); gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); // toggle the other one off if it's on if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) { LLPipeline::toggleRenderScriptedBeacons(); gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); } } else if (beacon == "sunbeacon") { gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon")); } else if (beacon == "moonbeacon") { gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon")); } else if (beacon == "renderbeacons") { LLPipeline::toggleRenderBeacons(); gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); // toggle the other one on if it's not if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) { LLPipeline::toggleRenderHighlights(); gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); } } else if (beacon == "renderhighlights") { LLPipeline::toggleRenderHighlights(); gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); // toggle the other one on if it's not if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) { LLPipeline::toggleRenderBeacons(); gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); } } return true; } }; class LLViewCheckBeaconEnabled : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string beacon = userdata.asString(); bool new_value = false; if (beacon == "scriptsbeacon") { new_value = gSavedSettings.getBOOL( "scriptsbeacon"); LLPipeline::setRenderScriptedBeacons(new_value); } else if (beacon == "moapbeacon") { new_value = gSavedSettings.getBOOL( "moapbeacon"); LLPipeline::setRenderMOAPBeacons(new_value); } else if (beacon == "physicalbeacon") { new_value = gSavedSettings.getBOOL( "physicalbeacon"); LLPipeline::setRenderPhysicalBeacons(new_value); } else if (beacon == "soundsbeacon") { new_value = gSavedSettings.getBOOL( "soundsbeacon"); LLPipeline::setRenderSoundBeacons(new_value); } else if (beacon == "particlesbeacon") { new_value = gSavedSettings.getBOOL( "particlesbeacon"); LLPipeline::setRenderParticleBeacons(new_value); } else if (beacon == "scripttouchbeacon") { new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); LLPipeline::setRenderScriptedTouchBeacons(new_value); } else if (beacon == "renderbeacons") { new_value = gSavedSettings.getBOOL( "renderbeacons"); LLPipeline::setRenderBeacons(new_value); } else if (beacon == "renderhighlights") { new_value = gSavedSettings.getBOOL( "renderhighlights"); LLPipeline::setRenderHighlights(new_value); } return new_value; } }; class LLViewToggleRenderType : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string type = userdata.asString(); if (type == "hideparticles") { LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); } return true; } }; class LLViewCheckRenderType : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string type = userdata.asString(); bool new_value = false; if (type == "hideparticles") { new_value = LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES); } return new_value; } }; class LLViewStatusAway : public view_listener_t { bool handleEvent(const LLSD& userdata) { return (gAgent.isInitialized() && gAgent.getAFK()); } }; class LLViewStatusDoNotDisturb : public view_listener_t { bool handleEvent(const LLSD& userdata) { return (gAgent.isInitialized() && gAgent.isDoNotDisturb()); } }; class LLViewShowHUDAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; return true; } }; class LLViewCheckHUDAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool new_value = LLPipeline::sShowHUDAttachments; return new_value; } }; class LLEditEnableTakeOff : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string clothing = userdata.asString(); LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) return LLAgentWearables::selfHasWearable(type); return false; } }; class LLEditTakeOff : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string clothing = userdata.asString(); if (clothing == "all") LLAppearanceMgr::instance().removeAllClothesFromAvatar(); else { LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT && (gAgentWearables.getWearableCount(type) > 0)) { // MULTI-WEARABLES: assuming user wanted to remove top shirt. U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); LLAppearanceMgr::instance().removeItemFromAvatar(item_id); } } return true; } }; class LLToolsSelectTool : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string tool_name = userdata.asString(); if (tool_name == "focus") { LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1); } else if (tool_name == "move") { LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2); } else if (tool_name == "edit") { LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3); } else if (tool_name == "create") { LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4); } else if (tool_name == "land") { LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5); } // Note: if floater is not visible LLViewerWindow::updateLayout() will // attempt to open it, but it won't bring it to front or de-minimize. if (gFloaterTools && (gFloaterTools->isMinimized() || !gFloaterTools->isShown() || !gFloaterTools->isFrontmost())) { gFloaterTools->setMinimized(false); gFloaterTools->openFloater(); gFloaterTools->setVisibleAndFrontmost(true); } return true; } }; /// WINDLIGHT callbacks void defocusEnvFloaters() { // currently there is only one instance of each floater std::vector env_floaters_names = {"env_edit_extdaycycle", "env_fixed_environmentent_water", "env_fixed_environmentent_sky"}; for (std::vector::const_iterator it = env_floaters_names.begin(); it != env_floaters_names.end(); ++it) { LLFloater *env_floater = LLFloaterReg::findTypedInstance(*it); if (env_floater) { env_floater->setFocus(false); } } } bool handle_env_setting_event(std::string event_name) { if (event_name == "sunrise") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "noon") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "legacy noon") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "sunset") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "midnight") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "region") { // reset probe data when reverting back to region sky setting gPipeline.mReflectionMapManager.reset(); LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "pause_clouds") { if (LLEnvironment::instance().isCloudScrollPaused()) LLEnvironment::instance().resumeCloudScroll(); else LLEnvironment::instance().pauseCloudScroll(); } else if (event_name == "adjust_tool") { LLFloaterReg::showInstance("env_adjust_snapshot"); } else if (event_name == "my_environs") { LLFloaterReg::showInstance("my_environments"); } return true; } class LLWorldEnvSettings : public view_listener_t { bool handleEvent(const LLSD& userdata) { handle_env_setting_event(userdata.asString()); return true; } }; class LLWorldEnableEnvSettings : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool result = false; std::string event_name = userdata.asString(); if (event_name == "pause_clouds") { return LLEnvironment::instance().isCloudScrollPaused(); } LLSettingsSky::ptr_t sky = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL); if (!sky) { return (event_name == "region"); } std::string skyname = (sky) ? sky->getName() : ""; LLUUID skyid = (sky) ? sky->getAssetId() : LLUUID::null; if (event_name == "sunrise") { result = (skyid == LLEnvironment::KNOWN_SKY_SUNRISE); } else if (event_name == "noon") { result = (skyid == LLEnvironment::KNOWN_SKY_MIDDAY); } else if (event_name == "legacy noon") { result = (skyid == LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY); } else if (event_name == "sunset") { result = (skyid == LLEnvironment::KNOWN_SKY_SUNSET); } else if (event_name == "midnight") { result = (skyid == LLEnvironment::KNOWN_SKY_MIDNIGHT); } else if (event_name == "region") { return false; } else { LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL; } return result; } }; class LLWorldEnvPreset : public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string item = userdata.asString(); if (item == "new_water") { LLFloaterReg::showInstance("env_fixed_environmentent_water", "new"); } else if (item == "edit_water") { LLFloaterReg::showInstance("env_fixed_environmentent_water", "edit"); } else if (item == "new_sky") { LLFloaterReg::showInstance("env_fixed_environmentent_sky", "new"); } else if (item == "edit_sky") { LLFloaterReg::showInstance("env_fixed_environmentent_sky", "edit"); } else if (item == "new_day_cycle") { LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory")); } else if (item == "edit_day_cycle") { LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory")); } else { LL_WARNS() << "Unknown item selected" << LL_ENDL; } return true; } }; class LLWorldEnableEnvPreset : public view_listener_t { bool handleEvent(const LLSD& userdata) { return false; } }; class LLWorldCheckBanLines : public view_listener_t { bool handleEvent(const LLSD& userdata) { S32 callback_data = userdata.asInteger(); return gSavedSettings.getS32("ShowBanLines") == callback_data; } }; class LLWorldShowBanLines : public view_listener_t { bool handleEvent(const LLSD& userdata) { S32 callback_data = userdata.asInteger(); gSavedSettings.setS32("ShowBanLines", callback_data); return true; } }; void handle_flush_name_caches() { if (gCacheName) gCacheName->clear(); } class LLUploadCostCalculator : public view_listener_t { std::string mCostStr; bool handleEvent(const LLSD& userdata) { std::vector fields; std::string str = userdata.asString(); boost::split(fields, str, boost::is_any_of(",")); if (fields.size()<1) { return false; } std::string menu_name = fields[0]; std::string asset_type_str = "texture"; if (fields.size()>1) { asset_type_str = fields[1]; } LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL; calculateCost(asset_type_str); gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr); return true; } void calculateCost(const std::string& asset_type_str); public: LLUploadCostCalculator() { } }; class LLUpdateMembershipLabel : public view_listener_t { bool handleEvent(const LLSD& userdata) { const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText"); gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str); return true; } }; class LLToggleUIHints : public view_listener_t { bool handleEvent(const LLSD& userdata) { bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints"); // toggle ui_hints_enabled = !ui_hints_enabled; gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled); return true; } }; void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str) { S32 upload_cost = -1; if (asset_type_str == "texture") { // This use minimal texture cost to allow bulk and // texture upload menu options to be visible upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); } else if (asset_type_str == "animation") { upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost(); } else if (asset_type_str == "sound") { upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost(); } if (upload_cost < 0) { LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL; } mCostStr = std::to_string(upload_cost); } void lua_run_script(const LLSD& userdata) { std::string script_path = userdata.asString(); if (script_path.empty()) { LL_WARNS() << "Script name is not specified" << LL_ENDL; return; } LLLUAmanager::runScriptFile(script_path); } void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y) { static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if(gMenuHolder->hasVisibleMenu()) { gMenuHolder->hideMenus(); } show_navbar_context_menu->buildDrawLabels(); show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y); } void show_topinfobar_context_menu(LLView* ctrl, S32 x, S32 y) { static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_topinfobar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild("Landmark"); if (!LLLandmarkActions::landmarkAlreadyExists()) { landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu")); } else { landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu")); } if(gMenuHolder->hasVisibleMenu()) { gMenuHolder->hideMenus(); } show_topbarinfo_context_menu->buildDrawLabels(); show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y); } void initialize_edit_menu() { view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo"); view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo"); view_listener_t::addMenu(new LLEditCut(), "Edit.Cut"); view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy"); view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste"); view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete"); view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll"); view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect"); view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff"); view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo"); view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo"); view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut"); view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy"); view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste"); view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete"); view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll"); view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect"); } typedef LLUICtrl::CommitCallbackInfo cb_info; void initialize_spellcheck_menu() { LLUICtrl::CommitRegistrarHelper registrar(LLUICtrl::CommitCallbackRegistry::defaultRegistrar()); LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); registrar.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2), cb_info::UNTRUSTED_BLOCK); enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2)); registrar.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1), cb_info::UNTRUSTED_BLOCK); enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1)); registrar.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1), cb_info::UNTRUSTED_BLOCK); enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1)); } void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. class LLZoomer : public view_listener_t { public: // The "mult" parameter says whether "val" is a multiplier or used to set the value. LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {} bool handleEvent(const LLSD& userdata) { F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal; LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad); gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it. return true; } private: F32 mVal; bool mMult; }; LLUICtrl::CommitRegistrarHelper registrar(LLUICtrl::CommitCallbackRegistry::currentRegistrar()); LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); // Generic enable and visible // Don't prepend MenuName.Foo because these can be used in any menu. enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel"); enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); // Agent registrar.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying)); enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land)); registrar.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2), cb_info::UNTRUSTED_BLOCK); registrar.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2), cb_info::UNTRUSTED_BLOCK); registrar.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2), cb_info::UNTRUSTED_BLOCK); enable.add("Agent.IsMicrophoneOn", boost::bind(&LLAgent::isMicrophoneOn, _2)); enable.add("Agent.IsActionAllowed", boost::bind(&LLAgent::isActionAllowed, _2)); // File menu init_menu_file(); view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff"); view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar"); view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape"); view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight"); view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics"); registrar.add("CustomizeAvatar", boost::bind(&handle_customize_avatar)); registrar.add("NowWearing", boost::bind(&handle_now_wearing)); registrar.add("EditOutfit", boost::bind(&handle_edit_outfit)); registrar.add("EditShape", boost::bind(&handle_edit_shape)); registrar.add("HoverHeight", boost::bind(&handle_hover_height)); registrar.add("EditPhysics", boost::bind(&handle_edit_physics)); // View menu view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook"); view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam"); view_listener_t::addMenu(new LLViewResetView(), "View.ResetView"); view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut"); view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn"); view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault"); view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize"); view_listener_t::addMenu(new LLViewToggleUI(), "View.ToggleUI"); view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook"); view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam"); view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter"); view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); //Communicate Nearby chat view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat"); // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile"); view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation"); view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway"); view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb"); view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome"); view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark"); view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation"); view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome"); view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand"); view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun"); view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings"); view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings"); view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset"); view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset"); view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines"); view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines"); // Tools menu view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects"); view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects"); view_listener_t::addMenu(new LLToolsSelectReflectionProbes(), "Tools.SelectReflectionProbes"); view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding"); view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection"); view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius"); view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts"); view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY"); view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid"); view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart"); registrar.add("Tools.Link", boost::bind(&handle_link_objects)); registrar.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance())); view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations"); view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys"); view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys"); registrar.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2)); registrar.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take), cb_info::UNTRUSTED_THROTTLE); registrar.add("Tools.TakeCopy", boost::bind(&handle_take_copy), cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory"); view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction"); view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie"); view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart"); enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance())); enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance())); view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake"); enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy)); enable.add("Tools.EnableCopySeparate", boost::bind(&enable_take_copy_objects)); enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object)); enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object)); view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory"); view_listener_t::addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); view_listener_t::addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); view_listener_t::addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion"); view_listener_t::addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion"); // Help menu // most items use the ShowFloater method view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo"); // Advanced menu view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole"); view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole"); view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole"); // Advanced > HUD Info view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo"); view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo"); // Advanced Other Settings view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache"); // Advanced > Render > Types view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType"); view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType"); //// Advanced > Render > Features 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"); // Advanced > Render > Info Displays view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay"); view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay"); view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo"); registrar.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info)); view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe"); view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); // Develop > Render view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate"); view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate"); view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame"); view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame"); view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles"); view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption"); view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption"); view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedClickGLTFOpen(), "Advanced.ClickGLTFOpen", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedClickGLTFSaveAs(), "Advanced.ClickGLTFSaveAs", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedClickGLTFUpload(), "Advanced.ClickGLTFUpload", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedClickGLTFEdit(), "Advanced.ClickGLTFEdit", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedClickResizeWindow(), "Advanced.ClickResizeWindow", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain", cb_info::UNTRUSTED_BLOCK); #ifdef TOGGLE_HACKED_GODLIKE_VIEWER view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode"); view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode"); view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode"); #endif // Advanced > World view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera"); view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache"); view_listener_t::addMenu(new LLAdvancedToggleStatsRecorder(), "Advanced.ToggleStatsRecorder"); view_listener_t::addMenu(new LLAdvancedCheckStatsRecorder(), "Advanced.CheckStatsRecorder"); view_listener_t::addMenu(new LLAdvancedToggleInterestList360Mode(), "Advanced.ToggleInterestList360Mode"); view_listener_t::addMenu(new LLAdvancedCheckInterestList360Mode(), "Advanced.CheckInterestList360Mode"); view_listener_t::addMenu(new LLAdvancedResetInterestLists(), "Advanced.ResetInterestLists"); // Develop > Terrain view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); view_listener_t::addMenu(new LLAdvancedTerrainCreateLocalPaintMap(), "Advanced.TerrainCreateLocalPaintMap"); view_listener_t::addMenu(new LLAdvancedTerrainEditLocalPaintMap(), "Advanced.TerrainEditLocalPaintMap"); view_listener_t::addMenu(new LLAdvancedTerrainDeleteLocalPaintMap(), "Advanced.TerrainDeleteLocalPaintMap"); // Advanced > UI registrar.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser registrar.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater registrar.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); registrar.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2)); view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); registrar.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers), cb_info::UNTRUSTED_THROTTLE); registrar.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus)); view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo"); view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo"); view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks"); view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks"); view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews"); view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews"); view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode"); view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode"); view_listener_t::addMenu(new LLAdvancedCheckDebugCamera(), "Advanced.CheckDebugCamera"); view_listener_t::addMenu(new LLAdvancedToggleDebugCamera(), "Advanced.ToggleDebugCamera"); view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips"); view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips"); view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents"); view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents"); view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys"); view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys"); view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc"); view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc"); // Advanced > XUI registrar.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance())); view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames"); view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames"); view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs"); registrar.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches), cb_info::UNTRUSTED_BLOCK); // Advanced > Character > Grab Baked Texture view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture"); view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture"); // Advanced > Character > Character Tests view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML"); view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML"); view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry"); view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale", cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale", cb_info::UNTRUSTED_THROTTLE); // Advanced > Character > Animation Speed view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster"); view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower"); view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll"); // Advanced > Character (toplevel) view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader"); view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo"); view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo"); view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt"); view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt"); view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt"); view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt"); view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates"); view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates"); view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD"); view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD"); view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis"); view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures"); view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); // Advanced > Network view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog"); view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog"); view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket"); // Advanced > Cache view_listener_t::addMenu(new LLAdvancedPurgeDiskCache(), "Advanced.PurgeDiskCache", cb_info::UNTRUSTED_BLOCK); // Advanced > Recorder view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot"); view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder"); // Advanced > Debugging view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorLlerrorMsg(), "Advanced.ForceErrorLlerrorMsg", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceOSException(), "Advanced.ForceErrorOSException", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer", cb_info::UNTRUSTED_BLOCK); // Advanced (toplevel) view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates"); view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); view_listener_t::addMenu(new LLAdvancedCompressFileTest(), "Advanced.CompressFileTest", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings"); view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector"); view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus"); // Develop >Set logging level view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); //Develop (clear cache immediately) registrar.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately), cb_info::UNTRUSTED_BLOCK); // Develop (Fonts debugging) registrar.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts), cb_info::UNTRUSTED_THROTTLE); registrar.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures), cb_info::UNTRUSTED_THROTTLE); // Admin >Object view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf"); view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive"); view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete"); view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock"); view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs"); // Admin >Parcel view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe"); view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent"); view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand"); // Admin >Region view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData"); // Admin top level view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState"); // Self context menu view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand"); enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand)); view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments"); view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments"); // we don't use boost::bind directly to delay side tray construction view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab"); view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab"); // Avatar pie menu view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode"); view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode"); view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend"); view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); registrar.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD())); view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug"); view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); registrar.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD())); registrar.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", cb_info::UNTRUSTED_BLOCK); enable.add("Avatar.EnableCall", boost::bind(&LLAvatarCall::isAvailable)); view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse", cb_info::UNTRUSTED_THROTTLE); 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 LLAvatarResetSkeleton(), "Avatar.ResetSkeleton", cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); view_listener_t::addMenu(new LLAvatarResetSelfSkeleton(), "Avatar.ResetSelfSkeleton"); view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations"); enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible)); enable.add("Avatar.IsPicksTabOpen", boost::bind(&picks_tab_visible)); registrar.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL"))); view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2)); // Object pie menu view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); registrar.add("Object.Touch", boost::bind(&handle_object_touch)); registrar.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); registrar.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); registrar.add("Object.Delete", boost::bind(&handle_object_delete)); view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar"); view_listener_t::addMenu(new LLObjectReturn(), "Object.Return"); registrar.add("Object.Duplicate", boost::bind(&LLSelectMgr::duplicate, LLSelectMgr::getInstance())); view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse", cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLObjectMute(), "Object.Mute"); enable.add("Object.VisibleTake", boost::bind(&visible_take_object)); enable.add("Object.VisibleTakeMultiple", boost::bind(&is_multiple_selection)); enable.add("Object.VisibleTakeSingle", boost::bind(&is_single_selection)); enable.add("Object.EnableTakeMultiple", boost::bind(&enable_take_objects)); enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object)); registrar.add("Object.Buy", boost::bind(&handle_buy), cb_info::UNTRUSTED_THROTTLE); registrar.add("Object.Edit", boost::bind(&handle_object_edit)); registrar.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material)); registrar.add("Object.Inspect", boost::bind(&handle_object_inspect)); registrar.add("Object.Open", boost::bind(&handle_object_open)); registrar.add("Object.Take", boost::bind(&handle_take, false)); registrar.add("Object.TakeSeparate", boost::bind(&handle_take, true)); registrar.add("Object.TakeSeparateCopy", boost::bind(&handle_take_separate_copy)); registrar.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector)); enable.add("Object.EnableInspect", boost::bind(&enable_object_inspect)); enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material)); enable.add("Object.EnableOpen", boost::bind(&enable_object_open)); enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1)); enable.add("Object.EnableDelete", boost::bind(&enable_object_delete)); enable.add("Object.EnableWear", boost::bind(&object_is_wearable)); enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up)); enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1)); view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn"); enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance())); view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute)); enable.add("Object.EnableMute", boost::bind(&enable_object_mute)); enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute)); enable.add("Object.EnableBuy", boost::bind(&enable_buy_object)); registrar.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom")); // Attachment pie menu enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2)); view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop"); view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint"); view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach"); view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled"); view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop"); view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach"); // Land pie menu view_listener_t::addMenu(new LLLandBuild(), "Land.Build"); view_listener_t::addMenu(new LLLandSit(), "Land.Sit"); view_listener_t::addMenu(new LLLandCanSit(), "Land.CanSit"); view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass"); view_listener_t::addMenu(new LLLandEdit(), "Land.Edit"); // Particle muting view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute"); view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass"); registrar.add("Land.Buy", boost::bind(&handle_buy_land), cb_info::UNTRUSTED_THROTTLE); // Generic actions registrar.add("ReportAbuse", boost::bind(&handle_report_abuse), cb_info::UNTRUSTED_THROTTLE); registrar.add("BuyCurrency", boost::bind(&handle_buy_currency), cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLShowHelp(), "ShowHelp"); view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp"); view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak", cb_info::UNTRUSTED_BLOCK); view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL"); view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks"); view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile"); view_listener_t::addMenu(new LLToggleControl(), "ToggleControl"); view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl"); view_listener_t::addMenu(new LLCheckControl(), "CheckControl"); view_listener_t::addMenu(new LLGoToObject(), "GoToObject"); registrar.add("PayObject", boost::bind(&handle_give_money_dialog)); registrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow), cb_info::UNTRUSTED_THROTTLE); enable.add("EnablePayObject", boost::bind(&enable_pay_object)); enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); enable.add("EnableEdit", boost::bind(&enable_object_edit)); enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle)); registrar.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects)); enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets)); enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets)); registrar.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects)); enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters)); enable.add("Advanced.EnableErrorOSException", boost::bind(&enable_os_exception)); enable.add("EnableGLTF", boost::bind(&enable_gltf)); enable.add("EnableGLTFSaveAs", boost::bind(&enable_gltf_save_as)); enable.add("EnableGLTFUpload", boost::bind(&enable_gltf_upload)); enable.add("EnableTerrainLocalPaintMap", std::bind(&enable_terrain_local_paintmap)); view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible"); view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel"); view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible"); view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected"); view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD"); view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected"); view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono"); view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints"); registrar.add("Lua.RunScript", boost::bind(&lua_run_script, _2), cb_info::UNTRUSTED_BLOCK); }