Skip to content

Commit

Permalink
Merge pull request #110 from MKhayle/props
Browse files Browse the repository at this point in the history
feat: Props handling
  • Loading branch information
Minmoose authored Jan 10, 2025
2 parents bdeccf2 + bf847d2 commit 3df5b0b
Show file tree
Hide file tree
Showing 25 changed files with 8,719 additions and 89 deletions.
3 changes: 2 additions & 1 deletion Brio/Capabilities/Actor/ActorAppearanceCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public Task ApplySmallclothes()
return SetAppearance(appearance, AppearanceImportOptions.Gear);
}

public Task ToggelHide()
public Task ToggleHide()
{
var appearance = _actorAppearanceService.GetActorAppearance(Character);

Expand All @@ -175,6 +175,7 @@ public Task ApplyEmperors()
return SetAppearance(appearance, AppearanceImportOptions.Gear);
}


public async Task Redraw()
{
await _actorAppearanceService.Redraw(Character);
Expand Down
44 changes: 41 additions & 3 deletions Brio/Capabilities/Actor/ActorLifetimeCapability.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
using Brio.Entities;
using Brio.Capabilities.Posing;
using Brio.Core;
using Brio.Entities;
using Brio.Entities.Actor;
using Brio.Files;
using Brio.Game.Actor;
using Brio.Game.Actor.Extensions;
using Brio.Game.Core;
using Brio.Game.Posing;
using Brio.Resources;
using Brio.UI.Widgets.Actor;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Plugin.Services;
using Swan.Formatters;

namespace Brio.Capabilities.Actor;

Expand All @@ -14,12 +21,16 @@ internal class ActorLifetimeCapability : ActorCapability

private readonly ActorSpawnService _actorSpawnService;
private readonly EntityManager _entityManager;

public ActorLifetimeCapability(ActorEntity parent, TargetService targetService, ActorSpawnService actorSpawnService, EntityManager entityManager) : base(parent)
private readonly IFramework _framework;
private readonly PosingService _posingService;
public ActorLifetimeCapability(ActorEntity parent, PosingService posingService, TargetService targetService, ActorSpawnService actorSpawnService, EntityManager entityManager, IFramework framework) : base(parent)
{
_targetService = targetService;
_actorSpawnService = actorSpawnService;
_entityManager = entityManager;
_framework = framework;
_posingService = posingService;

Widget = new ActorLifetimeWidget(this);
}

Expand Down Expand Up @@ -47,6 +58,33 @@ public void SpawnNewActor(bool selectInHierarchy, bool spawnCompanion, bool disa
}
}

public unsafe void SpawnNewProp(bool selectInHierarchy)
{
if(_actorSpawnService.CreateCharacter(out ICharacter? chara, SpawnFlags.AsProp | SpawnFlags.CopyPosition, true))
{
if(selectInHierarchy)
{
_entityManager.SetSelectedEntity(chara);
}

_framework.RunUntilSatisfied(
() => chara.Native()->IsReadyToDraw(),
(__) =>
{
var entity = _entityManager.GetEntity(chara.Native());
if(entity is not null)
{
entity.GetCapability<ActionTimelineCapability>().SetOverallSpeedOverride(0);
entity.GetCapability<PosingCapability>().ImportPose(JsonSerializer.Deserialize<PoseFile>(ResourceProvider.Instance.GetRawResourceString("Data.BrioPropPose.pose")), _posingService.SceneImporterOptions);
entity.GetCapability<ActorAppearanceCapability>().AttachWeapon();
}
},
100,
dontStartFor: 2
);
}
}

