Skip to content

Commit

Permalink
Experimental: set position in render hook so root translation applies…
Browse files Browse the repository at this point in the history
… without movement
  • Loading branch information
RisaDev committed Nov 21, 2024
1 parent 05b845a commit 35dee4e
Showing 1 changed file with 41 additions and 4 deletions.
45 changes: 41 additions & 4 deletions CustomizePlus/Armatures/Services/ArmatureManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using CustomizePlus.Profiles.Events;
using CustomizePlus.Templates.Events;
using Dalamud.Plugin.Services;
using Lumina.Excel.Sheets;
using OtterGui.Classes;
using OtterGui.Log;
using Penumbra.GameData.Actors;
Expand All @@ -36,6 +37,12 @@ public unsafe sealed class ArmatureManager : IDisposable
private readonly ActorManager _actorManager;
private readonly ArmatureChanged _event;

/// <summary>
/// This is a movement flag for every object. Used to prevent calls to ApplyRootTranslation from both movement and render hooks.
/// I know there are less than 1000 objects in object table but I want to be semi-protected from object table getting bigger in the future.
/// </summary>
private readonly bool[] _objectMovementFlagsArr = new bool[1000];

public Dictionary<ActorIdentifier, Armature> Armatures { get; private set; } = new();

public ArmatureManager(
Expand Down Expand Up @@ -96,7 +103,10 @@ public void OnGameObjectMove(Actor actor)
return;

if (Armatures.TryGetValue(identifier, out var armature) && armature.IsBuilt && armature.IsVisible)
{
_objectMovementFlagsArr[actor.AsObject->ObjectIndex] = true;
ApplyRootTranslation(armature, actor);
}
}

/// <summary>
Expand All @@ -122,12 +132,16 @@ private void RefreshArmatures()
var armature = kvPair.Value;
//Only remove armatures which haven't been seen for a while
//But remove armatures of special actors (like examine screen) right away
if (!_objectManager.Identifiers.ContainsKey(kvPair.Value.ActorIdentifier) &&
if (!_objectManager.Identifiers.TryGetValue(kvPair.Value.ActorIdentifier, out var actorData) &&
(armature.LastSeen <= armatureExpirationDateTime || armature.ActorIdentifier.Type == IdentifierType.Special))
{
_logger.Debug($"Removing armature {armature} because {kvPair.Key.IncognitoDebug()} is gone");
RemoveArmature(armature, ArmatureChanged.DeletionReason.Gone);

//Reset root translation
foreach (var obj in actorData.Objects)
ApplyRootTranslation(null, obj);

continue;
}

Expand Down Expand Up @@ -170,6 +184,11 @@ private void RefreshArmatures()
{
_logger.Debug($"Removing armature {armature} because it doesn't have any active profiles");
RemoveArmature(armature, ArmatureChanged.DeletionReason.NoActiveProfiles);

//Reset root translation
foreach (var actor in obj.Value.Objects)
ApplyRootTranslation(null, actor);

continue;
}

Expand Down Expand Up @@ -198,7 +217,14 @@ private unsafe void ApplyArmatureTransforms()
if (armature.IsBuilt && armature.IsVisible && _objectManager.TryGetValue(armature.ActorIdentifier, out var actorData))
{
foreach (var actor in actorData.Objects)
{
ApplyPiecewiseTransformation(armature, actor, armature.ActorIdentifier);

if (!_objectMovementFlagsArr[actor.AsObject->ObjectIndex])
ApplyRootTranslation(armature, actor);

_objectMovementFlagsArr[actor.AsObject->ObjectIndex] = false;
}
}
}
}
Expand Down Expand Up @@ -298,14 +324,25 @@ private void ApplyPiecewiseTransformation(Armature armature, Actor actor, ActorI
}
}

private void ApplyRootTranslation(Armature arm, Actor actor)
/// <summary>
/// Apply root bone translation. If null armature is passed then position is reset.
/// </summary>
private void ApplyRootTranslation(Armature? arm, Actor actor)
{
//I'm honestly not sure if we should or even can check if cBase->DrawObject or cBase->DrawObject.Object is a valid object
//So for now let's assume we don't need to check for that

//2024/11/21: we no longer check cBase->DrawObject.IsVisible here so we can set object position in render hook.

var cBase = actor.Model.AsCharacterBase;
if (cBase != null)
{
if(arm == null)
{
cBase->DrawObject.Object.Position = actor.AsObject->Position;
return;
}

var rootBoneTransform = arm.GetAppliedBoneTransform("n_root");
if (rootBoneTransform == null)
return;
Expand All @@ -315,8 +352,8 @@ private void ApplyRootTranslation(Armature arm, Actor actor)
rootBoneTransform.Translation.Z == 0)
return;

if (!cBase->DrawObject.IsVisible)
return;
//Reset position so we don't fly away
cBase->DrawObject.Object.Position = actor.AsObject->Position;

var newPosition = new FFXIVClientStructs.FFXIV.Common.Math.Vector3
{
Expand Down

0 comments on commit 35dee4e

Please sign in to comment.