summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@lindenlab.com>2025-06-25 14:32:09 -0400
committerGitHub <noreply@github.com>2025-06-25 14:32:09 -0400
commite15a89282171251924a7c75c9007f1cfbc37a8be (patch)
tree43740d9cba9f41d2f5cdc3b60cdcc107379bfda9 /indra
parentfeb4494365e019efd68d6881e4ff63e939a01264 (diff)
parent6c394f02829ae11b80385d3ff1884a70e623bdef (diff)
Merge pull request #4177 from DarlCat/hud-media-autoplay
Media changes including support for PRIM_MEDIA_FIRST_CLICK_INTERACT and HUD autoplay
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/lltoolpie.cpp147
-rw-r--r--indra/newview/lltoolpie.h20
-rw-r--r--indra/newview/llvovolume.cpp11
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml236
5 files changed, 342 insertions, 94 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 8cfe4f3d97..b515540e1e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -16190,5 +16190,27 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MediaAutoPlayHuds</key>
+ <map>
+ <key>Comment</key>
+ <string>Automatically play HUD media</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MediaFirstClickInteract</key>
+ <map>
+ <key>Comment</key>
+ <string>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.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
</map>
</llsd>
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<S32> 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<LLViewerObject> 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 fb6aa7a326..b96df0c79f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2643,6 +2643,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<bool> 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..efe3d4fb42 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" />
- <!-- *HACK
- After storm-1109 will be fixed: instead of using this text_box, word_wrap should be applied for "mute_when_minimized" check_box's label.-->
- <text
- follows="top|left"
- height="15"
- layout="topleft"
- left_pad="0"
- name="mute_chb_label"
- top_delta="-1"
- width="150"
- wrap="true">
- Mute when minimized
- </text>
+ width="20"
+ label="Mute when minimized"
+ word_wrap="true"/>
<slider
control_name="AudioLevelUI"
disabled_control="MuteAudio"
@@ -321,66 +310,45 @@
left_pad="5"
name="enable_voice_check"
width="110"/>
- <!-- -->
<text
type="string"
length="1"
follows="left|top"
layout="topleft"
left="23"
- top_delta="22"
+ top_delta="25"
name="Listen media from"
height="15"
- word_wrap="true"
- width="112">
- Hear media and sounds from:
+ width="165"
+ halign="right">
+ Hear media and sounds from
</text>
- <radio_group
+ <combo_box
control_name="MediaSoundsEarLocation"
follows="left|top"
- top_delta="-6"
layout="topleft"
- left_pad="10"
- width="360"
- height="40"
- name="media_ear_location">
- <radio_item
- height="19"
- label="Camera position"
- follows="left|top"
- layout="topleft"
- name="0"
- width="200"/>
- <radio_item
- height="19"
- follows="left|top"
- label="Avatar position"
- layout="topleft"
- left_delta="0"
- name="1"
- top_delta ="18"
- width="200" />
- </radio_group>
- <check_box
- name="media_show_on_others_btn"
- control_name="MediaShowOnOthers"
- value="true"
- follows="left|top"
- layout="topleft"
- height="15"
- top_pad="8"
- tool_tip="Uncheck this to hide media attached to other avatars nearby"
- label="Play media attached to other avatars"
- left="20"
- width="230"/>
+ left_pad="5"
+ width="130"
+ height="23"
+ top_delta="-4"
+ name="media_ear_location_combo">
+ <item
+ label="Camera position"
+ name="camera_position"
+ value="0" />
+ <item
+ label="Avatar position"
+ name="avatar_position"
+ value="1" />
+</combo_box>
<text
follows="left|top"
layout="topleft"
height="15"
left="23"
- top_pad="8"
- width="120"
- name="media_autoplay_label">
+ width="165"
+ name="media_autoplay_label"
+ halign="right">
Auto-play media
</text>
<combo_box
@@ -389,10 +357,10 @@
follows="left|top"
layout="topleft"
height="23"
- left_pad="-15"
+ left_delta="170"
top_delta="-4"
name="media_auto_play_combo"
- width="115">
+ width="130">
<item
label="Never"
name="autoplay_disabled"
@@ -406,23 +374,106 @@
name="autoplay_ask"
value="2"/>
</combo_box>
+ <text
+ follows="left|top"
+ layout="topleft"
+ height="15"
+ left="23"
+ width="165"
+ name="media_firstinteract_label"
+ halign="right">
+ Media first-interact
+ </text>
+ <combo_box
+ control_name="MediaFirstClickInteract"
+ enabled_control="AudioStreamingMedia"
+ follows="left|top"
+ layout="topleft"
+ height="23"
+ left_delta="170"
+ top_delta="-4"
+ width="130"
+ name="media_first_interact_combo"
+ tool_tip="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. Each option also inherits the previous ones.">
+ <item
+ label="Disabled"
+ name="media_first_click_none"
+ value="0"/>
+ <item
+ label="Worn HUDs only"
+ name="media_first_click_hud"
+ value="1"/>
+ <item
+ label="Owned objects"
+ name="media_first_click_own"
+ value="3"/>
+ <item
+ label="Friend objects"
+ name="media_first_click_group"
+ value="7"/>
+ <item
+ label="Group objects"
+ name="media_first_click_friend"
+ value="15"/>
+ <item
+ label="Landowner objects"
+ name="media_first_click_land"
+ value="31"/>
+ <item
+ label="Any object"
+ name="media_first_interact_any"
+ value="31"/>
+ <item
+ label="All MOAP"
+ name="media_first_click_all"
+ value="1073741824"/>
+ </combo_box>
+ <check_box
+ name="media_show_on_others_btn"
+ control_name="MediaShowOnOthers"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|top"
+ tool_tip="Uncheck this to hide media attached to other avatars nearby"
+ label="Play media attached to other avatars"
+ left="23"
+ width="15"
+ top_delta="30"
+ height="15"/>
+ <check_box
+ name="media_huds_autoplay"
+ control_name="MediaAutoPlayHuds"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|top"
+ layout="topleft"
+ tool_tip="Uncheck this to make HUDs follow the standard media auto-play setting"
+ label="Auto-play media attached to your HUD"
+ left="260"
+ top_pad="-15"
+ width="15"
+ height="15"/>
<text
layout="topleft"
+ follows="left"
height="15"
- left="260"
- top_pad="-18"
- width="100"
- name="noise_suppression_label">
- Noise Suppression
+ width="165"
+ name="noise_suppression_label"
+ left="23"
+ top_delta="22"
+ halign="right">
+ Microphone Noise Suppression
</text>
<combo_box
control_name="VoiceNoiseSuppressionLevel"
+ enabled_control="EnableVoiceChat"
+ follows="left|top"
layout="topleft"
+ left_delta="170"
+ top_delta="-6"
+ width="130"
height="23"
- left_pad="10"
- top_pad="-20"
- name="noise_suppression_combo"
- width="80">
+ name="noise_suppression_combo">
<item
label="Off"
name="noise_suppression_none"
@@ -452,48 +503,44 @@
left="23"
top_delta="30"
name="Listen from"
- width="112">
- Hear voice from:
+ width="165"
+ height="15"
+ halign="right">
+ Hear voice from
</text>
- <radio_group
+ <combo_box
enabled_control="EnableVoiceChat"
control_name="VoiceEarLocation"
follows="left|top"
layout="topleft"
- left_pad="10"
+ left_delta="170"
top_delta="-6"
- width="360"
- height="40"
- name="ear_location">
- <radio_item
- height="19"
- label="Camera position"
- follows="left|top"
- layout="topleft"
- name="0"
- width="200"/>
- <radio_item
- height="19"
- follows="left|top"
- label="Avatar position"
- layout="topleft"
- left_delta="0"
- name="1"
- top_delta ="18"
- width="200" />
- </radio_group>
+ width="130"
+ height="23"
+ name="ear_location_combo">
+ <item
+ label="Camera position"
+ name="camera_position"
+ value="0" />
+ <item
+ label="Avatar position"
+ name="avatar_position"
+ value="1" />
+</combo_box>
<check_box
control_name="LipSyncEnabled"
+ enabled_control="EnableVoiceChat"
follows="left|top"
height="15"
label="Move avatar lips when speaking"
layout="topleft"
left="20"
name="enable_lip_sync"
- top_pad="10"
+ top_pad="8"
width="237"/>
<check_box
control_name="VoiceEchoCancellation"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to enable voice echo cancellation"
label="Echo Cancellation"
@@ -516,6 +563,7 @@
top_pad="5"/>
<check_box
control_name="VoiceAutomaticGainControl"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to enable automatic gain control"
label="Automatic Gain Control"
@@ -537,6 +585,7 @@
left="20"/>
<check_box
control_name="VoiceVisualizerEnabled"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to show voice dot indicator above avatars"
label="Show voice dot above avatars"
@@ -547,6 +596,7 @@
width="200"/>
<button
control_name="ShowDeviceSettings"
+ enabled_control="EnableVoiceChat"
follows="left|top"
height="23"
is_toggle="true"