public void Clone(bool selectInHierarchy)
{
if(!CanClone)
Expand Down
2 changes: 1 addition & 1 deletion Brio/Capabilities/Posing/ModelPosingCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public unsafe Transform Transform
{
if(_transformOverride.HasValue)
return _transformOverride.Value;

return _transformService.GetTransform(GameObject);
}
set
Expand Down
12 changes: 6 additions & 6 deletions Brio/Capabilities/Posing/PosingCapability.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Brio.Capabilities.Actor;
using Brio.Capabilities.Core;
using Brio.Config;
using Brio.Core;
using Brio.Entities.Actor;
Expand Down Expand Up @@ -139,7 +138,7 @@ public void ImportPose(OneOf<PoseFile, CMToolPoseFile> rawPoseFile, PoseImporter
actionTimeline.StopSpeedAndResetTimeline(() =>
{
ImportPose_internal(rawPoseFile, options, reset: false, reconcile: false, asExpression: asExpression, asScene: asScene, asIPCpose: asIPCpose, asBody: asBody);

}, !(ConfigurationService.Instance.Configuration.Posing.FreezeActorOnPoseImport || freezeOnLoad));
}
else
Expand Down Expand Up @@ -174,15 +173,15 @@ internal void ImportPose_internal(OneOf<PoseFile, CMToolPoseFile> rawPoseFile, P
options = _posingService.ExpressionOptions;
tempPose = GeneratePoseFile();
}
else if (asBody)
else if(asBody)
{
options = _posingService.BodyOptions;
}
else if (asScene)
else if(asScene)
{
options = _posingService.SceneImporterOptions;
}
else if (asIPCpose)
else if(asIPCpose)
{
options = _posingService.DefaultIPCImporterOptions;
}
Expand Down Expand Up @@ -267,7 +266,8 @@ public void Undo()

public void Reset(bool generateSnapshot = true, bool reset = true, bool clearHistStack = true)
{
SkeletonPosing.ResetPose();
if(Actor.IsProp == false)
SkeletonPosing.ResetPose();
ModelPosing.ResetTransform();

if(clearHistStack)
Expand Down
15 changes: 11 additions & 4 deletions Brio/Entities/Actor/ActorEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Brio.Capabilities.Posing;
using Brio.Config;
using Brio.Entities.Core;
using Brio.Game.Actor;
using Brio.Game.Actor.Extensions;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Interface;
Expand Down Expand Up @@ -33,10 +34,12 @@ public override string FriendlyName
name = value;
}
}
public override FontAwesomeIcon Icon => GameObject.GetFriendlyIcon();
public override FontAwesomeIcon Icon => IsProp ? FontAwesomeIcon.Cube : GameObject.GetFriendlyIcon();

public unsafe override bool IsVisible => true;

public bool IsProp => SpawnFlag.HasFlag(SpawnFlags.AsProp);

public override void OnAttached()
{
AddCapability(ActivatorUtilities.CreateInstance<ActorLifetimeCapability>(_serviceProvider, this));
Expand All @@ -45,10 +48,14 @@ public override void OnAttached()
AddCapability(ActivatorUtilities.CreateInstance<SkeletonPosingCapability>(_serviceProvider, this));
AddCapability(ActivatorUtilities.CreateInstance<ModelPosingCapability>(_serviceProvider, this));
AddCapability(ActivatorUtilities.CreateInstance<PosingCapability>(_serviceProvider, this));

AddCapability(ActionTimelineCapability.CreateIfEligible(_serviceProvider, this));
AddCapability(CompanionCapability.CreateIfEligible(_serviceProvider, this));
AddCapability(StatusEffectCapability.CreateIfEligible(_serviceProvider, this));

if(IsProp == false)
{
AddCapability(CompanionCapability.CreateIfEligible(_serviceProvider, this));
AddCapability(StatusEffectCapability.CreateIfEligible(_serviceProvider, this));
}

AddCapability(ActivatorUtilities.CreateInstance<ActorDebugCapability>(_serviceProvider, this));
}
Expand Down
13 changes: 13 additions & 0 deletions Brio/Entities/Core/Entity.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Brio.Capabilities.Core;
using Brio.Game.Actor;
using Dalamud.Interface;
using System;
using System.Collections.Generic;
Expand All @@ -13,6 +14,8 @@ internal abstract class Entity : IDisposable

public Entity? Parent { get; protected set; }

public SpawnFlags SpawnFlag { get; protected set; }

public IReadOnlyCollection<Entity> Children => _children.AsReadOnly();

public IReadOnlyList<Capability> Capabilities => _capabilities.Values.ToList().AsReadOnly();
Expand Down Expand Up @@ -188,6 +191,16 @@ public bool TryGetCapabilities<T>([MaybeNullWhen(false)] out IEnumerable<T> capa
return results.Count != 0;
}

public bool SetSpawnFlags(SpawnFlags flags)
{
if(SpawnFlag is SpawnFlags.None)
{
SpawnFlag = flags;
return true;
}
return false;
}

