From ea75bfd4103c4074a8925e8abb14fa73e79821cc Mon Sep 17 00:00:00 2001 From: Darl Date: Fri, 25 Apr 2025 17:46:38 -0500 Subject: Implement support for PRIM_MEDIA_FIRST_CLICK_INTERACT and autoplay for HUD media --- indra/newview/app_settings/settings.xml | 22 ++ indra/newview/lltoolpie.cpp | 147 ++++++++++++- indra/newview/lltoolpie.h | 20 ++ indra/newview/llvovolume.cpp | 11 + .../default/xui/en/panel_preferences_sound.xml | 237 +++++++++++++-------- 5 files changed, 343 insertions(+), 94 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 60ae8ac691..11432dfb98 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16135,5 +16135,27 @@ Value 1 + MediaAutoPlayHuds + + Comment + Automatically play HUD media + Persist + 1 + Type + Boolean + Value + 1 + + MediaFirstClickInteract + + Comment + This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. This setting is a bitfield, precomputed values are as follows: Disabled=0; Worn HUDs only=1; Owned objects=3; Friend objects=7; Group objects=15; Landowner objects=31; Any object=31; All MOAP=1073741824. For complete details see lltoolpie.h enum MediaFirstClickTypes. + Persist + 1 + Type + S32 + Value + 1 + diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 8cdc2e94f4..e5bbc73af0 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -72,6 +72,7 @@ #include "llweb.h" #include "pipeline.h" // setHighlightObject #include "lluiusage.h" +#include "llcallingcard.h" extern bool gDebugClicks; @@ -1501,6 +1502,140 @@ static void handle_click_action_play() } } +bool LLToolPie::shouldAllowFirstMediaInteraction(const LLPickInfo& pick, bool moap_flag) +{ + // Early failure cases + if(!pick.getObject()) + { + LL_WARNS() << "pick.getObject() is NULL" << LL_ENDL; + return false; + } + + static LLCachedControl FirstClickPref(gSavedSettings, "MediaFirstClickInteract", 1); + + // Special / early-exit cases first, then checks get more complex and needy as we go down + // Feature disabled + if(FirstClickPref == MEDIA_FIRST_CLICK_NONE) + { + LL_DEBUGS_ONCE() << "FirstClickPref == MEDIA_FIRST_CLICK_NONE" << LL_ENDL; + return false; + } + // All objects (overriding PRIM_MEDIA_FIRST_CLICK_INTERACT) + if(FirstClickPref == MEDIA_FIRST_CLICK_ALL) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_ALL" << LL_ENDL; + return true; + } + // Every check beyond this point requires PRIM_MEDIA_FIRST_CLICK_INTERACT to be TRUE + if(!moap_flag) + { + LL_DEBUGS_ONCE() << "PRIM_MEDIA_FIRST_CLICK_INTERACT not set" << LL_ENDL; + return false; + } + // Any object with PRIM_MEDIA_FIRST_CLICK_INTERACT set to TRUE + if(FirstClickPref & MEDIA_FIRST_CLICK_ANY) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_ANY" << LL_ENDL; + return true; + } + + // The following checks require some object information so we obtain that + LLPointer object = pick.getObject(); + if(object.isNull()) + { + LL_WARNS() << "pick.getObject() is NULL" << LL_ENDL; + return false; + } + + // Own objects + if((FirstClickPref & MEDIA_FIRST_CLICK_OWN) && object->permYouOwner()) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_OWN" << LL_ENDL; + return true; + } + // HUD attachments + if((FirstClickPref & MEDIA_FIRST_CLICK_HUD) && object->isHUDAttachment()) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_HUD" << LL_ENDL; + return true; + } + + // Further object detail required beyond this point + LLPermissions* perms = LLSelectMgr::getInstance()->getHoverNode()->mPermissions; + if(perms == nullptr) + { + LL_WARNS() << "LLSelectMgr::getInstance()->getHoverNode()->mPermissions is NULL" << LL_ENDL; + return false; + } + LLUUID owner_id = perms->getOwner(); + LLUUID group_id = perms->getGroup(); + if(owner_id.isNull() && group_id.isNull()) + { + LL_WARNS() << "Owner information was not reliably obtained" << LL_ENDL; + return false; + } + + // Check if the object is owned by a friend of the agent + if(FirstClickPref & MEDIA_FIRST_CLICK_FRIEND) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_FRIEND. id: " << owner_id << LL_ENDL; + return LLAvatarTracker::instance().isBuddy(owner_id); + } + + // Check for objects set to or owned by the active group + if(FirstClickPref & MEDIA_FIRST_CLICK_GROUP) + { + // Get our active group + LLUUID active_group = gAgent.getGroupID(); + if(active_group.notNull() && (active_group == group_id || active_group == owner_id)) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_GROUP.Active group: " << active_group << ", group_id:" << group_id << ", owner_id: " << owner_id << LL_ENDL; + return true; + } + } + + // This check ensures that the following conditions are met: + // 1. The object is located in the same parcel as the agent. + // 2. One of the following is true: + // a. The object is owned by the same group as the parcel. + // b. The object is set to the same group as the parcel. + // c. The object is owned by the same owner as the parcel. + // Conditions 2a and 2b are mutually exclusive, our check is the same for both. + if(FirstClickPref & MEDIA_FIRST_CLICK_LAND) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(parcel == nullptr) + { + LL_WARNS() << "LLViewerParcelMgr::getInstance()->getAgentParcel() is NULL" << LL_ENDL; + return false; + } + + // Same parcel as the agent only + if(!LLViewerParcelMgr::getInstance()->inAgentParcel(object->getPositionGlobal())) + { + LL_WARNS_ONCE() << "Object is not in the same parcel as the agent" << LL_ENDL; + return false; + } + + LLUUID parcel_owner = parcel->getOwnerID(); + LLUUID parcel_group = parcel->getGroupID(); + + // The parcel owner and group can't both be null + if(parcel_owner.isNull() && parcel_group.isNull()) + { + LL_WARNS() << "Parcel owner and group are both null" << LL_ENDL; + return false; + } + + if(owner_id == parcel_owner || group_id == parcel_group) + { + LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_LAND. Parcel owner: " << parcel_owner << ", group_id:" << group_id << ", owner_id: " << owner_id << LL_ENDL; + return true; + } + } + return false; +} + bool LLToolPie::handleMediaClick(const LLPickInfo& pick) { //FIXME: how do we handle object in different parcel than us? @@ -1535,6 +1670,16 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) { // It's okay to give this a null impl LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal); + if (shouldAllowFirstMediaInteraction(pick, mep->getFirstClickInteract())) + { + if (media_impl.notNull()) + { + media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(true)); + mMediaMouseCaptureID = mep->getMediaID(); + setMouseCapture(true); + return true; + } + } } else { @@ -1647,7 +1792,7 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick) } // If this is the focused media face, send mouse move events. - if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace)) + if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace) || (shouldAllowFirstMediaInteraction(pick, mep->getFirstClickInteract()))) { media_impl->mouseMove(pick.mUVCoords, gKeyboard->currentMask(true)); gViewerWindow->setCursor(media_impl->getLastSetCursor()); diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index b3884a6bfc..f88fc00b4a 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -89,6 +89,26 @@ private: void showVisualContextMenuEffect(); ECursorType cursorFromObject(LLViewerObject* object); + enum MediaFirstClickTypes + { + MEDIA_FIRST_CLICK_NONE = 0, // Special case: Feature is disabled + MEDIA_FIRST_CLICK_HUD = 1 << 0, // 0b00000001 (1) + MEDIA_FIRST_CLICK_OWN = 1 << 1, // 0b00000010 (2) + MEDIA_FIRST_CLICK_GROUP = 1 << 2, // 0b00000100 (4) + MEDIA_FIRST_CLICK_FRIEND = 1 << 3, // 0b00001000 (8) + MEDIA_FIRST_CLICK_LAND = 1 << 4, // 0b00010000 (16) + + // Covers any object with PRIM_MEDIA_FIRST_CLICK_INTERACT (combines all other flags) + MEDIA_FIRST_CLICK_ANY = MEDIA_FIRST_CLICK_HUD & + MEDIA_FIRST_CLICK_OWN & + MEDIA_FIRST_CLICK_GROUP & + MEDIA_FIRST_CLICK_FRIEND & + MEDIA_FIRST_CLICK_LAND, + + // Covers all media regardless of other rules or PRIM_MEDIA_FIRST_CLICK_INTERACT + MEDIA_FIRST_CLICK_ALL = 1 << 30 // 0b01000000000000000000000000000000 (1073741824) + }; + bool shouldAllowFirstMediaInteraction(const LLPickInfo& info, bool moap_flag); bool handleMediaClick(const LLPickInfo& info); bool handleMediaDblClick(const LLPickInfo& info); bool handleMediaHover(const LLPickInfo& info); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4e8932f912..516d7328c6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2640,6 +2640,17 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m } viewer_media_t media_impl = LLViewerMedia::getInstance()->updateMediaImpl(mep, previous_url, update_from_self); + static LLCachedControl media_autoplay_huds(gSavedSettings, "MediaAutoPlayHuds", true); + bool was_loaded = media_impl->hasMedia(); + if (isHUDAttachment() && media_autoplay_huds && !was_loaded) + { + std::string url = mep->getCurrentURL(); + if (media_impl->getCurrentMediaURL() != url) + { + media_impl->navigateTo(url, "", false, true); + } + } + addMediaImpl(media_impl, texture_index) ; } else diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index d909a56733..3e2f01f105 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -62,20 +62,9 @@ name="mute_when_minimized" top_delta="3" left_pad="5" - width="20" /> - - - Mute when minimized - + width="20" + label="Mute when minimized" + word_wrap="true"/> - - Hear media and sounds from: + width="165" + halign="right"> + Hear media and sounds from - - - - - + left_pad="5" + width="130" + height="23" + top_delta="-4" + name="media_ear_location_combo"> + + + + width="165" + name="media_autoplay_label" + halign="right"> Auto-play media + width="130"> + + Media first-interact + + + + + + + + + + + + + - Noise Suppression + width="165" + name="noise_suppression_label" + left="23" + top_delta="22" + halign="right"> + Microphone Noise Suppression + name="noise_suppression_combo"> - Hear voice from: + width="165" + height="15" + halign="right"> + Hear voice from - - - - + width="130" + height="23" + name="ear_location_combo"> + + +