From 3571f35d4ad34387d5bafb55475ad2c6564cd438 Mon Sep 17 00:00:00 2001 From: XenHat <me@xenh.at> Date: Thu, 8 Dec 2022 21:39:14 -0500 Subject: [PATCH] Implement LookAt distance clamping --- .../newview/app_settings/settings_alchemy.xml | 22 +++++ indra/newview/llfloaterpreference.cpp | 8 ++ indra/newview/llfloaterpreference.h | 2 + indra/newview/llhudeffectlookat.cpp | 93 ++++++++++++++++--- .../xui/en/panel_preferences_privacy.xml | 26 ++++++ 5 files changed, 138 insertions(+), 13 deletions(-) diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml index 21e728cac6c..471cd754fe3 100644 --- a/indra/newview/app_settings/settings_alchemy.xml +++ b/indra/newview/app_settings/settings_alchemy.xml @@ -365,6 +365,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>AlchemyLookAtClampEnabled</key> + <map> + <key>Comment</key> + <string>If true, own look at distance will be clamped to a determined distance</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AlchemyLookAtClampDistance</key> + <map> + <key>Comment</key> + <string>Distance at which to clamp own avatar look at</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> <key>AlchemyLookAtShow</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 669d222c825..fd8bc194233 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -365,6 +365,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.RemoveSkin", boost::bind(&LLFloaterPreference::onRemoveSkin, this)); mCommitCallbackRegistrar.add("Pref.ApplySkin", boost::bind(&LLFloaterPreference::onApplySkin, this)); mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this, _2)); + + mCommitCallbackRegistrar.add("Pref.UpdateLookAtClampDistance", boost::bind(&LLFloaterPreference::onUpdateLookAtClampDistance, this, _2)); } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) @@ -888,6 +890,12 @@ void LLFloaterPreference::refreshSkinInfo(const skin_t& skin) getChild<LLTextBase>("skin_notes")->setText(skin.mNotes); } +void LLFloaterPreference::onUpdateLookAtClampDistance(const LLSD& data) +{ + F32 clamp_distance = (F32)(data.asReal()); + gSavedSettings.setF32("AlchemyLookAtClampDistance", clamp_distance); +} + LLFloaterPreference::~LLFloaterPreference() { diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 643d5375600..0b97c34b00f 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -220,6 +220,8 @@ class LLFloaterPreference final : public LLFloater, public LLAvatarPropertiesObs void onSelectSkin(const LLSD& data); void refreshSkinInfo(const skin_t& skin); + void onUpdateLookAtClampDistance(const LLSD& data); + static std::string sSkin; notifications_map mNotificationOptions; bool mGotPersonalInfo; diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 1f49f64f2b6..d7dcba00bc6 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llvoavatar.h" +#include "llvoavatarself.h" // for gAgentAvatarp #include "lldrawable.h" #include "llviewerobjectlist.h" #include "llrendersphere.h" @@ -411,27 +412,51 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec return FALSE; } + auto newTargetLookat = (*mAttentions)[mTargetType]; + // must be same or higher priority than existing effect - if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) + if ((*mAttentions)[target_type].mPriority < newTargetLookat.mPriority) { return FALSE; } F32 current_time = mTimer.getElapsedTimeF32(); - // type of lookat behavior or target object has changed - BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); - - // lookat position has moved a certain amount and we haven't just sent an update - lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && - ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); + bool looking_at_self = false; + if (object != NULL) // Why does this crash? + { + auto objectp = static_cast<LLViewerObject*>(object); + if (objectp->isAvatar()) + { + auto voavatarp = dynamic_cast<LLVOAvatar*>(objectp); + if (voavatarp->isSelf()) + { + looking_at_self = true; + } + } + } + static LLCachedControl<bool> clamp_lookat_enabled(gSavedSettings, "AlchemyLookAtClampEnabled", false); + bool clamp_lookat = clamp_lookat_enabled && !looking_at_self && + newTargetLookat.mName != "Respond" && + newTargetLookat.mName != "Conversation" && + newTargetLookat.mName != "AutoListen"; - if (lookAtChanged) + if (!clamp_lookat) { - mLastSentOffsetGlobal = position; - F32 timeout = (*mAttentions)[target_type].mTimeout; - setDuration(timeout); - setNeedsSendToSim(TRUE); + // type of lookat behavior or target object has changed + BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); + + // lookat position has moved a certain amount and we haven't just sent an update + lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && + ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); + + if (lookAtChanged) + { + mLastSentOffsetGlobal = position; + F32 timeout = (*mAttentions)[target_type].mTimeout; + setDuration(timeout); + setNeedsSendToSim(TRUE); + } } if (target_type == LOOKAT_TARGET_CLEAR) @@ -444,12 +469,54 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec mTargetObject = object; if (object) { - mTargetOffsetGlobal.setVec(position); + if(clamp_lookat) + { + // Pretend to look at the object + mTargetOffsetGlobal.setVec(object->getPositionGlobal() + (LLVector3d)(position * object->getRotationRegion())); + mTargetObject = NULL; + } + else + { + mTargetOffsetGlobal.setVec(position); + } } else { mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); } + + if (clamp_lookat) + { + static LLCachedControl<F32> lookat_clamp_distance(gSavedSettings, "AlchemyLookAtClampDistance", 1.0f); + auto head_position = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); + auto distance = dist_vec(mTargetOffsetGlobal, head_position); + + if (distance > lookat_clamp_distance) + { + auto distance_from_object = (mTargetOffsetGlobal - head_position) * (lookat_clamp_distance / distance); + mTargetOffsetGlobal.setVec(head_position + distance_from_object); + } + + bool lookat_changed = target_type != mTargetType; + + // update position + if (!lookat_changed) + { + auto distance_difference = dist_vec_squared(gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal), mLastSentOffsetGlobal); + auto time_difference = (current_time - mLastSendTime); + if (distance_difference > MIN_DELTAPOS_FOR_UPDATE_SQUARED && time_difference > (1.f / MAX_SENDS_PER_SEC)) + { + lookat_changed = true; + } + } + if (lookat_changed) + { + mLastSentOffsetGlobal = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal); + F32 timeout = (*mAttentions)[target_type].mTimeout; + setDuration(timeout); + setNeedsSendToSim(TRUE); + } + } mKillTime = mTimer.getElapsedTimeF32() + mDuration; update(); diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index e1fe3e0e28c..fec3ac9f4a9 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -216,6 +216,32 @@ tool_tip="Don't show me my own camera crosshairs" top_pad="10" width="350" /> + <check_box + control_name="AlchemyLookAtClampEnabled" + height="16" + label="Limit camera target distance" + layout="topleft" + left="30" + name="privatelookat" + tool_tip="Allows cosmetic features like eye and head movement but will point at nothing specific if beyond the set distance." + top_pad="4" + width="200" /> + <slider + height="16" + left_pad="10" + top_delta="0" + min_val="0.5" + max_val="128" + follows="top|left" + control_name="AlchemyLookAtClampDistance" + initial_value="1.0" + increment="0.5" + label="Max Distance" + width="275" + layout="topleft"> + <button.commit_callback + function="Pref.UpdateLookAtClampDistance" /> + </slider> <check_box control_name="AlchemyLookAtPrivate" height="16" -- GitLab