public virtual void Dispose()
{
ClearCapabilities();
Expand Down
6 changes: 5 additions & 1 deletion Brio/Entities/EntityActorManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Brio.Entities.Actor;
using Brio.Entities.Core;
using Brio.Game.Actor;
using Brio.Game.Actor.Extensions;
using Brio.Game.Core;
using Dalamud.Game.ClientState.Objects.Types;
Expand All @@ -19,14 +20,16 @@ internal unsafe class EntityActorManager : IDisposable
private readonly IFramework _framework;

private readonly ActorContainerEntity _actorContainerEntity;
private readonly ActorSpawnService _actorSpawnService;

public EntityActorManager(EntityManager entityManager, IServiceProvider serviceProvider, ObjectMonitorService monitorService, IObjectTable objects, IFramework framework)
public EntityActorManager(EntityManager entityManager, ActorSpawnService actorSpawnService, IServiceProvider serviceProvider, ObjectMonitorService monitorService, IObjectTable objects, IFramework framework)
{
_entityManager = entityManager;
_serviceProvider = serviceProvider;
_monitorService = monitorService;
_objects = objects;
_framework = framework;
_actorSpawnService = actorSpawnService;

_monitorService.CharacterInitialized += OnCharacterInitialized;
_monitorService.CharacterDestroyed += OnCharacterDestroyed;
Expand Down Expand Up @@ -69,6 +72,7 @@ private void AttachActor(IGameObject go, Entity parent)

entity = ActivatorUtilities.CreateInstance<ActorEntity>(_serviceProvider, go);
}
entity.SetSpawnFlags(_actorSpawnService.GetSpawnFlagsByIndex((ushort)(go.ObjectIndex - 200)));

_entityManager.AttachEntity(entity, parent, true);

Expand Down
9 changes: 3 additions & 6 deletions Brio/Game/Actor/ActorAppearanceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,16 @@ public async Task<RedrawResult> SetCharacterAppearance(ICharacter character, Act

native->DrawData.Weapon(DrawDataContainer.WeaponSlot.MainHand).ModelId = appearance.Weapons.MainHand;
native->DrawData.Weapon(DrawDataContainer.WeaponSlot.OffHand).ModelId = appearance.Weapons.OffHand;
}


if(options.HasFlag(AppearanceImportOptions.Weapon))
{

// Weapon Visibility
if(existingAppearance.Runtime.IsMainHandHidden != appearance.Runtime.IsMainHandHidden)
character.GetWeaponDrawObjectData(ActorEquipSlot.MainHand)->IsHidden = appearance.Runtime.IsMainHandHidden;


if(existingAppearance.Runtime.IsOffHandHidden != appearance.Runtime.IsOffHandHidden)
character.GetWeaponDrawObjectData(ActorEquipSlot.OffHand)->IsHidden = appearance.Runtime.IsOffHandHidden;

if(existingAppearance.Runtime.IsPropHandHidden != appearance.Runtime.IsPropHandHidden)
character.GetWeaponDrawObjectData(ActorEquipSlot.Prop)->IsHidden = appearance.Runtime.IsPropHandHidden;
}
}

Expand Down
23 changes: 18 additions & 5 deletions Brio/Game/Actor/ActorSpawnService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using CharacterCopyFlags = FFXIVClientStructs.FFXIV.Client.Game.Character.CharacterSetupContainer.CopyFlags;
using ClientObjectManager = FFXIVClientStructs.FFXIV.Client.Game.Object.ClientObjectManager;
using NativeCharacter = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
Expand All @@ -27,7 +26,7 @@ internal class ActorSpawnService : IDisposable
private readonly GlamourerService _glamourerService;
private readonly TargetService _targetService;

private readonly List<ushort> _createdIndexes = [];
private readonly Dictionary<ushort, SpawnFlags> _createdIndexes = [];

