summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-08-24 17:58:46 +0800
committerErik Kundiman <erik@megapahit.org>2026-08-24 17:58:46 +0800
commitba4911d87bb833572b46dd1d6f38264f4c561662 (patch)
tree50b89cf816b2d6ffc528a9c4bc63dd85c9f7b776
parent07ea6d2e85bcdf48787feacecf12918e9a8f89da (diff)
Minimal animation override on existing #AO folderHEADmain
No user facing editor UI, cycle, or randomise yet. Sittings cannot be separately disabled yet. Sitting On Ground doesn't show Stand button (and cannot stand right away from it either unless sitting, but not on ground, on some object, and then stand). Pre-jumping and landing can get you stuck (unless you disable pre-jumping and landing, whose code might be the cause of this stuckness). Standing can get glitchy if idle which might be because of the random cycle of the default stands. The #AO folder can be anywhere, doesn't have to be under some folder with a specific name. AOs are loaded lazily, and per action, not all at once. Reset animation changes by turning AO off and on again. All these limitations will be fixed later.
-rw-r--r--indra/newview/app_settings/commands.xml8
-rw-r--r--indra/newview/app_settings/settings_per_account.xml11
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp126
-rw-r--r--indra/newview/llvoavatar.h7
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/textures/toolbar_icons/ao.pngbin0 -> 236 bytes
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
9 files changed, 165 insertions, 0 deletions
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 9b80b40008..51372e2d16 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -321,4 +321,12 @@
is_running_function="Floater.IsOpen"
is_running_parameters="quick_prefs"
/>
+ <command name="animation_override"
+ available_in_toybox="true"
+ icon="Command_AO_Icon"
+ label_ref="Command_AO_Label"
+ tooltip_ref="Command_AO_Tooltip"
+ execute_function="ToggleAnimationOverride"
+ is_running_function="AreAnimationsOverridden"
+ />
</commands>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 8361a50b6c..2ff54c6034 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -469,5 +469,16 @@
<key>Value</key>
<string></string>
</map>
+ <key>OverrideAnimations</key>
+ <map>
+ <key>Comment</key>
+ <string>Override animations</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 6dc87e9aa3..60ac866b7d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -10053,6 +10053,8 @@ void initialize_menus()
commit.add("HoverHeight", boost::bind(&handle_hover_height));
commit.add("EditPhysics", boost::bind(&handle_edit_physics));
commit.add("QuickPrefs", boost::bind(&handle_quick_prefs)); // Firestorm port
+ commit.add("ToggleAnimationOverride", boost::bind(&LLVOAvatar::toggleAnimationOverride));
+ enable.add("AreAnimationsOverridden", boost::bind(&LLVOAvatar::areAnimationsOverridden));
// View menu
view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0bdcb535a8..4d15126271 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -632,6 +632,8 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f;
LLPointer<LLViewerTexture> LLVOAvatar::sCloudTexture = NULL;
std::vector<LLUUID> LLVOAvatar::sAVsIgnoringARTLimit;
S32 LLVOAvatar::sAvatarsNearby = 0;
+static std::unordered_map<std::string, std::vector<LLUUID>> sAnimationOverriders;
+static bool sOverrideAnimations;
//-----------------------------------------------------------------------------
// Helper functions
@@ -781,6 +783,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mVisuallyMuteSetting = LLVOAvatar::VisualMuteSettings(LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(getID()));
sInstances.push_back(this);
+ sOverrideAnimations = LLCachedControl<bool>(gSavedPerAccountSettings, "OverrideAnimations", false);
}
std::string LLVOAvatar::avString() const
@@ -6368,6 +6371,79 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
}
//-----------------------------------------------------------------------------
+// Animation Override
+//-----------------------------------------------------------------------------
+
+void LLVOAvatar::toggleAnimationOverride()
+{
+ gAgent.stopCurrentAnimations();
+ sOverrideAnimations = !sOverrideAnimations;
+ if (!sOverrideAnimations)
+ sAnimationOverriders.clear();
+ gSavedPerAccountSettings.setBOOL("OverrideAnimations", sOverrideAnimations);
+}
+
+bool LLVOAvatar::areAnimationsOverridden()
+{
+ return sOverrideAnimations;
+}
+
+#define AO_GET_ACTION() \
+ std::string action;\
+ if (remap_id == ANIM_AGENT_CROUCH)\
+ action = "Crouching";\
+ else if (remap_id == ANIM_AGENT_CROUCHWALK)\
+ action = "Crouch Walking";\
+ else if (remap_id == ANIM_AGENT_FALLDOWN)\
+ action = "Falling";\
+ else if (remap_id == ANIM_AGENT_FEMALE_RUN_NEW\
+ || remap_id == ANIM_AGENT_RUN\
+ || remap_id == ANIM_AGENT_RUN_NEW)\
+ action = "Running";\
+ else if (remap_id == ANIM_AGENT_FEMALE_WALK\
+ || remap_id == ANIM_AGENT_FEMALE_WALK_NEW\
+ || remap_id == ANIM_AGENT_WALK\
+ || remap_id == ANIM_AGENT_WALK_NEW)\
+ action = "Walking";\
+ else if (remap_id == ANIM_AGENT_FLY)\
+ action = "Flying";\
+ else if (remap_id == ANIM_AGENT_FLYSLOW)\
+ action = "Flying Slow";\
+ else if (remap_id == ANIM_AGENT_HOVER)\
+ action = "Hovering";\
+ else if (remap_id == ANIM_AGENT_HOVER_DOWN)\
+ action = "Flying Down";\
+ else if (remap_id == ANIM_AGENT_HOVER_UP)\
+ action = "Flying Up";\
+ else if (remap_id == ANIM_AGENT_JUMP)\
+ action = "Jumping";\
+ else if (remap_id == ANIM_AGENT_LAND)\
+ action = "Landing";\
+ else if (remap_id == ANIM_AGENT_PRE_JUMP)\
+ action = "Pre Jumping";\
+ else if (remap_id == ANIM_AGENT_SIT\
+ || remap_id == ANIM_AGENT_SIT_FEMALE\
+ || remap_id == ANIM_AGENT_SIT_GENERIC)\
+ action = "Sitting";\
+ else if (remap_id == ANIM_AGENT_SIT_GROUND\
+ || remap_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)\
+ action = "Sitting On Ground";\
+ else if (remap_id == ANIM_AGENT_STAND\
+ || remap_id == ANIM_AGENT_STAND_1\
+ || remap_id == ANIM_AGENT_STAND_2\
+ || remap_id == ANIM_AGENT_STAND_3\
+ || remap_id == ANIM_AGENT_STAND_4)\
+ action = "Standing";\
+ else if (remap_id == ANIM_AGENT_STANDUP)\
+ action = "Standing Up";\
+ else if (remap_id == ANIM_AGENT_TURNLEFT)\
+ action = "Turning Left";\
+ else if (remap_id == ANIM_AGENT_TURNRIGHT)\
+ action = "Turning Right";\
+ else if (remap_id == ANIM_AGENT_TYPE)\
+ action = "Typing";
+
+//-----------------------------------------------------------------------------
// startMotion()
// id is the asset if of the animation to start
// time_offset is the offset into the animation at which to start playing
@@ -6396,6 +6472,50 @@ bool LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
gAgent.setControlFlags(AGENT_CONTROL_FINISH_ANIM);
return false;
}
+
+ if (sOverrideAnimations)
+ {
+ AO_GET_ACTION();
+ if (!action.empty())
+ {
+ if (sAnimationOverriders.empty() || sAnimationOverriders.find(action) == sAnimationOverriders.end())
+ {
+ auto folderID = gInventory.getRootFolderID();
+ folderID = findDescendentCategoryIDByName(folderID, "#AO");
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(folderID, cats, items);
+ auto iter = cats->begin();
+ for(; cats->end() != iter; ++iter)
+ {
+ auto name = (*iter)->getName();
+ if (name.back() == '*')
+ {
+ folderID = findDescendentCategoryIDByName(folderID, name);
+ gInventory.getDirectDescendentsOf(folderID, cats, items);
+ auto iter = cats->begin();
+ for(; cats->end() != iter; ++iter)
+ {
+ auto name = (*iter)->getName();
+ auto colon = name.find_first_of(':');
+ if (name == action || colon != std::string::npos && !name.compare(0, colon, action))
+ {
+ folderID = findDescendentCategoryIDByName(folderID, name);
+ gInventory.getDirectDescendentsOf(folderID, cats, items);
+ auto iter = items->begin();
+ for(; items->end() != iter; ++iter)
+ sAnimationOverriders[action].push_back((*iter)->getLinkedItem()->getAssetUUID());
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (sAnimationOverriders.find(action) != sAnimationOverriders.end())
+ remap_id = sAnimationOverriders[action].front();
+ }
+ }
}
return LLCharacter::startMotion(remap_id, time_offset);
@@ -6418,6 +6538,12 @@ bool LLVOAvatar::stopMotion(const LLUUID& id, bool stop_immediate)
if (isSelf())
{
+ if (sOverrideAnimations && !sAnimationOverriders.empty())
+ {
+ AO_GET_ACTION();
+ if (!action.empty() && sAnimationOverriders.find(action) != sAnimationOverriders.end())
+ remap_id = sAnimationOverriders[action].front();
+ }
gAgent.onAnimStop(remap_id);
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index cc2a083794..ee1403ff8f 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -1090,6 +1090,13 @@ public:
AnimationSourceMap mAnimationSources; // object ids that triggered anim ids
//--------------------------------------------------------------------
+ // Animation override
+ //--------------------------------------------------------------------
+public:
+ static void toggleAnimationOverride();
+ static bool areAnimationsOverridden();
+
+ //--------------------------------------------------------------------
// Chat
//--------------------------------------------------------------------
public:
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b84d9cf780..5699174f4f 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -166,6 +166,7 @@ with the same filename but different name
<texture name="Command_Voice_Icon" file_name="toolbar_icons/nearbyvoice.png" preload="true" />
<texture name="Command_FavoriteFolder_Icon" file_name="toolbar_icons/favorite_folder.png" preload="true" />
<texture name="Command_Resync_Animations" file_name="toolbar_icons/resync_animations.png" preload="true" />
+ <texture name="Command_AO_Icon" file_name="toolbar_icons/ao.png" preload="true" />
<texture name="Caret_Bottom_Icon" file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />
<texture name="Caret_Right_Icon" file_name="toolbar_icons/caret_right.png" preload="true" scale.left="5" scale.top="15" scale.right="28" scale.bottom="1" />
<texture name="Caret_Left_Icon" file_name="toolbar_icons/caret_left.png" preload="true" scale.left="1" scale.top="15" scale.right="23" scale.bottom="1" />
diff --git a/indra/newview/skins/default/textures/toolbar_icons/ao.png b/indra/newview/skins/default/textures/toolbar_icons/ao.png
new file mode 100644
index 0000000000..20fff67938
--- /dev/null
+++ b/indra/newview/skins/default/textures/toolbar_icons/ao.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 48ee13bf21..2272389125 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -479,6 +479,14 @@
<menu_item_check.on_click
function="World.AlwaysRun" />
</menu_item_check>
+ <menu_item_check
+ label="Override animations"
+ name="AnimationOverride">
+ <menu_item_check.on_check
+ function="AreAnimationsOverridden" />
+ <menu_item_check.on_click
+ function="ToggleAnimationOverride" />
+ </menu_item_check>
<menu_item_separator/>
<menu_item_check
label="Gestures..."
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b442024361..8568874089 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4230,6 +4230,7 @@ name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_Voice_Label">Voice settings</string>
<string name="Command_FavoriteFolder_Label">Favorite folder</string>
<string name="Command_ResyncAnimations_Label">Resync animations</string>
+ <string name="Command_AO_Label">AO</string>
<string
name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
@@ -4266,6 +4267,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_Voice_Tooltip">Volume controls for calls and people near you in world</string>
<string name="Command_FavoriteFolder_Tooltip">Open your favorite inventory folder</string>
<string name="Command_ResyncAnimations_Tooltip">Synchronizes avatar animations</string>
+ <string name="Command_AO_Tooltip">Animation Override</string>
<string name="Toolbar_Bottom_Tooltip">currently in your bottom toolbar</string>
<string name="Toolbar_Left_Tooltip" >currently in your left toolbar</string>