public unsafe ActorSpawnService(ObjectMonitorService monitorService, GlamourerService glamourerService, IObjectTable objectTable, IClientState clientState, IFramework framework, GPoseService gPoseService, ActorRedrawService actorRedrawService, TargetService targetService)
{
Expand Down Expand Up @@ -153,7 +152,7 @@ public unsafe bool DestroyObject(IGameObject go)
if(go is null)
return false;

Brio.Log.Debug($"Destroying gameobjectobject {go.ObjectIndex}...");
Brio.Log.Debug($"Destroying gameobject: {go.ObjectIndex}...");

var com = ClientObjectManager.Instance();
var native = go.Native();
Expand All @@ -171,7 +170,7 @@ public unsafe void DestroyAllCreated()
{
Brio.Log.Debug("Destroying all created gameobjects.");

var indexes = _createdIndexes.ToList();
var indexes = _createdIndexes.Keys;
var com = ClientObjectManager.Instance();
foreach(var idx in indexes)
{
Expand Down Expand Up @@ -240,7 +239,7 @@ private bool CreateEmptyCharacter([MaybeNullWhen(false)] out ICharacter outChara
}
ushort newId = (ushort)idCheck;

_createdIndexes.Add(newId);
_createdIndexes.Add(newId, flags);

var newObject = com->GetObjectByIndex(newId);
if(newObject == null) return false;
Expand All @@ -264,6 +263,17 @@ private bool CreateEmptyCharacter([MaybeNullWhen(false)] out ICharacter outChara
return true;
}

public unsafe SpawnFlags GetSpawnFlagsByIndex(ushort objectIndex)
{
if(_createdIndexes.TryGetValue(objectIndex, out var spawnFlags))
{
Brio.Log.Warning($"GetSpawnFlagsByIndex {objectIndex} {spawnFlags}");
return spawnFlags;
}

return SpawnFlags.None;
}

private void OnGPoseStateChanged(bool newState)
{
if(!newState)
Expand Down Expand Up @@ -303,6 +313,9 @@ enum SpawnFlags
None = 0,
ReserveCompanionSlot = 1 << 0,
CopyPosition = 1 << 1,
AsProp = 1 << 2,
SetDefaultAppearance = 1 << 3,

Prop = AsProp | SetDefaultAppearance,
Default = CopyPosition,
}
1 change: 1 addition & 0 deletions Brio/Game/Actor/Appearance/ActorAppearance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public unsafe static ActorAppearance FromCharacter(DalamudCharacter character)

actorAppearance.Runtime.IsMainHandHidden = character.GetWeaponDrawObjectData(ActorEquipSlot.MainHand)->IsHidden;
actorAppearance.Runtime.IsOffHandHidden = character.GetWeaponDrawObjectData(ActorEquipSlot.OffHand)->IsHidden;
actorAppearance.Runtime.IsPropHandHidden = character.GetWeaponDrawObjectData(ActorEquipSlot.Prop)->IsHidden;

actorAppearance.ExtendedAppearance.Transparency = native->Alpha;

Expand Down
2 changes: 1 addition & 1 deletion Brio/Game/Actor/Appearance/ActorRuntimeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ internal struct ActorRuntimeOptions()

public bool IsMainHandHidden = false;
public bool IsOffHandHidden = false;

public bool IsPropHandHidden = false;
}
1 change: 1 addition & 0 deletions Brio/Game/Posing/ModelTransformService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public unsafe Transform GetTransform(IGameObject go)
public unsafe void SetTransform(StructsGameObject* native, Transform transform)
{
var drawObject = native->DrawObject;

if(drawObject != null)
{
*(Transform*)(&drawObject->Object.Position) = transform;
Expand Down
7 changes: 3 additions & 4 deletions Brio/Game/Posing/SkeletonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.Havok.Animation.Rig;
using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform;
using FFXIVClientStructs.Havok.Common.Base.Math.Quaternion;
using FFXIVClientStructs.Havok.Common.Base.Math.Vector;
using System;
Expand Down Expand Up @@ -269,12 +270,10 @@ private void ApplySnapshot(hkaPose* pose, Bone bone, BonePoseTransformInfo info)

var boneId = bone.Index;

var trans = info.Transform;
trans.Filter(info.PropagateComponents);
var prop = info.PropagateComponents.HasFlag(TransformComponents.Position);
var modelSpace = pose->AccessBoneModelSpace(boneId, prop ? PropagateOrNot.Propagate : PropagateOrNot.DontPropagate);

// Position
bool prop = info.PropagateComponents.HasFlag(TransformComponents.Position);
var modelSpace = pose->AccessBoneModelSpace(boneId, prop ? PropagateOrNot.Propagate : PropagateOrNot.DontPropagate);
temp = modelSpace;
temp.Position += info.Transform.Position;
if(info.IKInfo.Enabled)
Expand Down
Loading

0 comments on commit 3df5b0b

Please sign in to comment.