diff --git a/Assets/BrioIcon.afdesign b/Assets/BrioIcon.afdesign new file mode 100644 index 00000000..a57586b1 Binary files /dev/null and b/Assets/BrioIcon.afdesign differ diff --git a/Assets/image-brio01.png b/Assets/image-brio01.png new file mode 100644 index 00000000..90a8c1c6 Binary files /dev/null and b/Assets/image-brio01.png differ diff --git a/Assets/image-brio02.png.png b/Assets/image-brio02.png.png new file mode 100644 index 00000000..c561f01e Binary files /dev/null and b/Assets/image-brio02.png.png differ diff --git a/Assets/image-brio03.png.png b/Assets/image-brio03.png.png new file mode 100644 index 00000000..78bb8711 Binary files /dev/null and b/Assets/image-brio03.png.png differ diff --git a/Brio/.editorconfig b/Brio/.editorconfig index 9b6ba1e4..c2fdcef7 100644 --- a/Brio/.editorconfig +++ b/Brio/.editorconfig @@ -19,15 +19,15 @@ dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case # Symbol specifications dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.applicable_accessibilities = public, public, private, protected, protected_public, private_protected dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.applicable_accessibilities = public, public, private, protected, protected_public, private_protected dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, public, private, protected, protected_public, private_protected dotnet_naming_symbols.non_field_members.required_modifiers = # Naming styles diff --git a/Brio/Brio.cs b/Brio/Brio.cs index f646f768..3f5e6875 100644 --- a/Brio/Brio.cs +++ b/Brio/Brio.cs @@ -8,6 +8,7 @@ using Brio.Game.Core; using Brio.Game.Cutscene; using Brio.Game.GPose; +using Brio.Game.Input; using Brio.Game.Posing; using Brio.Game.Scene; using Brio.Game.World; @@ -115,12 +116,15 @@ private static ServiceCollection SetupServices(DalamudServices dalamudServices) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // IPC serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // Web serviceCollection.AddSingleton(); @@ -148,8 +152,9 @@ private static ServiceCollection SetupServices(DalamudServices dalamudServices) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); // Library @@ -172,6 +177,7 @@ private static ServiceCollection SetupServices(DalamudServices dalamudServices) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Brio/Brio.csproj b/Brio/Brio.csproj index e74b8293..9b0cef51 100644 --- a/Brio/Brio.csproj +++ b/Brio/Brio.csproj @@ -27,11 +27,12 @@ - - + + + - + $(DalamudLibPath)FFXIVClientStructs.dll false diff --git a/Brio/Brio.json b/Brio/Brio.json index 8be5a4d0..8598841e 100644 --- a/Brio/Brio.json +++ b/Brio/Brio.json @@ -5,6 +5,7 @@ "Description": "Control actors during GPose sessions.", "AssemblyVersion": "0.0.0.1", "InternalName": "Brio", + "publicName": "Brio", "ApplicableVersion": "any", "IconUrl": "https://raw.githubusercontent.com/Etheirys/Brio/main/Resources/Images/BrioIcon.png", "Tags": [ diff --git a/Brio/Capabilities/Actor/ActionTimelineCapability.cs b/Brio/Capabilities/Actor/ActionTimelineCapability.cs index 92f1786a..9f71085b 100644 --- a/Brio/Capabilities/Actor/ActionTimelineCapability.cs +++ b/Brio/Capabilities/Actor/ActionTimelineCapability.cs @@ -16,7 +16,7 @@ namespace Brio.Capabilities.Actor; -internal class ActionTimelineCapability : ActorCharacterCapability +public class ActionTimelineCapability : ActorCharacterCapability { private readonly IFramework _framework; diff --git a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs index c4fd3ae7..cb3d8cde 100644 --- a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs +++ b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs @@ -9,18 +9,22 @@ using Brio.IPC; using Brio.Resources; using Brio.UI.Widgets.Actor; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game.Character; using System; using System.Threading.Tasks; namespace Brio.Capabilities.Actor; -internal class ActorAppearanceCapability : ActorCharacterCapability +public class ActorAppearanceCapability : ActorCharacterCapability { private readonly ActorAppearanceService _actorAppearanceService; private readonly PenumbraService _penumbraService; + private readonly CustomizePlusService _customizePlusService; private readonly GlamourerService _glamourerService; private readonly MareService _mareService; private readonly GPoseService _gposeService; + private readonly IFramework _framework; public string CurrentCollection => _penumbraService.GetCollectionForObject(Character); public PenumbraService PenumbraService => _penumbraService; @@ -28,10 +32,22 @@ internal class ActorAppearanceCapability : ActorCharacterCapability public bool IsCollectionOverridden => _oldCollection != null; private string? _oldCollection = null; + + public string CurrentDesign { get; set; } = "None"; + public GlamourerService GlamourerService => _glamourerService; + + + public (string? name, Guid? id) SelectedDesign { get; set; } = ("None", null); + public (string? data, Guid? id) CurrentProfile => _customizePlusService.GetActiveProfile(Character); + public CustomizePlusService CustomizePlusService => _customizePlusService; + + private ActorAppearance? _originalAppearance = null; public bool IsAppearanceOverridden => _originalAppearance.HasValue; - public bool HasPenumbraIntegration => _penumbraService.IsPenumbraAvailable; + public bool HasPenumbraIntegration => _penumbraService.IsAvailable; + public bool HasGlamourerIntegration => _glamourerService.IsAvailable; + public bool HasCustomizePlusIntegration => _customizePlusService.IsAvailable; public ActorAppearance CurrentAppearance => _actorAppearanceService.GetActorAppearance(Character); @@ -43,17 +59,20 @@ internal class ActorAppearanceCapability : ActorCharacterCapability public bool CanTint => _actorAppearanceService.CanTint; - public bool CanMcdf => _mareService.IsMareAvailable; + public bool CanMcdf => _mareService.IsAvailable; public bool IsHidden => CurrentAppearance.ExtendedAppearance.Transparency == 0; - public ActorAppearanceCapability(ActorEntity parent, ActorAppearanceService actorAppearanceService, PenumbraService penumbraService, GlamourerService glamourerService, MareService mareService, GPoseService gPoseService) : base(parent) + public ActorAppearanceCapability(ActorEntity parent, IFramework framework, ActorAppearanceService actorAppearanceService, CustomizePlusService customizePlusService, PenumbraService penumbraService, GlamourerService glamourerService, MareService mareService, GPoseService gPoseService) : base(parent) { _actorAppearanceService = actorAppearanceService; _penumbraService = penumbraService; _glamourerService = glamourerService; _mareService = mareService; _gposeService = gPoseService; + _customizePlusService = customizePlusService; + _framework = framework; + Widget = new ActorAppearanceWidget(this); _gposeService.OnGPoseStateChange += OnGPoseStateChanged; @@ -80,7 +99,6 @@ public void SetCollection(Guid collection) _ = _actorAppearanceService.Redraw(Character); } - public void ResetCollection() { if(IsCollectionOverridden) @@ -91,6 +109,65 @@ public void ResetCollection() } } + public void SetDesign(Guid design) + { + _ = _glamourerService.ApplyDesign(design, Character); + } + public void ResetDesign(bool isRest = false) + { + _glamourerService.RevertCharacter(Character); + + if(isRest == false && _glamourerService.CheckForLock(Character)) + { + ResetCollection(); + ResetProfile(true); + } + } + + public void SetProfile(string data) + { + _customizePlusService.SetProfile(Character, data); + } + public void ResetProfile(bool isRest = false) + { + _customizePlusService.RemoveTemporaryProfile(Character); + + if(isRest == false && _glamourerService.CheckForLock(Character)) + { + ResetCollection(); + ResetDesign(true); + } + + SetSelectedProfile(); + } + public Guid? GetActiveProfile() + { + return _customizePlusService.GetActiveProfile(Character).Item2; + } + public void SetSelectedProfile() + { + var profiles = _customizePlusService.GetProfiles(); + + var activeProfile = GetActiveProfile(); + if(activeProfile is not null) + { + foreach(var item in profiles) + { + if(item.UniqueId == activeProfile.Value) + { + SelectedDesign = (item.Name, activeProfile.Value); + } + } + } + else + { + SelectedDesign = ("None", null); + } + } + + public async void SetAppearanceAsTask(ActorAppearance appearance, AppearanceImportOptions options) + => await SetAppearance(appearance, options); + public async Task SetAppearance(ActorAppearance appearance, AppearanceImportOptions options) { Brio.Log.Debug($"Setting appearance for gameobject {GameObject.ObjectIndex}..."); @@ -107,6 +184,12 @@ public async Task SetAppearance(ActorAppearance appearance, AppearanceImportOpti _modelShaderOverride.Reset(); } + if(Entity is ActorEntity actor && actor.IsProp == true) + await _framework.RunOnTick(() => + { + AttachWeapon(); + }, delayTicks: 5); + Brio.Log.Debug($"Appearance set for gameobject {GameObject.ObjectIndex}."); } @@ -193,6 +276,13 @@ public async Task Redraw() { await _actorAppearanceService.Redraw(Character); ApplyShaderOverride(); + + if(Entity is ActorEntity actor && actor.IsProp == true) + await _framework.RunOnTick(() => + { + AttachWeapon(); + }, delayTicks: 5); + return; } @@ -212,6 +302,19 @@ public unsafe void AttachWeapon() Character.Native()->Timeline.TimelineSequencer.PlayTimeline(5616); } + public Task SetProp(WeaponModelId modelId) + { + var appearance = _actorAppearanceService.GetActorAppearance(Character); + appearance.Weapons.MainHand = modelId; + return SetAppearance(appearance, AppearanceImportOptions.Weapon); + } + + public WeaponModelId GetProp() + { + var appearance = _actorAppearanceService.GetActorAppearance(Character); + return appearance.Weapons.MainHand; + } + private unsafe void ApplyShaderOverride() { var shaders = Character.GetShaderParams(); diff --git a/Brio/Capabilities/Actor/ActorCapability.cs b/Brio/Capabilities/Actor/ActorCapability.cs index d0155181..68eb94cc 100644 --- a/Brio/Capabilities/Actor/ActorCapability.cs +++ b/Brio/Capabilities/Actor/ActorCapability.cs @@ -4,14 +4,14 @@ namespace Brio.Capabilities.Actor; -internal abstract class ActorCapability(ActorEntity parent) : Capability(parent) +public abstract class ActorCapability(ActorEntity parent) : Capability(parent) { public ActorEntity Actor => (ActorEntity)Entity; public IGameObject GameObject => Actor.GameObject; } -internal abstract class ActorCharacterCapability(ActorEntity parent) : ActorCapability(parent) +public abstract class ActorCharacterCapability(ActorEntity parent) : ActorCapability(parent) { public ICharacter Character => (ICharacter)GameObject; } diff --git a/Brio/Capabilities/Actor/ActorContainerCapability.cs b/Brio/Capabilities/Actor/ActorContainerCapability.cs index b1227876..2df2cf0b 100644 --- a/Brio/Capabilities/Actor/ActorContainerCapability.cs +++ b/Brio/Capabilities/Actor/ActorContainerCapability.cs @@ -11,7 +11,7 @@ namespace Brio.Capabilities.Actor; -internal class ActorContainerCapability : Capability +public class ActorContainerCapability : Capability { private readonly EntityManager _entityManager; private readonly ActorSpawnService _actorSpawnService; @@ -53,6 +53,21 @@ public void SelectActorInHierarchy(ActorEntity entity) throw new Exception("Failed to create character"); } + public (EntityId, ICharacter) CreateProp(bool selectInHierarchy) + { + if(_actorSpawnService.SpawnNewProp(out ICharacter? chara)) + { + EntityId characterId = new EntityId(chara); + if(selectInHierarchy) + { + _entityManager.SetSelectedEntity(chara); + } + return (characterId, chara); + } + + throw new Exception("Failed to create prop"); + } + public void DestroyCharacter(ActorEntity entity) { _actorSpawnService.DestroyObject(entity.GameObject); diff --git a/Brio/Capabilities/Actor/ActorDebugCapability.cs b/Brio/Capabilities/Actor/ActorDebugCapability.cs index fd782320..146a793b 100644 --- a/Brio/Capabilities/Actor/ActorDebugCapability.cs +++ b/Brio/Capabilities/Actor/ActorDebugCapability.cs @@ -6,7 +6,7 @@ namespace Brio.Capabilities.Actor; -internal class ActorDebugCapability : ActorCharacterCapability +public class ActorDebugCapability : ActorCharacterCapability { public bool IsDebug => _configService.IsDebug; diff --git a/Brio/Capabilities/Actor/ActorDynamicPoseCapability.cs b/Brio/Capabilities/Actor/ActorDynamicPoseCapability.cs new file mode 100644 index 00000000..1b8a9457 --- /dev/null +++ b/Brio/Capabilities/Actor/ActorDynamicPoseCapability.cs @@ -0,0 +1,30 @@ +using Brio.Entities.Actor; +using Brio.Game.Actor; +using Brio.Game.GPose; +using Brio.UI.Widgets.Actor; + +namespace Brio.Capabilities.Actor; +public class ActorDynamicPoseCapability : ActorCharacterCapability +{ + private readonly ActorAppearanceService _actorAppearanceService; + private readonly GPoseService _gposeService; + + public ActorDynamicPoseCapability(ActorEntity parent, ActorAppearanceService actorAppearanceService, GPoseService gPoseService) : base(parent) + { + _actorAppearanceService = actorAppearanceService; + _gposeService = gPoseService; + + Widget = new ActorDynamicPoseWidget(this); + } + + public unsafe void TESTactorlook() + { + _actorAppearanceService.TESTactorlook(GameObject); + } + + public unsafe void TESTactorlookClear() + { + _actorAppearanceService.TESTactorlookClear(GameObject); + } + +} diff --git a/Brio/Capabilities/Actor/ActorLifetimeCapability.cs b/Brio/Capabilities/Actor/ActorLifetimeCapability.cs index a7dc9af8..3131b54e 100644 --- a/Brio/Capabilities/Actor/ActorLifetimeCapability.cs +++ b/Brio/Capabilities/Actor/ActorLifetimeCapability.cs @@ -1,34 +1,24 @@ -using Brio.Capabilities.Posing; -using Brio.Core; -using Brio.Entities; +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; namespace Brio.Capabilities.Actor; -internal class ActorLifetimeCapability : ActorCapability +public class ActorLifetimeCapability : ActorCapability { private readonly TargetService _targetService; private readonly ActorSpawnService _actorSpawnService; private readonly EntityManager _entityManager; - private readonly IFramework _framework; - private readonly PosingService _posingService; - public ActorLifetimeCapability(ActorEntity parent, PosingService posingService, TargetService targetService, ActorSpawnService actorSpawnService, EntityManager entityManager, IFramework framework) : base(parent) + public ActorLifetimeCapability(ActorEntity parent, TargetService targetService, ActorSpawnService actorSpawnService, EntityManager entityManager) : base(parent) { _targetService = targetService; _actorSpawnService = actorSpawnService; _entityManager = entityManager; - _framework = framework; - _posingService = posingService; Widget = new ActorLifetimeWidget(this); } @@ -57,33 +47,18 @@ public void SpawnNewActor(bool selectInHierarchy, bool spawnCompanion, bool disa } } - public unsafe void SpawnNewProp(bool selectInHierarchy) + public void SpawnNewProp(bool selectInHierarchy) { - if(_actorSpawnService.CreateCharacter(out ICharacter? chara, SpawnFlags.AsProp | SpawnFlags.CopyPosition, true)) + if(_actorSpawnService.SpawnNewProp(out ICharacter? chara)) { if(selectInHierarchy) { _entityManager.SetSelectedEntity(chara); } - - _framework.RunUntilSatisfied( - () => chara.Native()->IsReadyToDraw(), - (__) => - { - var entity = _entityManager.GetEntity(chara.Native()); - if(entity is not null) - { - entity.GetCapability().SetOverallSpeedOverride(0); - entity.GetCapability().ImportPose(JsonSerializer.Deserialize(ResourceProvider.Instance.GetRawResourceString("Data.BrioPropPose.pose")), _posingService.SceneImporterOptions); - entity.GetCapability().AttachWeapon(); - } - }, - 100, - dontStartFor: 2 - ); } } + public void Clone(bool selectInHierarchy) { if(!CanClone) diff --git a/Brio/Capabilities/Actor/CompanionCapability.cs b/Brio/Capabilities/Actor/CompanionCapability.cs index 02342b6b..2fea6ef7 100644 --- a/Brio/Capabilities/Actor/CompanionCapability.cs +++ b/Brio/Capabilities/Actor/CompanionCapability.cs @@ -10,7 +10,7 @@ namespace Brio.Capabilities.Actor; -internal unsafe class CompanionCapability : ActorCharacterCapability +public unsafe class CompanionCapability : ActorCharacterCapability { public ModeType Mode { get; } diff --git a/Brio/Capabilities/Actor/StatusEffectCapability.cs b/Brio/Capabilities/Actor/StatusEffectCapability.cs index b3cfbdbe..2719b07f 100644 --- a/Brio/Capabilities/Actor/StatusEffectCapability.cs +++ b/Brio/Capabilities/Actor/StatusEffectCapability.cs @@ -10,7 +10,7 @@ namespace Brio.Capabilities.Actor; -internal class StatusEffectCapability : ActorCapability +public class StatusEffectCapability : ActorCapability { public IBattleChara Character { get; } diff --git a/Brio/Capabilities/Camera/BrioCameraCapability.cs b/Brio/Capabilities/Camera/BrioCameraCapability.cs new file mode 100644 index 00000000..dc881e35 --- /dev/null +++ b/Brio/Capabilities/Camera/BrioCameraCapability.cs @@ -0,0 +1,31 @@ +using Brio.Entities.Camera; +using Brio.Game.Camera; +using Brio.Game.GPose; +using Brio.UI.Widgets.Camera; +using Brio.UI.Windows.Specialized; + +namespace Brio.Capabilities.Camera; + +public class BrioCameraCapability : CameraCapability +{ + private readonly CameraWindow _cameraWindow; + private readonly VirtualCameraManager _virtualCameraService; + + public BrioCameraCapability(CameraEntity parent, VirtualCameraManager virtualCameraService, GPoseService gPoseService, CameraWindow cameraWindow) : base(parent, gPoseService) + { + _virtualCameraService = virtualCameraService; + _cameraWindow = cameraWindow; + + Widget = new BrioCameraWidget(this); + } + + public override void OnEntitySelected() + { + _virtualCameraService.SelectCamera(VirtualCamera); + } + + public void ShowCameraWindow() + { + _cameraWindow.IsOpen = true; + } +} diff --git a/Brio/Capabilities/Camera/CameraCapability.cs b/Brio/Capabilities/Camera/CameraCapability.cs index 967a5dc9..b070c84c 100644 --- a/Brio/Capabilities/Camera/CameraCapability.cs +++ b/Brio/Capabilities/Camera/CameraCapability.cs @@ -1,87 +1,33 @@ using Brio.Capabilities.Core; +using Brio.Entities.Camera; using Brio.Entities.Core; using Brio.Game.Camera; using Brio.Game.GPose; -using Brio.UI.Widgets.Camera; -using Brio.UI.Windows.Specialized; -using System.Numerics; +using System; namespace Brio.Capabilities.Camera; -internal class CameraCapability : Capability +public class CameraCapability : Capability, IDisposable { - private readonly CameraService _cameraService; private readonly GPoseService _gPoseService; - private readonly CameraWindow _cameraWindow; - - public unsafe BrioCamera* Camera => _cameraService.GetCurrentCamera(); - - public bool DisableCollision { get; set; } = false; - - public unsafe bool DelimitCamera - { - get => _originalZoomLimits.HasValue; - set - { - var camera = Camera; - if(camera != null) - { - if(value) - { - - _originalZoomLimits = new Vector2(camera->Camera.MinDistance, camera->Camera.MaxDistance); - camera->Camera.MinDistance = 0f; - camera->Camera.MaxDistance = 500f; - } - else - { - if(_originalZoomLimits.HasValue) - { - - camera->Camera.MinDistance = _originalZoomLimits.Value.X; - camera->Camera.MaxDistance = _originalZoomLimits.Value.Y; - - if(camera->Camera.Distance < camera->Camera.MinDistance) - camera->Camera.Distance = camera->Camera.MinDistance; - - _originalZoomLimits = null; - - } - } - } - } - } - - public bool IsOveridden => DisableCollision || DelimitCamera || PositionOffset != Vector3.Zero; - - public Vector3 PositionOffset { get; set; } = Vector3.Zero; - public bool IsAllowed => _gPoseService.IsGPosing; - private Vector2? _originalZoomLimits { get; set; } = null; - - public CameraCapability(Entity parent, CameraService cameraService, GPoseService gPoseService, CameraWindow cameraWindow) : base(parent) + public CameraCapability(Entity parent, GPoseService gPoseService) : base(parent) { - _cameraService = cameraService; _gPoseService = gPoseService; - _cameraWindow = cameraWindow; - - Widget = new CameraWidget(this); - _gPoseService.OnGPoseStateChange += OnGPoseStateChange; } - public unsafe void Reset() - { - DisableCollision = false; - PositionOffset = Vector3.Zero; - DelimitCamera = false; - } + public CameraEntity CameraEntity => (CameraEntity)Entity; + + public VirtualCamera VirtualCamera => CameraEntity.VirtualCamera; private void OnGPoseStateChange(bool newState) { - if(!newState) - Reset(); + if(newState is false) + { + VirtualCamera.ResetCamera(); + } } public override void Dispose() @@ -89,8 +35,4 @@ public override void Dispose() _gPoseService.OnGPoseStateChange -= OnGPoseStateChange; } - public void ShowCameraWindow() - { - _cameraWindow.IsOpen = true; - } } diff --git a/Brio/Capabilities/Camera/CameraContainerCapability.cs b/Brio/Capabilities/Camera/CameraContainerCapability.cs new file mode 100644 index 00000000..744efd19 --- /dev/null +++ b/Brio/Capabilities/Camera/CameraContainerCapability.cs @@ -0,0 +1,25 @@ +using Brio.Capabilities.Core; +using Brio.Entities.Core; +using Brio.Game.Camera; +using Brio.Game.GPose; +using Brio.UI.Widgets.Camera; + +namespace Brio.Capabilities.Camera; + +public class CameraContainerCapability : Capability +{ + private readonly VirtualCameraManager _virtualCameraService; + private readonly GPoseService _gPoseService; + public bool IsAllowed => _gPoseService.IsGPosing; + + public VirtualCameraManager VirtualCameraManager => _virtualCameraService; + public VirtualCamera CurrentCamera => VirtualCameraManager.CurrentCamera!; + + public CameraContainerCapability(Entity parent, GPoseService gPoseService, VirtualCameraManager virtualCameraService) : base(parent) + { + _gPoseService = gPoseService; + _virtualCameraService = virtualCameraService; + + Widget = new CameraContainerWidget(this); + } +} diff --git a/Brio/Capabilities/Camera/CameraLifetimeCapability.cs b/Brio/Capabilities/Camera/CameraLifetimeCapability.cs new file mode 100644 index 00000000..a9dbea5f --- /dev/null +++ b/Brio/Capabilities/Camera/CameraLifetimeCapability.cs @@ -0,0 +1,23 @@ +using Brio.Entities.Camera; +using Brio.Game.Camera; +using Brio.Game.GPose; +using Brio.UI.Widgets.Camera; + +namespace Brio.Capabilities.Camera; + +public class CameraLifetimeCapability : CameraCapability +{ + private readonly VirtualCameraManager _virtualCameraManager; + + public VirtualCameraManager VirtualCameraManager => _virtualCameraManager; + + public CameraLifetimeCapability(CameraEntity parent, GPoseService gPoseService, VirtualCameraManager virtualCameraManager) : base(parent, gPoseService) + { + _virtualCameraManager = virtualCameraManager; + + Widget = new CameraLifetimeWidget(this); + } + + public bool CanDestroy => CameraEntity.CameraID != 0; + public bool CanClone => CameraEntity.CameraID != 0; +} diff --git a/Brio/Capabilities/Core/Capability.cs b/Brio/Capabilities/Core/Capability.cs index fdc0c927..725a2583 100644 --- a/Brio/Capabilities/Core/Capability.cs +++ b/Brio/Capabilities/Core/Capability.cs @@ -4,7 +4,7 @@ namespace Brio.Capabilities.Core; -internal abstract class Capability(Entity parent) : IDisposable +public abstract class Capability(Entity parent) : IDisposable { public Entity Entity { get; } = parent; diff --git a/Brio/Capabilities/Debug/DebugCapability.cs b/Brio/Capabilities/Debug/DebugCapability.cs index cf342cca..0741e04e 100644 --- a/Brio/Capabilities/Debug/DebugCapability.cs +++ b/Brio/Capabilities/Debug/DebugCapability.cs @@ -13,7 +13,7 @@ namespace Brio.Capabilities.Debug; -internal unsafe class DebugCapability : Capability +public unsafe class DebugCapability : Capability { private readonly GPoseService _gPoseService; diff --git a/Brio/Capabilities/Posing/ModelPosingCapability.cs b/Brio/Capabilities/Posing/ModelPosingCapability.cs index 633415ac..ac110d37 100644 --- a/Brio/Capabilities/Posing/ModelPosingCapability.cs +++ b/Brio/Capabilities/Posing/ModelPosingCapability.cs @@ -8,7 +8,7 @@ namespace Brio.Capabilities.Posing; -internal class ModelPosingCapability : ActorCharacterCapability +public class ModelPosingCapability : ActorCharacterCapability { public bool HasOverride => _transformOverride.HasValue; diff --git a/Brio/Capabilities/Posing/PosingCapability.cs b/Brio/Capabilities/Posing/PosingCapability.cs index 2bb87ce8..fcf7709e 100644 --- a/Brio/Capabilities/Posing/PosingCapability.cs +++ b/Brio/Capabilities/Posing/PosingCapability.cs @@ -3,6 +3,7 @@ using Brio.Core; using Brio.Entities.Actor; using Brio.Files; +using Brio.Game.Input; using Brio.Game.Posing; using Brio.Input; using Brio.Resources; @@ -17,7 +18,7 @@ namespace Brio.Capabilities.Posing; -internal class PosingCapability : ActorCharacterCapability +public class PosingCapability : ActorCharacterCapability { public PosingSelectionType Selected { get; set; } = new None(); public PosingSelectionType Hover { get; set; } = new None(); @@ -26,6 +27,8 @@ internal class PosingCapability : ActorCharacterCapability public SkeletonPosingCapability SkeletonPosing => Entity.GetCapability(); public ModelPosingCapability ModelPosing => Entity.GetCapability(); + public PosingService PosingService => _posingService; + public bool HasOverride { get @@ -52,7 +55,12 @@ public bool HasOverride public bool OverlayOpen { get => _overlayWindow.IsOpen; - set => _overlayWindow.IsOpen = value; + set + { + _overlayWindow.IsOpen = value; + if(value == false) + _gameInputService.AllowEscape = true; + } } public bool TransformWindowOpen @@ -67,7 +75,7 @@ public bool TransformWindowOpen private readonly PosingTransformWindow _overlayTransformWindow; private readonly IFramework _framework; private readonly InputService _input; - private readonly PhysicsService _physicsService; + private readonly GameInputService _gameInputService; public PosingCapability( ActorEntity parent, @@ -75,8 +83,8 @@ public PosingCapability( PosingService posingService, ConfigurationService configurationService, PosingTransformWindow overlayTransformWindow, - PhysicsService physicsService, IFramework framework, + GameInputService gameInputService, InputService input) : base(parent) { @@ -87,7 +95,7 @@ public PosingCapability( _overlayTransformWindow = overlayTransformWindow; _framework = framework; _input = input; - _physicsService = physicsService; + _gameInputService = gameInputService; } public override void OnEntitySelected() @@ -110,6 +118,11 @@ public override void OnEntityDeselected() public void ClearSelection() => Selected = PosingSelectionType.None; + public void LoadResourcesPose(string resourcesPath, bool freezeOnLoad = false) + { + ImportPose(JsonSerializer.Deserialize(ResourceProvider.Instance.GetRawResourceString(resourcesPath)), _posingService.SceneImporterOptions, freezeOnLoad: freezeOnLoad); + } + public void ImportPose(string path, PoseImporterOptions? options = null) { try @@ -128,7 +141,8 @@ public void ImportPose(string path, PoseImporterOptions? options = null) } } - public void ImportPose(OneOf rawPoseFile, PoseImporterOptions? options = null, bool asExpression = false, bool asScene = false, bool asIPCpose = false, bool asBody = false, bool freezeOnLoad = false) + public void ImportPose(OneOf rawPoseFile, PoseImporterOptions? options = null, bool asExpression = false, bool asScene = false, bool asIPCpose = false, bool asBody = false, + bool freezeOnLoad = false, bool asProp = false, TransformComponents? transformComponents = null, bool? applyModelTransformOverride = null) { if(Actor.TryGetCapability(out var actionTimeline)) { @@ -136,7 +150,8 @@ public void ImportPose(OneOf rawPoseFile, PoseImporter actionTimeline.StopSpeedAndResetTimeline(() => { - ImportPose_internal(rawPoseFile, options, reset: false, reconcile: false, asExpression: asExpression, asScene: asScene, asIPCpose: asIPCpose, asBody: asBody); + ImportPose_Internal(rawPoseFile, options, reset: false, reconcile: false, asExpression: asExpression, asScene: asScene, + asIPCpose: asIPCpose, asBody: asBody, asProp: asProp, transformComponents: transformComponents); }, !(ConfigurationService.Instance.Configuration.Posing.FreezeActorOnPoseImport || freezeOnLoad)); } @@ -148,8 +163,9 @@ public void ImportPose(OneOf rawPoseFile, PoseImporter // TODO change this boolean hell into flags after Scenes are added PoseFile? tempPose; - internal void ImportPose_internal(OneOf rawPoseFile, PoseImporterOptions? options = null, bool generateSnapshot = true, bool reset = true, bool reconcile = true, - bool asExpression = false, bool expressionPhase2 = false, bool asScene = false, bool asIPCpose = false, bool asBody = false) + internal void ImportPose_Internal(OneOf rawPoseFile, PoseImporterOptions? options = null, bool generateSnapshot = true, bool reset = true, bool reconcile = true, + bool asExpression = false, bool expressionPhase2 = false, bool asScene = false, bool asIPCpose = false, bool asBody = false, bool asProp = false, + TransformComponents? transformComponents = null, bool? applyModelTransformOverride = null) { var poseFile = rawPoseFile.Match( poseFile => poseFile, @@ -191,6 +207,16 @@ internal void ImportPose_internal(OneOf rawPoseFile, P options ??= _posingService.DefaultImporterOptions; } + if(transformComponents.HasValue) + { + options.TransformComponents = transformComponents.Value; + } + + if(applyModelTransformOverride.HasValue) + { + options.ApplyModelTransform = applyModelTransformOverride.Value; + } + if(options.ApplyModelTransform && reset) ModelPosing.ResetTransform(); @@ -227,7 +253,7 @@ public void Snapshot(bool reset = true, bool reconcile = true, bool asExpression if(asExpression == true) { - ImportPose_internal(tempPose!, new PoseImporterOptions(new BoneFilter(_posingService), TransformComponents.All, false), + ImportPose_Internal(tempPose!, new PoseImporterOptions(new BoneFilter(_posingService), TransformComponents.All, false), generateSnapshot: true, expressionPhase2: true); return; @@ -293,7 +319,7 @@ private void Reconcile(bool reset = true, bool generateSnapshot = true) { Reset(generateSnapshot, false); } - ImportPose_internal(poseFile, options: all, generateSnapshot: false); + ImportPose_Internal(poseFile, options: all, generateSnapshot: false); }, delayTicks: 2); } public PoseFile GeneratePoseFile() @@ -304,7 +330,7 @@ public PoseFile GeneratePoseFile() return poseFile; } - internal record struct PoseStack(PoseInfo Info, Transform ModelTransform); + public record struct PoseStack(PoseInfo Info, Transform ModelTransform); } public enum ExpressionPhase diff --git a/Brio/Capabilities/Posing/SkeletonPosingCapability.cs b/Brio/Capabilities/Posing/SkeletonPosingCapability.cs index 0173d243..567fb891 100644 --- a/Brio/Capabilities/Posing/SkeletonPosingCapability.cs +++ b/Brio/Capabilities/Posing/SkeletonPosingCapability.cs @@ -12,7 +12,7 @@ namespace Brio.Capabilities.Posing { - internal class SkeletonPosingCapability : ActorCharacterCapability + public class SkeletonPosingCapability : ActorCharacterCapability { private readonly SkeletonService _skeletonService; private readonly PosingService _posingService; @@ -186,7 +186,5 @@ public override void Dispose() PoseInfo.Clear(); base.Dispose(); } - - } } diff --git a/Brio/Capabilities/World/FestivalCapability.cs b/Brio/Capabilities/World/FestivalCapability.cs index 0801d9ec..29238a42 100644 --- a/Brio/Capabilities/World/FestivalCapability.cs +++ b/Brio/Capabilities/World/FestivalCapability.cs @@ -7,7 +7,7 @@ namespace Brio.Capabilities.World; -internal class FestivalCapability : Capability +public class FestivalCapability : Capability { private readonly FestivalService _festivalService; diff --git a/Brio/Capabilities/World/TimeCapability.cs b/Brio/Capabilities/World/TimeCapability.cs index 70df2b7e..0285b332 100644 --- a/Brio/Capabilities/World/TimeCapability.cs +++ b/Brio/Capabilities/World/TimeCapability.cs @@ -5,7 +5,7 @@ namespace Brio.Capabilities.World; -internal class TimeCapability : Capability +public class TimeCapability : Capability { public TimeService TimeService { get; } diff --git a/Brio/Capabilities/World/WeatherCapability.cs b/Brio/Capabilities/World/WeatherCapability.cs index 5d204e0a..232b40d3 100644 --- a/Brio/Capabilities/World/WeatherCapability.cs +++ b/Brio/Capabilities/World/WeatherCapability.cs @@ -5,7 +5,7 @@ namespace Brio.Capabilities.World; -internal class WeatherCapability : Capability +public class WeatherCapability : Capability { public WeatherService WeatherService { get; } diff --git a/Brio/Capabilities/World/WorldRenderingCapability.cs b/Brio/Capabilities/World/WorldRenderingCapability.cs index 1fd39422..eb33d989 100644 --- a/Brio/Capabilities/World/WorldRenderingCapability.cs +++ b/Brio/Capabilities/World/WorldRenderingCapability.cs @@ -5,7 +5,7 @@ namespace Brio.Capabilities.World; -internal class WorldRenderingCapability : Capability +public class WorldRenderingCapability : Capability { public WorldRenderingService WorldRenderingService { get; } diff --git a/Brio/Config/AppearanceConfiguration.cs b/Brio/Config/AppearanceConfiguration.cs index e8bde4f7..69d055e9 100644 --- a/Brio/Config/AppearanceConfiguration.cs +++ b/Brio/Config/AppearanceConfiguration.cs @@ -1,10 +1,12 @@ namespace Brio.Config; -internal class AppearanceConfiguration +public class AppearanceConfiguration { public ApplyNPCHack ApplyNPCHack { get; set; } = ApplyNPCHack.InGPose; public bool EnableTinting { get; set; } = true; public bool EnableBrioStyle { get; set; } = true; + + public bool EnableBrioColor { get; set; } = true; } diff --git a/Brio/Config/AutoSaveConfiguration.cs b/Brio/Config/AutoSaveConfiguration.cs new file mode 100644 index 00000000..f08fe8b5 --- /dev/null +++ b/Brio/Config/AutoSaveConfiguration.cs @@ -0,0 +1,12 @@ +namespace Brio.Config; + +public class AutoSaveConfiguration +{ + public bool AutoSaveSystemEnabled { get; set; } = true; + + public int AutoSaveInterval { get; set; } = 60; + public int MaxAutoSaves { get; set; } = 8; + + public bool CleanAutoSaveOnLeavingGpose { get; set; } = false; + +} diff --git a/Brio/Config/Configuration.cs b/Brio/Config/Configuration.cs index 3a0da0cf..e43a7cca 100644 --- a/Brio/Config/Configuration.cs +++ b/Brio/Config/Configuration.cs @@ -2,10 +2,10 @@ namespace Brio.Config; -internal class Configuration : IPluginConfiguration +public class Configuration : IPluginConfiguration { public const int CurrentVersion = 3; - public const int CurrentPopupKey = 12; + public const int CurrentPopupKey = 13; public int Version { get; set; } = CurrentVersion; @@ -45,6 +45,9 @@ internal class Configuration : IPluginConfiguration // Input public InputConfiguration Input { get; set; } = new InputConfiguration(); + // AutoSave + public AutoSaveConfiguration AutoSave { get; set; } = new AutoSaveConfiguration(); + // Developer public bool ForceDebug { get; set; } = false; } diff --git a/Brio/Config/ConfigurationService.cs b/Brio/Config/ConfigurationService.cs index 180ea23d..6a59101d 100644 --- a/Brio/Config/ConfigurationService.cs +++ b/Brio/Config/ConfigurationService.cs @@ -3,7 +3,7 @@ namespace Brio.Config; -internal class ConfigurationService : IDisposable +public class ConfigurationService : IDisposable { public Configuration Configuration { get; private set; } = null!; diff --git a/Brio/Config/EnvironmentConfiguration.cs b/Brio/Config/EnvironmentConfiguration.cs index 01dd1a14..7d881c54 100644 --- a/Brio/Config/EnvironmentConfiguration.cs +++ b/Brio/Config/EnvironmentConfiguration.cs @@ -1,5 +1,5 @@ namespace Brio.Config; -internal class EnvironmentConfiguration +public class EnvironmentConfiguration { public bool ResetWeatherOnGPoseExit { get; set; } = true; public bool ResetTimeOnGPoseExit { get; set; } = true; diff --git a/Brio/Config/IPCConfiguration.cs b/Brio/Config/IPCConfiguration.cs index 144b2a8b..3e34f4c8 100644 --- a/Brio/Config/IPCConfiguration.cs +++ b/Brio/Config/IPCConfiguration.cs @@ -1,10 +1,11 @@ namespace Brio.Config; -internal class IPCConfiguration +public class IPCConfiguration { public bool EnableBrioIPC { get; set; } = true; public bool AllowPenumbraIntegration { get; set; } = true; public bool AllowGlamourerIntegration { get; set; } = true; public bool AllowMareIntegration { get; set; } = true; public bool AllowWebAPI { get; set; } = false; + public bool AllowCustomizePlusIntegration { get; set; } = true; } diff --git a/Brio/Config/InputConfiguration.cs b/Brio/Config/InputConfiguration.cs index bafbf4ba..49e53c6e 100644 --- a/Brio/Config/InputConfiguration.cs +++ b/Brio/Config/InputConfiguration.cs @@ -4,7 +4,7 @@ namespace Brio.Config; -internal class InputConfiguration +public class InputConfiguration { public Dictionary Bindings { get; set; } = new() { @@ -17,6 +17,8 @@ internal class InputConfiguration { KeyBindEvents.Posing_Undo, new(VirtualKey.Z, true) }, { KeyBindEvents.Posing_Redo, new(VirtualKey.Y, true) }, + { KeyBindEvents.Poseing_Esc, new(VirtualKey.ESCAPE) }, + { KeyBindEvents.Posing_DisableGizmo, new(VirtualKey.SHIFT) }, { KeyBindEvents.Posing_DisableSkeleton, new(VirtualKey.CONTROL) }, { KeyBindEvents.Posing_HideOverlay, new(VirtualKey.MENU) }, @@ -31,4 +33,7 @@ internal class InputConfiguration public bool ShowPromptsInGPose { get; set; } = false; public bool EnableKeybinds { get; set; } = true; + + public bool EnableKeyHandling { get; set; } = true; + public bool EnableKeyHandlingOnKeyMod { get; set; } = true; } diff --git a/Brio/Config/InterfaceConfiguration.cs b/Brio/Config/InterfaceConfiguration.cs index 5c74f0f9..f0149e33 100644 --- a/Brio/Config/InterfaceConfiguration.cs +++ b/Brio/Config/InterfaceConfiguration.cs @@ -1,6 +1,6 @@ namespace Brio.Config; -internal class InterfaceConfiguration +public class InterfaceConfiguration { public OpenBrioBehavior OpenBrioBehavior { get; set; } = OpenBrioBehavior.OnGPoseEnter; public bool ShowInGPose { get; set; } = true; diff --git a/Brio/Config/LibraryConfiguration.cs b/Brio/Config/LibraryConfiguration.cs index ab530af1..d2ddf62b 100644 --- a/Brio/Config/LibraryConfiguration.cs +++ b/Brio/Config/LibraryConfiguration.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace Brio.Config; -internal class LibraryConfiguration +public class LibraryConfiguration { public float IconSize { get; set; } = 120; diff --git a/Brio/Config/PosingConfiguration.cs b/Brio/Config/PosingConfiguration.cs index 5f78c518..945c8e9d 100644 --- a/Brio/Config/PosingConfiguration.cs +++ b/Brio/Config/PosingConfiguration.cs @@ -1,6 +1,6 @@ namespace Brio.Config; -internal class PosingConfiguration +public class PosingConfiguration { // Overlay public bool OverlayDefaultsOn { get; set; } = false; diff --git a/Brio/Config/SceneImportConfiguration.cs b/Brio/Config/SceneImportConfiguration.cs index 41007321..4dc11eab 100644 --- a/Brio/Config/SceneImportConfiguration.cs +++ b/Brio/Config/SceneImportConfiguration.cs @@ -1,6 +1,6 @@ namespace Brio.Config; -internal class SceneImportConfiguration +public class SceneImportConfiguration { public bool ApplyModelTransform { get; set; } = true; @@ -9,7 +9,7 @@ internal class SceneImportConfiguration public ScenePoseTransformType ScaleTransformType { get; set; } = ScenePoseTransformType.Absolute; } -internal enum ScenePoseTransformType +public enum ScenePoseTransformType { Ignore, Difference, diff --git a/Brio/Core/CollectionExtensions.cs b/Brio/Core/CollectionExtensions.cs index 25d9ab31..57b4a6eb 100644 --- a/Brio/Core/CollectionExtensions.cs +++ b/Brio/Core/CollectionExtensions.cs @@ -3,7 +3,7 @@ namespace Brio.Core; -internal static class CollectionExtensions +public static class CollectionExtensions { public static Stack Trim(this Stack stack, int trimCount) { diff --git a/Brio/Core/DalamudServices.cs b/Brio/Core/DalamudServices.cs index 74434761..83327eef 100644 --- a/Brio/Core/DalamudServices.cs +++ b/Brio/Core/DalamudServices.cs @@ -6,7 +6,7 @@ namespace Brio.Core; -internal class DalamudServices +public class DalamudServices { [PluginService] public IDalamudPluginInterface PluginInterface { get; private set; } = null!; [PluginService] public IFramework Framework { get; private set; } = null!; diff --git a/Brio/Core/EventBus.cs b/Brio/Core/EventBus.cs index 62bf8ef5..33765726 100644 --- a/Brio/Core/EventBus.cs +++ b/Brio/Core/EventBus.cs @@ -2,7 +2,7 @@ namespace Brio.Core; -internal class EventBus +public class EventBus { public static EventBus Instance { get; private set; } = null!; diff --git a/Brio/Core/ImGuizmoExtensions.cs b/Brio/Core/ImGuizmoExtensions.cs index 4306a514..ea051092 100644 --- a/Brio/Core/ImGuizmoExtensions.cs +++ b/Brio/Core/ImGuizmoExtensions.cs @@ -5,7 +5,7 @@ namespace Brio.Core; -internal static class ImGuizmoExtensions +public static class ImGuizmoExtensions { public static bool MouseWheelManipulate(ref Matrix4x4 matrix) { diff --git a/Brio/Core/IntExtensions.cs b/Brio/Core/IntExtensions.cs index 91fc11af..476efb77 100644 --- a/Brio/Core/IntExtensions.cs +++ b/Brio/Core/IntExtensions.cs @@ -2,7 +2,7 @@ namespace Brio.Core; -internal static class IntExtensions +public static class IntExtensions { public static string ToWords(this int number, string separator = " ") { @@ -61,4 +61,9 @@ public static string ToBrioName(this int i) return result; } + + public static string ToName(this int i) + { + return ToWords(i, " "); + } } diff --git a/Brio/Core/JsonSerializer.cs b/Brio/Core/JsonSerializer.cs index 7e7e3ba0..cdb69a22 100644 --- a/Brio/Core/JsonSerializer.cs +++ b/Brio/Core/JsonSerializer.cs @@ -14,7 +14,8 @@ static JsonSerializer() { _serializeOptions = new() { - WriteIndented = true + WriteIndented = true, + AllowTrailingCommas = true }; _serializeOptions.Converters.Add(new JsonStringEnumConverter()); @@ -25,7 +26,8 @@ static JsonSerializer() _legacySerializeOptions = new() { - WriteIndented = true + WriteIndented = true, + AllowTrailingCommas = true }; _legacySerializeOptions.Converters.Add(new JsonStringEnumConverter()); diff --git a/Brio/Core/MathHelpers.cs b/Brio/Core/MathHelpers.cs index a0851f16..58dc9acf 100644 --- a/Brio/Core/MathHelpers.cs +++ b/Brio/Core/MathHelpers.cs @@ -2,7 +2,7 @@ namespace Brio.Core; -internal static class MathHelpers +public static class MathHelpers { public const float DegreesToRadians = MathF.PI / 180.0f; public const float RadiansToDegrees = 180.0f / MathF.PI; diff --git a/Brio/Core/MultiValueDictionary.cs b/Brio/Core/MultiValueDictionary.cs index 26f630aa..e4c2c15c 100644 --- a/Brio/Core/MultiValueDictionary.cs +++ b/Brio/Core/MultiValueDictionary.cs @@ -3,7 +3,7 @@ namespace Brio.Core; -internal class MultiValueDictionary where TKey : notnull +public class MultiValueDictionary where TKey : notnull { private readonly Dictionary> _underlyingDictionary = []; diff --git a/Brio/Core/NativeHelpers.cs b/Brio/Core/NativeHelpers.cs index 771e475c..ee2aed3c 100644 --- a/Brio/Core/NativeHelpers.cs +++ b/Brio/Core/NativeHelpers.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; namespace Brio.Core; -internal static class NativeHelpers +public static class NativeHelpers { public static (nint Aligned, nint Unaligned) AllocateAlignedMemory(int sizeInBytes, int alignment) { diff --git a/Brio/Core/NumericsExtensions.cs b/Brio/Core/NumericsExtensions.cs index 459bd6d4..31427514 100644 --- a/Brio/Core/NumericsExtensions.cs +++ b/Brio/Core/NumericsExtensions.cs @@ -2,7 +2,7 @@ using System.Numerics; namespace Brio.Core; -internal static class NumericsExtensions +public static class NumericsExtensions { public static Quaternion ToQuaternion(this Vector3 euler) { diff --git a/Brio/Core/Transform.cs b/Brio/Core/Transform.cs index 6d618c26..a5d2a51e 100644 --- a/Brio/Core/Transform.cs +++ b/Brio/Core/Transform.cs @@ -1,4 +1,5 @@ using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; +using MessagePack; using System; using System.Numerics; using System.Runtime.InteropServices; @@ -8,7 +9,8 @@ namespace Brio.Core; [StructLayout(LayoutKind.Sequential)] -internal struct Transform +[MessagePackObject(keyAsPropertyName: true)] +public struct Transform { public Vector3 Position; public Quaternion Rotation; @@ -148,7 +150,7 @@ public readonly bool IsRotationNaN() } [Flags] -internal enum TransformComponents +public enum TransformComponents { None = 0, Position = 1, diff --git a/Brio/Core/WelcomeService.cs b/Brio/Core/WelcomeService.cs index 390e6685..5740e22d 100644 --- a/Brio/Core/WelcomeService.cs +++ b/Brio/Core/WelcomeService.cs @@ -5,11 +5,10 @@ namespace Brio.Core; -internal class WelcomeService +public class WelcomeService { public WelcomeService(ConfigurationService configService, MainWindow mainWindow, InfoWindow infoWindow, UpdateWindow updateWindow) { - if(configService.Configuration.PopupKey == -1) // New User { infoWindow.IsOpen = true; diff --git a/Brio/Entities/Actor/ActorContainerEntity.cs b/Brio/Entities/Actor/ActorContainerEntity.cs index e2aa1371..06e4985c 100644 --- a/Brio/Entities/Actor/ActorContainerEntity.cs +++ b/Brio/Entities/Actor/ActorContainerEntity.cs @@ -1,16 +1,27 @@ using Brio.Capabilities.Actor; using Brio.Entities.Core; +using Brio.Game.GPose; +using Brio.UI.Controls.Editors; +using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using Microsoft.Extensions.DependencyInjection; using System; namespace Brio.Entities.Actor; -internal class ActorContainerEntity(IServiceProvider provider) : Entity("actorContainer", provider) +public class ActorContainerEntity(IServiceProvider provider) : Entity("actorContainer", provider) { + private readonly GPoseService _gPoseService = provider.GetRequiredService(); + private readonly EntityManager _entityManager = provider.GetRequiredService(); + public override string FriendlyName => "Actors"; public override FontAwesomeIcon Icon => FontAwesomeIcon.Users; + public override EntityFlags Flags => EntityFlags.HasContextButton; + public override void OnAttached() { AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); @@ -19,6 +30,21 @@ public override void OnAttached() public override void OnChildAttached() => SortChildren(); public override void OnChildDetached() => SortChildren(); + public override void DrawContextButton() + { + using(ImRaii.Disabled(_gPoseService.IsGPosing == false)) + { + using(ImRaii.PushColor(ImGuiCol.Button, TheameManager.CurrentTheame.Accent.AccentColor)) + { + string toolTip = $"New Actor"; + if(ImBrio.FontIconButtonRight($"###{Id}_actors_contextButton", FontAwesomeIcon.Plus, 1f, toolTip, bordered: false)) + { + ImGui.OpenPopup("ActorEditorDrawSpawnMenuPopup"); + } + ActorEditor.DrawSpawnMenu(this); + } + } + } private void SortChildren() { diff --git a/Brio/Entities/Actor/ActorEntity.cs b/Brio/Entities/Actor/ActorEntity.cs index f1f2011c..8f705c90 100644 --- a/Brio/Entities/Actor/ActorEntity.cs +++ b/Brio/Entities/Actor/ActorEntity.cs @@ -4,14 +4,18 @@ using Brio.Entities.Core; using Brio.Game.Actor; using Brio.Game.Actor.Extensions; +using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using Microsoft.Extensions.DependencyInjection; using System; namespace Brio.Entities.Actor { - internal class ActorEntity(IGameObject gameObject, IServiceProvider provider) : Entity(new EntityId(gameObject), provider) + public class ActorEntity(IGameObject gameObject, IServiceProvider provider) : Entity(new EntityId(gameObject), provider) { public readonly IGameObject GameObject = gameObject; @@ -38,12 +42,41 @@ public override string FriendlyName public unsafe override bool IsVisible => true; - public bool IsProp => SpawnFlag.HasFlag(SpawnFlags.AsProp); + public override EntityFlags Flags => EntityFlags.HasContextButton | EntityFlags.DefaultOpen; + + public bool IsProp => ActorType == ActorType.Prop; + + public ActorType ActorType => GetActorType(); + + private ActorType GetActorType() + { + if(SpawnFlag.HasFlag(SpawnFlags.IsEffect)) + return ActorType.Effect; + if(SpawnFlag.HasFlag(SpawnFlags.IsProp)) + return ActorType.Prop; + + return ActorType.BrioActor; + } + + public override void DrawContextButton() + { + var aac = GetCapability(); + + using(ImRaii.PushColor(ImGuiCol.Button, TheameManager.CurrentTheame.Accent.AccentColor, aac.IsHidden)) + { + string toolTip = aac.IsHidden ? $"Show {aac.Actor.FriendlyName}" : $"Hide {aac.Actor.FriendlyName}"; + if(ImBrio.FontIconButtonRight($"###{Id}_hideActor", aac.IsHidden ? FontAwesomeIcon.EyeSlash : FontAwesomeIcon.Eye, 1f, toolTip, bordered: false)) + { + aac.ToggleHide(); + } + } + } public override void OnAttached() { AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); + //AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); @@ -51,9 +84,13 @@ public override void OnAttached() AddCapability(ActionTimelineCapability.CreateIfEligible(_serviceProvider, this)); - if(IsProp == false) + if(ActorType is not ActorType.Prop) { - AddCapability(CompanionCapability.CreateIfEligible(_serviceProvider, this)); + if(ActorType is not ActorType.Effect) + { + AddCapability(CompanionCapability.CreateIfEligible(_serviceProvider, this)); + } + AddCapability(StatusEffectCapability.CreateIfEligible(_serviceProvider, this)); } diff --git a/Brio/Entities/Actor/ActorType.cs b/Brio/Entities/Actor/ActorType.cs new file mode 100644 index 00000000..fc3d6e3e --- /dev/null +++ b/Brio/Entities/Actor/ActorType.cs @@ -0,0 +1,9 @@ +namespace Brio.Entities.Actor; + +public enum ActorType +{ + BrioActor, + Companion, + Prop, + Effect +} diff --git a/Brio/Entities/Camera/CameraContainerEntity.cs b/Brio/Entities/Camera/CameraContainerEntity.cs new file mode 100644 index 00000000..d74a0a0f --- /dev/null +++ b/Brio/Entities/Camera/CameraContainerEntity.cs @@ -0,0 +1,62 @@ +using Brio.Capabilities.Camera; +using Brio.Entities.Core; +using Brio.Game.Camera; +using Brio.Game.GPose; +using Brio.Game.Input; +using Brio.UI.Controls.Editors; +using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; +using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace Brio.Entities.Camera; + +public class CameraContainerEntity(IServiceProvider provider) : Entity("cameras", provider) +{ + private readonly GPoseService _gPoseService = provider.GetRequiredService(); + private readonly VirtualCameraManager _virtualCameraManager = provider.GetRequiredService(); + private readonly GameInputService _gameInputService = provider.GetRequiredService(); + + public override string FriendlyName => "Cameras"; + + public override FontAwesomeIcon Icon => FontAwesomeIcon.Camera; + + public override EntityFlags Flags => EntityFlags.DefaultOpen | EntityFlags.HasContextButton; + + public override void DrawContextButton() + { + using(ImRaii.Disabled(_gPoseService.IsGPosing == false)) + { + using(ImRaii.PushColor(ImGuiCol.Button, TheameManager.CurrentTheame.Accent.AccentColor)) + { + string toolTip = $"New Camera"; + if(ImBrio.FontIconButtonRight($"###{Id}_cameras_contextButton", FontAwesomeIcon.Plus, 1f, toolTip, bordered: false)) + { + ImGui.OpenPopup("DrawSpawnMenuPopup"); + } + CameraEditor.DrawSpawnMenu(_virtualCameraManager); + } + } + } + + public override void OnAttached() + { + AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); + } + + public override void OnSelected() + { + _gameInputService.AllowEscape = true; + base.OnSelected(); + } + + public override void OnChildAttached() => SortChildren(); + public override void OnChildDetached() => SortChildren(); + + private void SortChildren() => + _children.Sort(static (a, b) => string.Compare(a.Id.Unique, b.Id.Unique, StringComparison.Ordinal)); + +} diff --git a/Brio/Entities/Camera/CameraEntity.cs b/Brio/Entities/Camera/CameraEntity.cs index 0c30da4f..5d7f8426 100644 --- a/Brio/Entities/Camera/CameraEntity.cs +++ b/Brio/Entities/Camera/CameraEntity.cs @@ -1,25 +1,124 @@ using Brio.Capabilities.Camera; +using Brio.Core; using Brio.Entities.Core; +using Brio.Game.Camera; +using Brio.Game.GPose; +using Brio.Game.Input; +using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using Microsoft.Extensions.DependencyInjection; using System; namespace Brio.Entities.Camera; -internal class CameraEntity : Entity +public class CameraEntity(IServiceProvider provider, int cameraID, CameraType cameraType) : Entity(new EntityId(new CameraId(cameraID)), provider) { - public override string FriendlyName => "Camera"; + private readonly GPoseService _gPoseService = provider.GetRequiredService(); + private readonly VirtualCameraManager _virtualCameraManager = provider.GetRequiredService(); + private readonly GameInputService _gameInputService = provider.GetRequiredService(); - public override FontAwesomeIcon Icon => FontAwesomeIcon.Camera; + public VirtualCamera VirtualCamera { get; private set; } = new(cameraID); - public CameraEntity(IServiceProvider serviceProvider) : base("camera", serviceProvider) + public readonly int CameraID = cameraID; + + public string RawName = ""; + public override string FriendlyName { + get + { + if(string.IsNullOrEmpty(RawName)) + { + if(CameraID == 0) + { + return $"Default Camera"; + } + + return $"Camera {CameraID.ToName()}"; + } + + return $"{RawName} ({CameraID})"; + } + set + { + RawName = value; + } + } + public unsafe override bool IsVisible => CameraID != 0; + + public VirtualCameraManager VirtualCameraManager => _virtualCameraManager; + + public CameraContainerEntity? CameraContainer => Parent as CameraContainerEntity; + + public override EntityFlags Flags => EntityFlags.HasContextButton | EntityFlags.DefaultOpen; + + public override int ContextButtonCount => VirtualCamera.IsFreeCamera ? 2 : 1; + + public override FontAwesomeIcon Icon => GetIcon(); + + public CameraType CameraType { get; private set; } = cameraType; + + public int SetVirtualCamera(VirtualCamera virtualCamera) + { + virtualCamera.SetCameraID(CameraID); + VirtualCamera = virtualCamera; + return CameraID; } public override void OnAttached() { - AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); + AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); + AddCapability(ActivatorUtilities.CreateInstance(_serviceProvider, this)); + } - base.OnAttached(); + public override void OnSelected() + { + _gameInputService.AllowEscape = true; + base.OnSelected(); + } + + public override void DrawContextButton() + { + using(ImRaii.Disabled(_gPoseService.IsGPosing == false)) + { + if(VirtualCamera is null) + return; + + if(VirtualCamera.IsFreeCamera) + { + var pixelPos = ImGui.GetWindowSize().X - ((ImGui.CalcTextSize("XXX").X + (ImGui.GetStyle().FramePadding.X * 2)) * 2); + + ImGui.SetCursorPosX(pixelPos); + + string toolTip1 = $"Toggle as Camera Movement"; + using(ImRaii.PushColor(ImGuiCol.Button, 0)) + if(ImBrio.ToggelFontIconButton($"###{Id}_camera_movement", FontAwesomeIcon.Walking, new System.Numerics.Vector2(0), VirtualCamera.FreeCamValues.IsMovementEnabled, hoverText: toolTip1)) + { + VirtualCamera.FreeCamValues.IsMovementEnabled = !VirtualCamera.FreeCamValues.IsMovementEnabled; + } + } + + ImGui.SameLine(); + + string toolTip = $"Set as Active Camera"; + + using(ImRaii.PushColor(ImGuiCol.Text, TheameManager.CurrentTheame.Accent.AccentColor, VirtualCamera.IsActiveCamera)) + { + if(ImBrio.FontIconButtonRight($"###{Id}_camera_contextButton", FontAwesomeIcon.LocationCrosshairs, 1f, toolTip, bordered: false)) + { + _virtualCameraManager.SelectCamera(VirtualCamera); + } + } + } } + + public FontAwesomeIcon GetIcon() => CameraType switch + { + CameraType.Brio => FontAwesomeIcon.CameraRetro, + CameraType.Free => FontAwesomeIcon.Video, + CameraType.Cutscene => FontAwesomeIcon.Clapperboard, + _ => FontAwesomeIcon.CameraRetro, + }; } diff --git a/Brio/Entities/Camera/CameraType.cs b/Brio/Entities/Camera/CameraType.cs new file mode 100644 index 00000000..ab73d54b --- /dev/null +++ b/Brio/Entities/Camera/CameraType.cs @@ -0,0 +1,10 @@ + +namespace Brio.Entities.Camera; + +public enum CameraType +{ + Default, + Brio, + Free, + Cutscene +} diff --git a/Brio/Entities/Core/CameraId.cs b/Brio/Entities/Core/CameraId.cs new file mode 100644 index 00000000..6b48371d --- /dev/null +++ b/Brio/Entities/Core/CameraId.cs @@ -0,0 +1,4 @@ + +namespace Brio.Entities.Core; + +public record struct CameraId(int Id); diff --git a/Brio/Entities/Core/Entity.cs b/Brio/Entities/Core/Entity.cs index 6c8d46e1..8b1493f3 100644 --- a/Brio/Entities/Core/Entity.cs +++ b/Brio/Entities/Core/Entity.cs @@ -8,7 +8,7 @@ namespace Brio.Entities.Core; -internal abstract class Entity : IDisposable +public abstract class Entity : IDisposable { public EntityId Id { get; private set; } @@ -44,6 +44,10 @@ public virtual string FriendlyName public virtual bool IsAttached => Parent != null; public virtual EntityFlags Flags => EntityFlags.DefaultOpen; + public virtual int ContextButtonCount => 1; + public virtual bool IsIPCControlled => false; + public virtual bool IsLocked => false; + protected List _children = []; @@ -73,7 +77,8 @@ public void RemoveChild(Entity child) { OnChildDetached(); child.Parent = null; - _children.Remove(child); + if(_children.Contains(child)) + _children.Remove(child); } public virtual void OnAttached() @@ -112,6 +117,11 @@ public virtual void OnDeselected() } } + public virtual void DrawContextButton() + { + + } + public void AddCapability(T? capability) where T : Capability { if(capability == null) @@ -229,8 +239,9 @@ public override int GetHashCode() } [Flags] -internal enum EntityFlags +public enum EntityFlags { None, DefaultOpen = 1 << 0, + HasContextButton = 1 << 1, } diff --git a/Brio/Entities/Core/EntityId.cs b/Brio/Entities/Core/EntityId.cs index 7325b3a7..3c270da8 100644 --- a/Brio/Entities/Core/EntityId.cs +++ b/Brio/Entities/Core/EntityId.cs @@ -5,11 +5,14 @@ namespace Brio.Entities.Core; -internal record struct EntityId(string Unique) +public record struct EntityId(string Unique) { public EntityId(IGameObject go) : this($"actor_{go.Address}") { } + public EntityId(CameraId id) : this($"camera_{id}") + { + } public static implicit operator EntityId(Entity entity) { @@ -21,6 +24,11 @@ public static implicit operator EntityId(string id) return new EntityId(id); } + public static implicit operator EntityId(CameraId id) + { + return new EntityId(id); + } + public unsafe static implicit operator EntityId(NativeCharacter* chara) { return new EntityId($"actor_{(nint)chara}"); diff --git a/Brio/Entities/Debug/DebugEntity.cs b/Brio/Entities/Debug/DebugEntity.cs index 033b845f..5adf5cbf 100644 --- a/Brio/Entities/Debug/DebugEntity.cs +++ b/Brio/Entities/Debug/DebugEntity.cs @@ -6,7 +6,7 @@ namespace Brio.Entities.Debug; -internal class DebugEntity(IServiceProvider provider) : Entity(FixedId, provider) +public class DebugEntity(IServiceProvider provider) : Entity(FixedId, provider) { public const string FixedId = "debug_entity"; diff --git a/Brio/Entities/EntityActorManager.cs b/Brio/Entities/EntityActorManager.cs index f4117ae6..5f8d2d24 100644 --- a/Brio/Entities/EntityActorManager.cs +++ b/Brio/Entities/EntityActorManager.cs @@ -11,7 +11,7 @@ namespace Brio.Entities; -internal unsafe class EntityActorManager : IDisposable +public unsafe class EntityActorManager : IDisposable { private readonly EntityManager _entityManager; private readonly IServiceProvider _serviceProvider; diff --git a/Brio/Entities/EntityManager.cs b/Brio/Entities/EntityManager.cs index 58491bff..6f96d4e8 100644 --- a/Brio/Entities/EntityManager.cs +++ b/Brio/Entities/EntityManager.cs @@ -15,9 +15,9 @@ namespace Brio.Entities; -internal unsafe partial class EntityManager : IDisposable +public unsafe partial class EntityManager(IServiceProvider serviceProvider, ConfigurationService configurationService) : IDisposable { - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _serviceProvider = serviceProvider; public Entity? RootEntity => _worldEntity; @@ -41,13 +41,7 @@ public Entity? SelectedEntity private WorldEntity? _worldEntity; private readonly Dictionary _entityMap = []; - private readonly ConfigurationService _configurationService; - - public EntityManager(IServiceProvider serviceProvider, ConfigurationService configurationService) - { - _serviceProvider = serviceProvider; - _configurationService = configurationService; - } + private readonly ConfigurationService _configurationService = configurationService; public void SetupDefaultEntities() { @@ -57,8 +51,11 @@ public void SetupDefaultEntities() var environmentEntity = ActivatorUtilities.CreateInstance(_serviceProvider); AttachEntity(environmentEntity, _worldEntity); - var cameraEntity = ActivatorUtilities.CreateInstance(_serviceProvider); - AttachEntity(cameraEntity, _worldEntity); + var cameraContainerEntity = ActivatorUtilities.CreateInstance(_serviceProvider); + AttachEntity(cameraContainerEntity, _worldEntity); + + var defaultCameraEntity = ActivatorUtilities.CreateInstance(_serviceProvider, 0, CameraType.Default); + AttachEntity(defaultCameraEntity, cameraContainerEntity); RefreshDebugEntity(); } @@ -164,7 +161,8 @@ public IEnumerable TryGetAllActors() { if(entity is ActorEntity actor) { - yield return actor; + if(actor.IsProp == false) + yield return actor; } } } diff --git a/Brio/Entities/World/EnvironmentEntity.cs b/Brio/Entities/World/EnvironmentEntity.cs index b671557b..c4b8c032 100644 --- a/Brio/Entities/World/EnvironmentEntity.cs +++ b/Brio/Entities/World/EnvironmentEntity.cs @@ -6,7 +6,7 @@ namespace Brio.Entities.World; -internal class EnvironmentEntity(IServiceProvider provider) : Entity("environment", provider) +public class EnvironmentEntity(IServiceProvider provider) : Entity("environment", provider) { public override string FriendlyName => "Environment"; public override FontAwesomeIcon Icon => FontAwesomeIcon.MountainSun; diff --git a/Brio/Entities/World/WorldEntity.cs b/Brio/Entities/World/WorldEntity.cs index 7473e3ab..41f06c72 100644 --- a/Brio/Entities/World/WorldEntity.cs +++ b/Brio/Entities/World/WorldEntity.cs @@ -4,7 +4,7 @@ namespace Brio.Entities.World; -internal class WorldEntity : Entity +public class WorldEntity : Entity { public override string FriendlyName => "World"; public override FontAwesomeIcon Icon => FontAwesomeIcon.Globe; diff --git a/Brio/Files/ActorFile.cs b/Brio/Files/ActorFile.cs index a3b9f05e..33626f99 100644 --- a/Brio/Files/ActorFile.cs +++ b/Brio/Files/ActorFile.cs @@ -1,14 +1,17 @@ using Brio.Capabilities.Actor; using Brio.Capabilities.Posing; +using Brio.Core; using Brio.Entities.Actor; using Brio.Game.Actor.Extensions; using Brio.Game.Types; +using MessagePack; using System; namespace Brio.Files; [Serializable] -internal class ActorFile +[MessagePackObject(keyAsPropertyName: true)] +public class ActorFile { public string Name { get; set; } = ""; @@ -17,6 +20,7 @@ internal class ActorFile public bool HasChild { get; set; } public ChildActor? Child { get; set; } + public PropData? PropData { get; set; } public bool HeadSlotShown { get; set; } public bool MainHandSlotShown { get; set; } @@ -26,16 +30,26 @@ internal class ActorFile public bool HasBaseAnimation { get; set; } public int BaseAnimation { get; set; } + public bool IsProp { get; set; } + public static implicit operator ActorFile(ActorEntity actorEntity) { var appearanceCapability = actorEntity.GetCapability(); var posingCapability = actorEntity.GetCapability(); + var modelCapability = actorEntity.GetCapability(); var actorFile = new ActorFile { Name = actorEntity.RawName, AnamnesisCharaFile = appearanceCapability.CurrentAppearance, - PoseFile = posingCapability.GeneratePoseFile() + PoseFile = posingCapability.GeneratePoseFile(), + IsProp = actorEntity.IsProp, + PropData = new PropData + { + //PropID = appearanceCapability.GetProp(), + PropTransformAbsolute = modelCapability.Transform, + PropTransformDifference = modelCapability.Transform.CalculateDiff(modelCapability.OriginalTransform) + } }; CompanionContainer? companionContainer; @@ -49,7 +63,6 @@ public static implicit operator ActorFile(ActorEntity actorEntity) actorFile.HasChild = true; actorFile.Child = new ChildActor() { Companion = companionContainer.Value }; - var companionEntity = companionCapability.GetCompanionAsEntity(); if(companionEntity is not null && companionEntity.TryGetCapability(out var companionPosingCapability)) @@ -63,9 +76,19 @@ public static implicit operator ActorFile(ActorEntity actorEntity) } [Serializable] -internal class ChildActor +[MessagePackObject(keyAsPropertyName: true)] +public class ChildActor { public required CompanionContainer Companion { get; set; } public PoseFile? PoseFile { get; set; } } + +[Serializable] +[MessagePackObject(keyAsPropertyName: true)] +public class PropData +{ + //public FFXIVClientStructs.FFXIV.Client.Game.Character.WeaponModelId PropID { get; set; } + public Transform PropTransformDifference { get; set; } + public Transform PropTransformAbsolute { get; set; } +} diff --git a/Brio/Files/AnamnesisCharaFile.cs b/Brio/Files/AnamnesisCharaFile.cs index fea8b762..650f3f1d 100644 --- a/Brio/Files/AnamnesisCharaFile.cs +++ b/Brio/Files/AnamnesisCharaFile.cs @@ -6,12 +6,13 @@ using Brio.Resources; using Dalamud.Interface.Textures.TextureWraps; using FFXIVClientStructs.FFXIV.Client.Game.Character; +using MessagePack; using System; using System.Numerics; namespace Brio.Files; -internal class AnamnesisCharaFileInfo(EntityManager entityManager) : AppliableActorFileInfoBase(entityManager) +public class AnamnesisCharaFileInfo(EntityManager entityManager) : AppliableActorFileInfoBase(entityManager) { public override string Name => "Character File"; public override IDalamudTextureWrap Icon => ResourceProvider.Instance.GetResourceImage("Images.FileIcon_Chara.png"); @@ -27,7 +28,8 @@ protected override void Apply(AnamnesisCharaFile file, ActorEntity actor, bool a } [Serializable] -internal class AnamnesisCharaFile : JsonDocumentBase +[MessagePackObject(keyAsPropertyName: true)] +public class AnamnesisCharaFile : JsonDocumentBase { public uint ModelType { get; set; } = 0; public Races Race { get; set; } @@ -224,7 +226,8 @@ public static implicit operator AnamnesisCharaFile(ActorAppearance appearance) return charaFile; } - internal struct ItemSave + [MessagePackObject(keyAsPropertyName: true)] + public struct ItemSave { public ushort ModelBase { get; set; } public byte ModelVariant { get; set; } @@ -249,7 +252,8 @@ internal struct ItemSave }; } - internal struct GlassesSave + [MessagePackObject(keyAsPropertyName: true)] + public struct GlassesSave { public ushort GlassesId { get; set; } @@ -261,7 +265,8 @@ internal struct GlassesSave }; } - internal struct WeaponSave + [MessagePackObject(keyAsPropertyName: true)] + public struct WeaponSave { public Vector3 Color { get; set; } public Vector3 Scale { get; set; } diff --git a/Brio/Files/AppliableActorFileInfoBase.cs b/Brio/Files/AppliableActorFileInfoBase.cs index 9c8a12e1..5397839a 100644 --- a/Brio/Files/AppliableActorFileInfoBase.cs +++ b/Brio/Files/AppliableActorFileInfoBase.cs @@ -5,7 +5,7 @@ namespace Brio.Files; -internal abstract class AppliableActorFileInfoBase : JsonDocumentBaseFileInfo +public abstract class AppliableActorFileInfoBase : JsonDocumentBaseFileInfo where T : class { private EntityManager _entityManager; diff --git a/Brio/Files/CMToolPoseFile.cs b/Brio/Files/CMToolPoseFile.cs index a8a07b01..083c0edc 100644 --- a/Brio/Files/CMToolPoseFile.cs +++ b/Brio/Files/CMToolPoseFile.cs @@ -48,7 +48,7 @@ namespace Brio.Files; -internal class CMToolPoseFileInfo : AppliableActorFileInfoBase +public class CMToolPoseFileInfo : AppliableActorFileInfoBase { private PosingService _posingService; @@ -93,7 +93,7 @@ protected override void Apply(CMToolPoseFile file, ActorEntity actor, bool asExp } [Serializable] -internal class CMToolPoseFile +public class CMToolPoseFile { public string? Race { get; set; } diff --git a/Brio/Files/Converters/LegacyGlassesSaveConverter.cs b/Brio/Files/Converters/LegacyGlassesSaveConverter.cs index 35fc16e0..de171386 100644 --- a/Brio/Files/Converters/LegacyGlassesSaveConverter.cs +++ b/Brio/Files/Converters/LegacyGlassesSaveConverter.cs @@ -5,7 +5,7 @@ namespace Brio.Files.Converters; -internal class LegacyGlassesSaveConverter : JsonConverter +public class LegacyGlassesSaveConverter : JsonConverter { public override GlassesSave Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/Brio/Files/Converters/QuaternionConverter.cs b/Brio/Files/Converters/QuaternionConverter.cs index 77fbccb8..e472a903 100644 --- a/Brio/Files/Converters/QuaternionConverter.cs +++ b/Brio/Files/Converters/QuaternionConverter.cs @@ -6,7 +6,7 @@ namespace Brio.Files.Converters; -internal class QuaternionConverter : JsonConverter +public class QuaternionConverter : JsonConverter { public override Quaternion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/Brio/Files/Converters/VectorConverters.cs b/Brio/Files/Converters/VectorConverters.cs index 2178cfcc..e4ead5bd 100644 --- a/Brio/Files/Converters/VectorConverters.cs +++ b/Brio/Files/Converters/VectorConverters.cs @@ -6,7 +6,7 @@ namespace Brio.Files.Converters; -internal class Vector2Converter : JsonConverter +public class Vector2Converter : JsonConverter { public override Vector2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -29,7 +29,7 @@ public override void Write(Utf8JsonWriter writer, Vector2 value, JsonSerializerO } } -internal class Vector3Converter : JsonConverter +public class Vector3Converter : JsonConverter { public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -53,7 +53,7 @@ public override void Write(Utf8JsonWriter writer, Vector3 value, JsonSerializerO } } -internal class Vector4Converter : JsonConverter +public class Vector4Converter : JsonConverter { public override Vector4 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/Brio/Files/EnvironmentFile.cs b/Brio/Files/EnvironmentFile.cs deleted file mode 100644 index 08dd08c2..00000000 --- a/Brio/Files/EnvironmentFile.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Brio.Files; - -[Serializable] -internal class EnvironmentFile -{ - -} diff --git a/Brio/Files/FileService.cs b/Brio/Files/FileService.cs index c46c1c8c..6e9e0c69 100644 --- a/Brio/Files/FileService.cs +++ b/Brio/Files/FileService.cs @@ -3,7 +3,7 @@ namespace Brio.Files; -internal class FileService +public class FileService { private readonly IEnumerable _fileInfos; private readonly Dictionary _typeInfoMap = new(); @@ -24,14 +24,14 @@ public FileService(IEnumerable fileInfos) } } - internal FileTypeInfoBase? GetFileTypeInfo(Type fileType) + public FileTypeInfoBase? GetFileTypeInfo(Type fileType) { FileTypeInfoBase? result = null; _typeInfoMap.TryGetValue(fileType, out result); return result; } - internal FileTypeInfoBase? GetFileTypeInfo(string path) + public FileTypeInfoBase? GetFileTypeInfo(string path) { foreach(FileTypeInfoBase fileType in _fileInfos) { @@ -47,7 +47,7 @@ public FileService(IEnumerable fileInfos) /// /// Attempt to load the file at the given path with any file type info that supports it. /// - internal object? Load(string path) + public object? Load(string path) { Exception? lastException = null; diff --git a/Brio/Files/FileTypeInfoBase.cs b/Brio/Files/FileTypeInfoBase.cs index 0d1078ae..76e35df9 100644 --- a/Brio/Files/FileTypeInfoBase.cs +++ b/Brio/Files/FileTypeInfoBase.cs @@ -5,7 +5,7 @@ namespace Brio.Files; -internal abstract class FileTypeInfoBase +public abstract class FileTypeInfoBase { public abstract string Name { get; } public abstract IDalamudTextureWrap Icon { get; } @@ -40,7 +40,7 @@ public virtual bool InvokeDefaultAction(FileEntry fileEntry, object? args) } } -internal abstract class FileTypeInfoBase : FileTypeInfoBase +public abstract class FileTypeInfoBase : FileTypeInfoBase { public override Type Type => typeof(T); } diff --git a/Brio/Files/GameCameraFile.cs b/Brio/Files/GameCameraFile.cs index b02f88b7..c5b1b7a9 100644 --- a/Brio/Files/GameCameraFile.cs +++ b/Brio/Files/GameCameraFile.cs @@ -1,10 +1,17 @@ -using System; +using Brio.Entities.Camera; +using Brio.Game.Camera; +using MessagePack; +using System; namespace Brio.Files; [Serializable] -internal class GameCameraFile +[MessagePackObject(keyAsPropertyName: true)] +public class GameCameraFile { + [Key(0)] public CameraType CameraType { get; set; } -} + [Key(1)] public VirtualCamera? Camera { get; set; } + [Key(2)] public XATCameraFile? XATCamera { get; set; } +} diff --git a/Brio/Files/JsonDocumentBase.cs b/Brio/Files/JsonDocumentBase.cs index 22c0c268..47655763 100644 --- a/Brio/Files/JsonDocumentBase.cs +++ b/Brio/Files/JsonDocumentBase.cs @@ -1,23 +1,28 @@ using Brio.Library.Sources; using Brio.Library.Tags; using Brio.Resources; +using MessagePack; using System; namespace Brio.Files; -internal abstract class JsonDocumentBaseFileInfo : FileTypeInfoBase +public abstract class JsonDocumentBaseFileInfo : FileTypeInfoBase { public override object? Load(string filePath) => ResourceProvider.Instance.GetFileDocument(filePath); } [Serializable] -internal abstract class JsonDocumentBase : IFileMetadata +[MessagePackObject(keyAsPropertyName: true)] +[Union(0, typeof(SceneFile))] +[Union(1, typeof(AnamnesisCharaFile))] +[Union(2, typeof(PoseFile))] +public abstract class JsonDocumentBase : IFileMetadata { - public string? Author { get; set; } - public string? Description { get; set; } - public string? Version { get; set; } - public string? Base64Image { get; set; } - public TagCollection? Tags { get; set; } + [Key(0)] public string? Author { get; set; } + [Key(1)] public string? Description { get; set; } + [Key(2)] public string? Version { get; set; } + [Key(3)] public string? Base64Image { get; set; } + [Key(4)] public TagCollection? Tags { get; set; } public virtual void GetAutoTags(ref TagCollection tags) { diff --git a/Brio/Files/MareCharacterDataFile.cs b/Brio/Files/MareCharacterDataFile.cs index b3f5319a..792d4b9c 100644 --- a/Brio/Files/MareCharacterDataFile.cs +++ b/Brio/Files/MareCharacterDataFile.cs @@ -8,7 +8,7 @@ namespace Brio.Files; -internal class MareCharacterDataFileInfo : AppliableActorFileInfoBase +public class MareCharacterDataFileInfo : AppliableActorFileInfoBase { public MareCharacterDataFileInfo(EntityManager entityManager) : base(entityManager) @@ -33,7 +33,7 @@ protected override void Apply(MareCharacterDataFile file, ActorEntity actor, boo } } -internal class MareCharacterDataFile : IFileMetadata +public class MareCharacterDataFile : IFileMetadata { private string _filePath; diff --git a/Brio/Files/PoseFile.cs b/Brio/Files/PoseFile.cs index 2bf0a6e5..d97f1c52 100644 --- a/Brio/Files/PoseFile.cs +++ b/Brio/Files/PoseFile.cs @@ -12,13 +12,14 @@ using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Utility.Raii; using ImGuiNET; +using MessagePack; using System; using System.Collections.Generic; using System.Numerics; namespace Brio.Files; -internal class PoseFileInfo : AppliableActorFileInfoBase +public class PoseFileInfo : AppliableActorFileInfoBase { private PosingService _posingService; @@ -63,7 +64,8 @@ protected override void Apply(PoseFile file, ActorEntity actor, bool asExpressio } [Serializable] -internal class PoseFile : JsonDocumentBase +[MessagePackObject(keyAsPropertyName: true)] +public class PoseFile : JsonDocumentBase { public string TypeName { get; set; } = "Brio Pose"; @@ -78,6 +80,7 @@ internal class PoseFile : JsonDocumentBase public Quaternion Rotation { get; set; } // legacy & for better support for other pose tools public Vector3 Scale { get; set; } // legacy & for better support for other pose tools + [MessagePackObject(keyAsPropertyName: true)] public class Bone { public Vector3 Position { get; set; } diff --git a/Brio/Files/SceneFile.cs b/Brio/Files/SceneFile.cs index 8be66f8e..35cc8f77 100644 --- a/Brio/Files/SceneFile.cs +++ b/Brio/Files/SceneFile.cs @@ -1,46 +1,55 @@ +using Brio.Game.Types; using Brio.Resources; using Dalamud.Interface.Textures.TextureWraps; +using MessagePack; using System; using System.Collections.Generic; - namespace Brio.Files; -internal class SceneFileInfo : JsonDocumentBaseFileInfo +public class SceneFileInfo : JsonDocumentBaseFileInfo { public override string Name => "Scene File"; public override IDalamudTextureWrap Icon => ResourceProvider.Instance.GetResourceImage("Images.FileIcon_Unknown.png"); public override string Extension => ".brioscn"; -} -internal class ProjectFileInfo : JsonDocumentBaseFileInfo -{ - public override string Name => "Brio Project"; - - public override IDalamudTextureWrap Icon => ResourceProvider.Instance.GetResourceImage("Images.FileIcon_Unknown.png"); - public override string Extension => ".briosln"; - } [Serializable] -internal class SceneFile : JsonDocumentBase +[MessagePackObject] +public class SceneFile : JsonDocumentBase { - public string FileType { get; set; } = "Brio Scene"; + [Key(5)] public string FileType => "Brio Scene"; - public List Actors { get; set; } = []; + [Key(6)] public List Actors { get; set; } = []; - public GameCameraFile? GameCamera { get; set; } + [Key(7)] public List GameCameras { get; set; } = []; - public XATCameraFile? XATCamera { get; set; } + [Key(8)] public SceneMetaData? MetaData { get; set; } - public SceneMetaData? MetaData { get; set; } + [Key(9)] public EnvironmentData? EnvironmentData { get; set; } } [Serializable] -internal class SceneMetaData +[MessagePackObject(keyAsPropertyName: true)] +public class SceneMetaData { public uint Map { get; set; } public ushort Territory { get; set; } public string? World { get; set; } } + +[Serializable] +[MessagePackObject(keyAsPropertyName: true)] +public class EnvironmentData +{ + public bool IsTimeFrozen; + public long EorzeaTime; + + public int MinuteOfDay; + public int DayOfMonth; + + public WeatherId CurrentWeather; + public bool IsWaterFrozen; +} diff --git a/Brio/Files/XATCameraFile.cs b/Brio/Files/XATCameraFile.cs index 653270c5..48ef5aeb 100644 --- a/Brio/Files/XATCameraFile.cs +++ b/Brio/Files/XATCameraFile.cs @@ -1,4 +1,5 @@ -using System; +using MessagePack; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -8,10 +9,12 @@ namespace Brio.Files; [Serializable] +[MessagePackObject(keyAsPropertyName: true)] public record CameraKeyframe(int Frame, Vector3 Position, Quaternion Rotation, float FoV); [Serializable] -public class XATCameraFile +[MessagePackObject(keyAsPropertyName: true)] +public partial class XATCameraFile { public List CameraFrames { get; private set; } diff --git a/Brio/Game/Actor/ActionTimelineService.cs b/Brio/Game/Actor/ActionTimelineService.cs index a8b73784..256d1e9d 100644 --- a/Brio/Game/Actor/ActionTimelineService.cs +++ b/Brio/Game/Actor/ActionTimelineService.cs @@ -9,7 +9,7 @@ namespace Brio.Game.Actor; -internal unsafe class ActionTimelineService : IDisposable +public unsafe class ActionTimelineService : IDisposable { public enum ActionTimelineSlots : int { diff --git a/Brio/Game/Actor/ActorAppearanceService.cs b/Brio/Game/Actor/ActorAppearanceService.cs index b2fa0920..e042a499 100644 --- a/Brio/Game/Actor/ActorAppearanceService.cs +++ b/Brio/Game/Actor/ActorAppearanceService.cs @@ -2,6 +2,7 @@ using Brio.Entities; using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; +using Brio.Game.Camera; using Brio.Game.GPose; using Brio.IPC; using Dalamud.Game; @@ -11,6 +12,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using System; +using System.Collections.Generic; +using System.Numerics; using System.Runtime.InteropServices; using System.Threading.Tasks; using static Brio.Game.Actor.ActorRedrawService; @@ -18,13 +21,15 @@ namespace Brio.Game.Actor; -internal class ActorAppearanceService : IDisposable +public class ActorAppearanceService : IDisposable { private readonly GPoseService _gPoseService; private readonly ConfigurationService _configurationService; private readonly ActorRedrawService _redrawService; private readonly GlamourerService _glamourerService; + private readonly VirtualCameraManager _virtualCameraManager; private readonly EntityManager _entityManager; + private readonly IObjectTable _objectTable; private delegate byte EnforceKindRestrictionsDelegate(nint a1, nint a2); private readonly Hook _enforceKindRestrictionsHook = null!; @@ -36,18 +41,21 @@ internal class ActorAppearanceService : IDisposable private readonly Hook _updateTintHook = null!; private unsafe delegate* unmanaged _setFacewear; + private unsafe delegate* unmanaged _updateLookAt; private uint _forceNpcHackCount = 0; public bool CanTint => _configurationService.Configuration.Appearance.EnableTinting; - public unsafe ActorAppearanceService(GPoseService gPoseService, ConfigurationService configurationService, ActorRedrawService redrawService, GlamourerService glamourerService, EntityManager entityManager, ISigScanner sigScanner, IGameInteropProvider hooks) + public unsafe ActorAppearanceService(GPoseService gPoseService, VirtualCameraManager virtualCameraManager, IObjectTable objectTable, ConfigurationService configurationService, ActorRedrawService redrawService, GlamourerService glamourerService, EntityManager entityManager, ISigScanner sigScanner, IGameInteropProvider hooks) { _gPoseService = gPoseService; _configurationService = configurationService; _redrawService = redrawService; _glamourerService = glamourerService; _entityManager = entityManager; + _objectTable = objectTable; + _virtualCameraManager = virtualCameraManager; var enforceKindRestrictionsAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 41 B0 ?? 48 8B D6 48 8B"); _enforceKindRestrictionsHook = hooks.HookFromAddress(enforceKindRestrictionsAddress, EnforceKindRestrictionsDetour); @@ -57,29 +65,116 @@ public unsafe ActorAppearanceService(GPoseService gPoseService, ConfigurationSer _updateWetnessHook = hooks.HookFromAddress(updateWetnessAddress, UpdateWetnessDetour); _updateWetnessHook.Enable(); - var updateTintHook = Marshal.ReadInt64((nint)(CharacterBase.StaticVirtualTablePointer) + 0xC0); - _updateTintHook = hooks.HookFromAddress((nint)updateTintHook, UpdateTintDetour); + var updateTintHookAddress = Marshal.ReadInt64((nint)(CharacterBase.StaticVirtualTablePointer) + 0xC0); + _updateTintHook = hooks.HookFromAddress((nint)updateTintHookAddress, UpdateTintDetour); _updateTintHook.Enable(); var setFacewearAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 41 FF C7 41 83 FF ?? 72 ?? 48"); _setFacewear = (delegate* unmanaged)setFacewearAddress; + + var updateFaceTrackerAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 8B D7 48 8B CB E8 ?? ?? ?? ?? 41 ?? ?? 8B D7 48 ?? ?? 48 ?? ?? ?? ?? 48 83 ?? ?? 5F"); + _updateLookAt = (delegate* unmanaged)updateFaceTrackerAddress; + + var actorLookAtLoopAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 48 83 C3 08 48 83 EF 01 75 CF 48 ?? ?? ?? ?? 48"); + _actorLookAtLoop = hooks.HookFromAddress(actorLookAtLoopAddress, ActorLookAtLoopDetour); + _actorLookAtLoop.Enable(); + } + + public delegate nint ActorLookAtLoopDelegate(nint a1); + public Hook _actorLookAtLoop = null!; + + Dictionary _lookAtHandles = []; + + public unsafe IntPtr ActorLookAtLoopDetour(nint a1) + { + if(_gPoseService.IsGPosing) + { + var obj = _objectTable.CreateObjectReference((a1 - 0xD00)); + if(obj is not null && obj.IsValid() && obj.IsGPose() && _lookAtHandles.ContainsKey(obj.GameObjectId)) + { + actorLook(obj, _lookAtHandles[obj.GameObjectId]); + } + } + + return _actorLookAtLoop.Original(a1); } - public void PushForceNpcHack() => ++_forceNpcHackCount; - public void PopForceNpcHack() + public unsafe void actorLook(IGameObject targetActor, LookAtDataHolder lookAtDataHolder) { - if(_forceNpcHackCount == 0) - throw new Exception("Invalid _forceNpcHack count (is already 0)"); + LookAtSource lookAt = lookAtDataHolder.Target; + + lookAt.Eyes.LookAtTarget.LookMode = (uint)lookAtDataHolder.LookAtMode; + lookAt.Head.LookAtTarget.LookMode = (uint)lookAtDataHolder.LookAtMode; + lookAt.Body.LookAtTarget.LookMode = (uint)lookAtDataHolder.LookAtMode; - --_forceNpcHackCount; + if(lookAtDataHolder.LookatType == LookAtTargetMode.Camera) + { + var camera = _virtualCameraManager?.CurrentCamera; + + if(camera is null) + return; + + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Eyes)) + lookAt.Eyes.LookAtTarget.Position = camera.RealPosition; + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Body)) + lookAt.Head.LookAtTarget.Position = camera.RealPosition; + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Head)) + lookAt.Body.LookAtTarget.Position = camera.RealPosition; + } + else if(lookAtDataHolder.LookatType == LookAtTargetMode.None) + return; + + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Eyes)) + _updateLookAt(targetActor.Address + 0xD10, &lookAt.Eyes.LookAtTarget, (uint)LookEditType.Eyes, 0); + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Body)) + _updateLookAt(targetActor.Address + 0xD10, &lookAt.Body.LookAtTarget, (uint)LookEditType.Body, 0); + if(lookAtDataHolder.lookAtTargetType.HasFlag(LookAtTargetType.Head)) + _updateLookAt(targetActor.Address + 0xD10, &lookAt.Head.LookAtTarget, (uint)LookEditType.Head, 0); } - public IDisposable ForceNpcHack() + public unsafe void TESTactorlookClear(IGameObject gameobj) { - PushForceNpcHack(); - return new HackDisposer(this); + if(_lookAtHandles.TryGetValue(gameobj.GameObjectId, out var obj)) + { + obj.LookAtMode = LookMode.None; + obj.lookAtTargetType = LookAtTargetType.All; + obj.LookatType = LookAtTargetMode.None; + } + else + { + + } + } + + public unsafe void TESTactorlook(IGameObject gameobj) + { + if(_lookAtHandles.TryGetValue(gameobj.GameObjectId, out var obj)) + { + obj.LookAtMode = LookMode.Position; + obj.lookAtTargetType = LookAtTargetType.All; + obj.LookatType = LookAtTargetMode.Camera; + } + else + { + _lookAtHandles.Add(gameobj.GameObjectId, new LookAtDataHolder + { + Target = new(), + LookAtMode = LookMode.Position, + lookAtTargetType = LookAtTargetType.All, + LookatType = LookAtTargetMode.Camera + }); + } + } + public void RemoveFromLook(IGameObject gameobj) + { + if(_lookAtHandles.ContainsKey(gameobj.GameObjectId)) + { + _lookAtHandles.Remove(gameobj.GameObjectId); + } } + // + public async Task Redraw(ICharacter character) { var appearance = GetActorAppearance(character); @@ -353,13 +448,94 @@ public void Dispose() _enforceKindRestrictionsHook.Dispose(); _updateWetnessHook.Dispose(); _updateTintHook.Dispose(); + _actorLookAtLoop.Dispose(); } +} + +public record class LookAtDataHolder +{ + public LookAtTargetMode LookatType; + + public LookAtTargetType lookAtTargetType; + public LookMode LookAtMode; - private class HackDisposer(ActorAppearanceService service) : IDisposable + public LookAtSource Target; + + public void SetTarget(Vector3 vector, LookAtTargetType targetType) { - public void Dispose() - { - service.PopForceNpcHack(); - } + if(targetType.HasFlag(LookAtTargetType.Eyes)) + Target.Eyes.LookAtTarget.Position = vector; + if(targetType.HasFlag(LookAtTargetType.Body)) + Target.Head.LookAtTarget.Position = vector; + if(targetType.HasFlag(LookAtTargetType.Head)) + Target.Body.LookAtTarget.Position = vector; } } + +public enum LookAtTargetMode +{ + None, + Forward, + Camera, + Position +} + +public class LookAtData +{ + public uint EntityIdSource; + public LookAtSource LookAtSource; + + public LookMode LookMode; + public LookAtTargetType TargetType; + + public uint TargetEntityId; + public Vector3 TargetPosition; +} + +[Flags] +public enum LookAtTargetType +{ + Body = 0, + Head = 1, + Eyes = 2, + + Face = Head | Eyes, + All = Body | Head | Eyes +} + +[StructLayout(LayoutKind.Sequential)] +public struct LookAtSource +{ + public LookAtType Body; + public LookAtType Head; + public LookAtType Eyes; + public LookAtType Unknown; +} + +[StructLayout(LayoutKind.Explicit)] +public struct LookAtType +{ + [FieldOffset(0x30)] public LookAtTarget LookAtTarget; +} + +[StructLayout(LayoutKind.Explicit)] +public struct LookAtTarget +{ + [FieldOffset(0x08)] public uint LookMode; + [FieldOffset(0x10)] public Vector3 Position; +} + +public enum LookEditType +{ + Body = 0, + Head = 1, + Eyes = 2 +} + +public enum LookMode +{ + None = 0, + Frozen = 1, + Pivot = 2, + Position = 3, +} diff --git a/Brio/Game/Actor/ActorRedrawService.cs b/Brio/Game/Actor/ActorRedrawService.cs index 07ea9f32..5bc60833 100644 --- a/Brio/Game/Actor/ActorRedrawService.cs +++ b/Brio/Game/Actor/ActorRedrawService.cs @@ -7,7 +7,7 @@ namespace Brio.Game.Actor; -internal class ActorRedrawService(IFramework framework, IObjectTable objectTable) +public class ActorRedrawService(IFramework framework, IObjectTable objectTable) { public delegate void ActorRedrawEventDelegate(IGameObject go, RedrawStage stage); diff --git a/Brio/Game/Actor/ActorSpawnService.cs b/Brio/Game/Actor/ActorSpawnService.cs index 9929ece9..65cd3f3a 100644 --- a/Brio/Game/Actor/ActorSpawnService.cs +++ b/Brio/Game/Actor/ActorSpawnService.cs @@ -1,9 +1,16 @@ -using Brio.Core; +using Brio.Capabilities.Actor; +using Brio.Capabilities.Posing; +using Brio.Core; +using Brio.Entities; +using Brio.Files; +using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; using Brio.Game.Core; using Brio.Game.GPose; +using Brio.Game.Posing; using Brio.Game.Types; using Brio.IPC; +using Brio.Resources; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using System; @@ -15,7 +22,7 @@ namespace Brio.Game.Actor; -internal class ActorSpawnService : IDisposable +public class ActorSpawnService : IDisposable { private readonly ObjectMonitorService _monitorService; private readonly IObjectTable _objectTable; @@ -25,10 +32,14 @@ internal class ActorSpawnService : IDisposable private readonly ActorRedrawService _actorRedrawService; private readonly GlamourerService _glamourerService; private readonly TargetService _targetService; + private readonly EntityManager _entityManager; + private readonly PosingService _posingService; + private readonly ActorAppearanceService _actorAppearanceService; + private readonly CustomizePlusService _customizePlusService; private readonly Dictionary _createdIndexes = []; - public unsafe ActorSpawnService(ObjectMonitorService monitorService, GlamourerService glamourerService, IObjectTable objectTable, IClientState clientState, IFramework framework, GPoseService gPoseService, ActorRedrawService actorRedrawService, TargetService targetService) + public unsafe ActorSpawnService(ObjectMonitorService monitorService, CustomizePlusService customizePlusService, ActorAppearanceService actorAppearanceService, PosingService posingService, GlamourerService glamourerService, EntityManager entityManager, IObjectTable objectTable, IClientState clientState, IFramework framework, GPoseService gPoseService, ActorRedrawService actorRedrawService, TargetService targetService) { _monitorService = monitorService; _objectTable = objectTable; @@ -38,6 +49,10 @@ public unsafe ActorSpawnService(ObjectMonitorService monitorService, GlamourerSe _actorRedrawService = actorRedrawService; _glamourerService = glamourerService; _targetService = targetService; + _entityManager = entityManager; + _posingService = posingService; + _actorAppearanceService = actorAppearanceService; + _customizePlusService = customizePlusService; _monitorService.CharacterDestroyed += OnCharacterDestroyed; _gPoseService.OnGPoseStateChange += OnGPoseStateChanged; @@ -125,6 +140,52 @@ public unsafe bool CloneCharacter(ICharacter sourceCharacter, [MaybeNullWhen(fal return false; } + public unsafe bool SpawnNewProp(out ICharacter? gamechara) + { + if(CreateCharacter(out ICharacter? chara, SpawnFlags.IsProp | SpawnFlags.CopyPosition, true)) + { + _framework.RunUntilSatisfied( + () => chara.Native()->IsReadyToDraw(), + (__) => + { + var entity = _entityManager.GetEntity(chara.Native()); + if(entity is not null) + { + entity.GetCapability().SetOverallSpeedOverride(0); + + var acf = JsonSerializer.Deserialize(ResourceProvider.Instance.GetRawResourceString("Data.BrioPropChar.chara")); + if(acf.Race == 0 && acf.ModelType == 0) + { + Brio.Log.Fatal("BrioPropChar was Invalid!!"); + } + else + { + entity.GetCapability().SetAppearanceAsTask(acf, AppearanceImportOptions.Default); + } + + _framework.RunOnTick(() => + { + entity.GetCapability().LoadResourcesPose("Data.BrioPropPose.pose"); + + _framework.RunOnTick(() => + { + entity.GetCapability().AttachWeapon(); + }, delayTicks: 5); + }, delayTicks: 5); + } + }, + 100, + dontStartFor: 2 + ); + + gamechara = chara; + return true; + } + + gamechara = null; + return false; + } + public void ClearAll() { for(int i = ActorTableHelpers.GPoseStart; i <= ActorTableHelpers.GPoseEnd; i++) @@ -152,6 +213,13 @@ public unsafe bool DestroyObject(IGameObject go) if(go is null) return false; + _actorAppearanceService.RemoveFromLook(go); + + if(_glamourerService.CheckForLock(go)) + _glamourerService.UnlockAndRevertCharacter(go); + + _customizePlusService.RemoveTemporaryProfile(go); + Brio.Log.Debug($"Destroying gameobject: {go.ObjectIndex}..."); var com = ClientObjectManager.Instance(); @@ -183,14 +251,14 @@ public void DestroyCompanion(ICharacter character) { if(character.CalculateCompanionInfo(out var info)) { - InternalSetCompanion(character, info.Kind, 0); + publicSetCompanion(character, info.Kind, 0); } } public unsafe void CreateCompanion(ICharacter character, CompanionContainer container) { DestroyCompanion(character); - InternalSetCompanion(character, container.Kind, (short)container.Id); + publicSetCompanion(character, container.Kind, (short)container.Id); // We need to wait for the companion to be ready before we can draw it. var companionNative = &character.Native()->CompanionObject->Character.GameObject; @@ -202,7 +270,7 @@ public unsafe void CreateCompanion(ICharacter character, CompanionContainer cont ); } - private unsafe void InternalSetCompanion(ICharacter character, CompanionKind kind, short id) + private unsafe void publicSetCompanion(ICharacter character, CompanionKind kind, short id) { var native = character.Native(); switch(kind) @@ -267,7 +335,7 @@ public unsafe SpawnFlags GetSpawnFlagsByIndex(ushort objectIndex) { if(_createdIndexes.TryGetValue(objectIndex, out var spawnFlags)) { - Brio.Log.Warning($"GetSpawnFlagsByIndex {objectIndex} {spawnFlags}"); + Brio.Log.Verbose($"GetSpawnFlagsByIndex {objectIndex} {spawnFlags}"); return spawnFlags; } @@ -308,14 +376,16 @@ public unsafe void Dispose() } [Flags] -enum SpawnFlags +public enum SpawnFlags { None = 0, ReserveCompanionSlot = 1 << 0, CopyPosition = 1 << 1, - AsProp = 1 << 2, - SetDefaultAppearance = 1 << 3, + IsProp = 1 << 2, + IsEffect = 1 << 3, + SetDefaultAppearance = 1 << 4, - Prop = AsProp | SetDefaultAppearance, + Prop = IsProp | SetDefaultAppearance | CopyPosition, + Effect = IsEffect | SetDefaultAppearance | CopyPosition, Default = CopyPosition, } diff --git a/Brio/Game/Actor/ActorTableHelpers.cs b/Brio/Game/Actor/ActorTableHelpers.cs index 0c9b9d8b..34df0bf3 100644 --- a/Brio/Game/Actor/ActorTableHelpers.cs +++ b/Brio/Game/Actor/ActorTableHelpers.cs @@ -1,6 +1,6 @@ namespace Brio.Game.Actor; -internal class ActorTableHelpers +public class ActorTableHelpers { public const int OverworldStart = 0; public const int OverworldEnd = 199; diff --git a/Brio/Game/Actor/Appearance/ActorAppearance.cs b/Brio/Game/Actor/Appearance/ActorAppearance.cs index 41169632..6c5eaa16 100644 --- a/Brio/Game/Actor/Appearance/ActorAppearance.cs +++ b/Brio/Game/Actor/Appearance/ActorAppearance.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Actor.Appearance; -internal struct ActorAppearance() +public struct ActorAppearance() { public int ModelCharaId; public byte Facewear; diff --git a/Brio/Game/Actor/Appearance/ActorCustomize.cs b/Brio/Game/Actor/Appearance/ActorCustomize.cs index 2ef26bec..969a957b 100644 --- a/Brio/Game/Actor/Appearance/ActorCustomize.cs +++ b/Brio/Game/Actor/Appearance/ActorCustomize.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Actor.Appearance; [StructLayout(LayoutKind.Explicit, Size = Count)] -internal struct ActorCustomize +public struct ActorCustomize { public const int Count = 0x1A; diff --git a/Brio/Game/Actor/Appearance/ActorEquipSlot.cs b/Brio/Game/Actor/Appearance/ActorEquipSlot.cs index 28a1c5b6..58ceb037 100644 --- a/Brio/Game/Actor/Appearance/ActorEquipSlot.cs +++ b/Brio/Game/Actor/Appearance/ActorEquipSlot.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Actor.Appearance; [Flags] -internal enum ActorEquipSlot +public enum ActorEquipSlot { None = 0, MainHand = 1 << 0, diff --git a/Brio/Game/Actor/Appearance/ActorEquipment.cs b/Brio/Game/Actor/Appearance/ActorEquipment.cs index b3094607..d75ec9df 100644 --- a/Brio/Game/Actor/Appearance/ActorEquipment.cs +++ b/Brio/Game/Actor/Appearance/ActorEquipment.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Actor.Appearance; [StructLayout(LayoutKind.Explicit, Size = Count)] -internal unsafe struct ActorEquipment +public unsafe struct ActorEquipment { public const int Count = 0x50; diff --git a/Brio/Game/Actor/Appearance/ActorExtendedAppearance.cs b/Brio/Game/Actor/Appearance/ActorExtendedAppearance.cs index 369bfa30..68060a2a 100644 --- a/Brio/Game/Actor/Appearance/ActorExtendedAppearance.cs +++ b/Brio/Game/Actor/Appearance/ActorExtendedAppearance.cs @@ -2,7 +2,7 @@ namespace Brio.Game.Actor.Appearance; -internal struct ActorExtendedAppearance() +public struct ActorExtendedAppearance() { public float Transparency = 1.0f; public float Wetness = 0.0f; diff --git a/Brio/Game/Actor/Appearance/ActorRuntimeOptions.cs b/Brio/Game/Actor/Appearance/ActorRuntimeOptions.cs index 8b8b1753..99e759c2 100644 --- a/Brio/Game/Actor/Appearance/ActorRuntimeOptions.cs +++ b/Brio/Game/Actor/Appearance/ActorRuntimeOptions.cs @@ -1,6 +1,6 @@ namespace Brio.Game.Actor.Appearance; -internal struct ActorRuntimeOptions() +public struct ActorRuntimeOptions() { public bool IsHatHidden = false; public bool IsVisorToggled = false; diff --git a/Brio/Game/Actor/Appearance/ActorWeapons.cs b/Brio/Game/Actor/Appearance/ActorWeapons.cs index dc928ae9..70d019a7 100644 --- a/Brio/Game/Actor/Appearance/ActorWeapons.cs +++ b/Brio/Game/Actor/Appearance/ActorWeapons.cs @@ -2,7 +2,7 @@ namespace Brio.Game.Actor.Appearance; -internal struct ActorWeapons +public struct ActorWeapons { public WeaponModelId MainHand; public WeaponModelId OffHand; diff --git a/Brio/Game/Actor/Appearance/AppearanceExtensions.cs b/Brio/Game/Actor/Appearance/AppearanceExtensions.cs index 144b4d44..0bb6f454 100644 --- a/Brio/Game/Actor/Appearance/AppearanceExtensions.cs +++ b/Brio/Game/Actor/Appearance/AppearanceExtensions.cs @@ -2,7 +2,7 @@ namespace Brio.Game.Actor.Appearance; -internal static class AppearanceExtensions +public static class AppearanceExtensions { public static Tribes[] GetValidTribes(this Races race) { diff --git a/Brio/Game/Actor/Appearance/AppearanceImportOptions.cs b/Brio/Game/Actor/Appearance/AppearanceImportOptions.cs index 095ee9fa..1b46ee61 100644 --- a/Brio/Game/Actor/Appearance/AppearanceImportOptions.cs +++ b/Brio/Game/Actor/Appearance/AppearanceImportOptions.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Actor.Appearance; [Flags] -internal enum AppearanceImportOptions +public enum AppearanceImportOptions { Customize = 1 << 0, Weapon = 1 << 1, diff --git a/Brio/Game/Actor/Appearance/AppearanceSanitizer.cs b/Brio/Game/Actor/Appearance/AppearanceSanitizer.cs index e7373607..fd2ab652 100644 --- a/Brio/Game/Actor/Appearance/AppearanceSanitizer.cs +++ b/Brio/Game/Actor/Appearance/AppearanceSanitizer.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Actor.Appearance; -internal static class AppearanceSanitizer +public static class AppearanceSanitizer { public static void SanitizeAppearance(ref ActorAppearance appearance, ActorAppearance? oldAppearance = null) { diff --git a/Brio/Game/Actor/Appearance/HumanData.cs b/Brio/Game/Actor/Appearance/HumanData.cs index 127de39d..b6077638 100644 --- a/Brio/Game/Actor/Appearance/HumanData.cs +++ b/Brio/Game/Actor/Appearance/HumanData.cs @@ -1,7 +1,7 @@ using System; namespace Brio.Game.Actor.Appearance; -internal class HumanData +public class HumanData { private readonly uint[] _rawColors; diff --git a/Brio/Game/Actor/Appearance/ModelShaderOverride.cs b/Brio/Game/Actor/Appearance/ModelShaderOverride.cs index b4c9780e..8c5ddb79 100644 --- a/Brio/Game/Actor/Appearance/ModelShaderOverride.cs +++ b/Brio/Game/Actor/Appearance/ModelShaderOverride.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Actor.Appearance; -internal struct ModelShaderOverride() +public struct ModelShaderOverride() { public Vector3? SkinColor = null; public float? MuscleTone = null; diff --git a/Brio/Game/Actor/Appearance/SpecialAppearances.cs b/Brio/Game/Actor/Appearance/SpecialAppearances.cs index 47f95d1c..76aa3931 100644 --- a/Brio/Game/Actor/Appearance/SpecialAppearances.cs +++ b/Brio/Game/Actor/Appearance/SpecialAppearances.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Actor.Appearance; -internal static class SpecialAppearances +public static class SpecialAppearances { public static WeaponModelId EmperorsMainHand { get; } = new() { diff --git a/Brio/Game/Actor/Extensions/CharacterExtensions.cs b/Brio/Game/Actor/Extensions/CharacterExtensions.cs index eff7e905..1edffd25 100644 --- a/Brio/Game/Actor/Extensions/CharacterExtensions.cs +++ b/Brio/Game/Actor/Extensions/CharacterExtensions.cs @@ -13,7 +13,7 @@ using StructsCharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase; using StructsDrawDataContainer = FFXIVClientStructs.FFXIV.Client.Game.Character.DrawDataContainer; -internal static class CharacterExtensions +public static class CharacterExtensions { public unsafe static StructsCharacter* Native(this ICharacter go) { diff --git a/Brio/Game/Actor/Extensions/GameObjectExtensions.cs b/Brio/Game/Actor/Extensions/GameObjectExtensions.cs index e615c3a6..e63a32c6 100644 --- a/Brio/Game/Actor/Extensions/GameObjectExtensions.cs +++ b/Brio/Game/Actor/Extensions/GameObjectExtensions.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Actor.Extensions; -internal static class GameObjectExtensions +public static class GameObjectExtensions { public static FontAwesomeIcon GetFriendlyIcon(this IGameObject go) { diff --git a/Brio/Game/Actor/Extensions/StatusManagerExtensions.cs b/Brio/Game/Actor/Extensions/StatusManagerExtensions.cs index d268be4a..027df56b 100644 --- a/Brio/Game/Actor/Extensions/StatusManagerExtensions.cs +++ b/Brio/Game/Actor/Extensions/StatusManagerExtensions.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Actor.Extensions; -internal static class StatusManagerExtensions +public static class StatusManagerExtensions { public static List GetAllStatuses(this ref StatusManager sm) { diff --git a/Brio/Game/Actor/Interop/BrioCharacterBase.cs b/Brio/Game/Actor/Interop/BrioCharacterBase.cs index eb5c1eb4..c1e2554a 100644 --- a/Brio/Game/Actor/Interop/BrioCharacterBase.cs +++ b/Brio/Game/Actor/Interop/BrioCharacterBase.cs @@ -7,7 +7,7 @@ namespace Brio.Game.Actor.Interop; [StructLayout(LayoutKind.Explicit, Size = 0x9D0)] -internal struct BrioCharacterBase +public struct BrioCharacterBase { [FieldOffset(0x0)] public CharacterBase CharacterBase; @@ -26,7 +26,7 @@ internal struct BrioCharacterBase } [StructLayout(LayoutKind.Explicit, Size = 0x78)] -internal unsafe struct Attach +public unsafe struct Attach { [FieldOffset(0x0)] public Task Task; @@ -40,12 +40,12 @@ internal unsafe struct Attach } [StructLayout(LayoutKind.Explicit, Size = 0x68)] -internal struct AttachmentEntry +public struct AttachmentEntry { [FieldOffset(0x02)] public ushort BoneIdx; } -internal enum AttachType : uint +public enum AttachType : uint { None = 0, Unknown1 = 1, diff --git a/Brio/Game/Actor/Interop/BrioDrawData.cs b/Brio/Game/Actor/Interop/BrioDrawData.cs index 841693df..e91ff507 100644 --- a/Brio/Game/Actor/Interop/BrioDrawData.cs +++ b/Brio/Game/Actor/Interop/BrioDrawData.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Actor.Interop; [StructLayout(LayoutKind.Explicit)] -internal unsafe struct BrioDrawData +public unsafe struct BrioDrawData { [FieldOffset(0x0)] public DrawDataContainer DawData; diff --git a/Brio/Game/Actor/Interop/BrioHuman.cs b/Brio/Game/Actor/Interop/BrioHuman.cs index cabf166d..a549ca5d 100644 --- a/Brio/Game/Actor/Interop/BrioHuman.cs +++ b/Brio/Game/Actor/Interop/BrioHuman.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Actor.Interop; [StructLayout(LayoutKind.Explicit)] -internal struct BrioHuman +public struct BrioHuman { [FieldOffset(0x0)] public Human Human; diff --git a/Brio/Game/Camera/BrioCamera.cs b/Brio/Game/Camera/BrioCamera.cs index 216eb7ed..38b681b3 100644 --- a/Brio/Game/Camera/BrioCamera.cs +++ b/Brio/Game/Camera/BrioCamera.cs @@ -5,7 +5,7 @@ using GameCamera = FFXIVClientStructs.FFXIV.Client.Game.Camera; [StructLayout(LayoutKind.Explicit, Size = 0x2B0)] -internal struct BrioCamera +public struct BrioCamera { [FieldOffset(0x0)] public GameCamera Camera; diff --git a/Brio/Game/Camera/CameraExtensions.cs b/Brio/Game/Camera/CameraExtensions.cs index c9233edb..ce2817e2 100644 --- a/Brio/Game/Camera/CameraExtensions.cs +++ b/Brio/Game/Camera/CameraExtensions.cs @@ -2,7 +2,7 @@ namespace Brio.Game.Camera; -internal static class CameraExtensions +public static class CameraExtensions { public unsafe static Matrix4x4 GetProjectionMatrix(this BrioCamera camera) { diff --git a/Brio/Game/Camera/CameraService.cs b/Brio/Game/Camera/CameraService.cs index da4bceab..e3bc94b8 100644 --- a/Brio/Game/Camera/CameraService.cs +++ b/Brio/Game/Camera/CameraService.cs @@ -16,11 +16,12 @@ namespace Brio.Game.Camera; -internal unsafe class CameraService : IDisposable +public unsafe class CameraService : IDisposable { private readonly EntityManager _entityManager; private readonly GPoseService _gPoseService; private readonly CutsceneManager _cutsceneManager; + private readonly VirtualCameraManager _virtualCameraService; private delegate nint CameraCollisionDelegate(BrioCamera* a1, Vector3* a2, Vector3* a3, float a4, nint a5, float a6); private readonly Hook _cameraCollisionHook = null!; @@ -32,20 +33,21 @@ internal unsafe class CameraService : IDisposable private readonly Hook _cameraSceneUpdateHook = null!; private delegate Matrix4x4* ProjectionMatrix(IntPtr ptr, float fov, float aspect, float nearPlane, float farPlane, float a6, float a7); - private static Hook ProjectionHook = null!; + private static Hook _projectionHook = null!; private delegate void CameraMatrixLoadDelegate(BrioRenderCamera* camera, nint a1); private readonly CameraMatrixLoadDelegate _cameraMatrixLoad; - public CameraService(EntityManager entityManager, CutsceneManager cutsceneManager, GPoseService gPoseService, ISigScanner scanner, IGameInteropProvider hooking) + public CameraService(EntityManager entityManager, VirtualCameraManager virtualCameraService, CutsceneManager cutsceneManager, GPoseService gPoseService, ISigScanner scanner, IGameInteropProvider hooking) { _entityManager = entityManager; _gPoseService = gPoseService; _cutsceneManager = cutsceneManager; + _virtualCameraService = virtualCameraService; var cameraProjection = "E8 ?? ?? ?? ?? EB ?? F3 0F ?? ?? ?? ?? ?? ?? F3 0F ?? ?? ?? ?? E8 ?? ?? ?? ?? 0F ?? ?? ?? 48 ?? ?? ??"; - ProjectionHook = hooking.HookFromAddress(scanner.ScanText(cameraProjection), ProjectionDetour); - ProjectionHook.Enable(); + _projectionHook = hooking.HookFromAddress(scanner.ScanText(cameraProjection), ProjectionDetour); + _projectionHook.Enable(); var cameraCollisionAddr = "E8 ?? ?? ?? ?? 4C 8D 45 ?? 89 83"; _cameraCollisionHook = hooking.HookFromAddress(scanner.ScanText(cameraCollisionAddr), CameraCollisionDetour); @@ -69,14 +71,14 @@ private nint CameraUpdateDetour(BrioCamera* camera) if(_gPoseService.IsGPosing) { - if(_entityManager.TryGetEntity("camera", out var cameraEntity)) + if(_entityManager.TryGetEntity("cameras", out var cameraEntity)) { - if(cameraEntity.TryGetCapability(out var cameraCapability)) + if(cameraEntity.TryGetCapability(out var cameraCapability)) { - if(camera == cameraCapability.Camera) + if(cameraCapability.CurrentCamera is not null) { Vector3 currentPos = camera->Camera.CameraBase.SceneCamera.Object.Position; - var newPos = cameraCapability.PositionOffset + currentPos; + var newPos = cameraCapability.CurrentCamera.PositionOffset + currentPos; camera->Camera.CameraBase.SceneCamera.Object.Position = newPos; Vector3 currentLookAt = camera->Camera.CameraBase.SceneCamera.LookAtVector; @@ -85,34 +87,42 @@ private nint CameraUpdateDetour(BrioCamera* camera) } } } + return result; } private unsafe Matrix4x4* ProjectionDetour(IntPtr ptr, float fov, float aspect, float nearPlane, float farPlane, float a6, float a7) { - if(_cutsceneManager.VirtualCamera.IsActive && _cutsceneManager.CameraSettings.EnableFOV) - fov = _cutsceneManager.VirtualCamera.State.FoV; - - var exec = ProjectionHook.Original(ptr, fov, aspect, nearPlane, farPlane, a6, a7); + if(_gPoseService.IsGPosing && _cutsceneManager.VirtualCamera.IsActiveCamera && _cutsceneManager.CameraSettings.EnableFOV) + fov = _cutsceneManager.VirtualCamera.FoV; - return exec; + return _projectionHook.Original(ptr, fov, aspect, nearPlane, farPlane, a6, a7); } private nint CameraSceneUpdateDetour(BrioSceneCamera* gsc) { var exec = _cameraSceneUpdateHook.Original(gsc); - if(_cutsceneManager.VirtualCamera.IsActive == false) + if(_gPoseService.IsGPosing == false) return exec; - var camMatrix = _cutsceneManager.UpdateCamera(); + if(_virtualCameraService.CurrentCamera is not null && _virtualCameraService.CurrentCamera.IsFreeCamera) + { + gsc->ViewMatrix = _virtualCameraService.UpdateMatrix(); - if(camMatrix is null) - return exec; + _cameraMatrixLoad(GetCurrentCamera()->Camera.CameraBase.SceneCamera.RenderCamera, (nint)(&gsc->ViewMatrix)); + } + else if(_cutsceneManager.VirtualCamera.IsActiveCamera) + { + var camMatrix = _cutsceneManager.UpdateCamera(); - gsc->ViewMatrix = camMatrix.Value; + if(camMatrix is null) + return exec; - _cameraMatrixLoad(GetCurrentCamera()->Camera.CameraBase.SceneCamera.RenderCamera, (nint)(&gsc->ViewMatrix)); + gsc->ViewMatrix = camMatrix.Value; + + _cameraMatrixLoad(GetCurrentCamera()->Camera.CameraBase.SceneCamera.RenderCamera, (nint)(&gsc->ViewMatrix)); + } return exec; } @@ -121,13 +131,13 @@ private nint CameraCollisionDetour(BrioCamera* camera, Vector3* a2, Vector3* a3, { if(_gPoseService.IsGPosing) { - if(_entityManager.TryGetEntity("camera", out var cameraEntity)) + if(_entityManager.TryGetEntity("camera", out var cameraEntity)) { - if(cameraEntity.TryGetCapability(out var cameraCapability)) + if(cameraEntity.TryGetCapability(out var cameraCapability)) { - if(cameraCapability.DisableCollision) + if(cameraCapability.CurrentCamera.DisableCollision) { - if(camera == cameraCapability.Camera) + if(camera == cameraCapability.CurrentCamera.BrioCamera) { camera->Collide = new Vector2(camera->Camera.MaxDistance); return 0; @@ -150,6 +160,6 @@ public void Dispose() _cameraCollisionHook.Dispose(); _cameraUpdateHook.Dispose(); _cameraSceneUpdateHook.Dispose(); - ProjectionHook.Dispose(); + _projectionHook.Dispose(); } } diff --git a/Brio/Game/Camera/VirtualCamera.cs b/Brio/Game/Camera/VirtualCamera.cs index 1d5b147c..45362ec9 100644 --- a/Brio/Game/Camera/VirtualCamera.cs +++ b/Brio/Game/Camera/VirtualCamera.cs @@ -1,12 +1,197 @@ -using System.Numerics; +using FFXIVClientStructs.FFXIV.Client.Game.Control; +using MessagePack; +using System.Numerics; namespace Brio.Game.Camera; -public record class CameraState(Matrix4x4 ViewMatrix, float FoV); +[MessagePackObject(keyAsPropertyName: true)] +public unsafe class VirtualCamera +{ + public VirtualCamera() { } + public VirtualCamera(int cameraID) + { + CameraID = cameraID; + + ResetCamera(); + } + + public FreeCamValues FreeCamValues { get; } = new FreeCamValues(); + + [IgnoreMember] public BrioCamera* BrioCamera => (BrioCamera*)CameraManager.Instance()->GetActiveCamera(); + + public unsafe bool IsOverridden => DisableCollision || DelimitCamera || PositionOffset != Vector3.Zero + | PivotRotation != 0 | FoV != 0 | Pan != Vector2.Zero | BrioCamera->Camera.Distance != 2.5f; + + [IgnoreMember] public bool IsActiveCamera { get; set; } = false; + public bool IsFreeCamera { get; set; } = false; + + [IgnoreMember] public int CameraID { get; private set; } = -1; + + public Vector3 RealPosition => BrioCamera->GetPosition(); + + public Vector3 Position = Vector3.Zero; + public Vector3 PositionOffset = Vector3.Zero; + public Vector3 Rotation = Vector3.Zero; + + public float PivotRotation + { + get => IsActiveCamera ? BrioCamera->Rotation : (field); + set + { + _ = IsActiveCamera ? (BrioCamera->Rotation = field = value) : (field = value); + } + } + public float Zoom + { + get => IsActiveCamera ? BrioCamera->Camera.Distance : (field); + set + { + _ = IsActiveCamera ? (BrioCamera->Camera.Distance = field = value) : (field = value); + } + } + public float FoV + { + get => IsActiveCamera ? BrioCamera->FoV : (field); + set + { + _ = IsActiveCamera ? (BrioCamera->FoV = field = value) : (field = value); + } + } + + public Vector2 Pan + { + get => IsActiveCamera ? BrioCamera->Pan : (field); + set + { + _ = IsActiveCamera ? (BrioCamera->Pan = field = value) : (field = value); + } + } + public Vector2 Angle + { + get => IsActiveCamera ? BrioCamera->Angle : (field); + set + { + _ = IsActiveCamera ? (BrioCamera->Angle = field = value) : (field = value); + } + } + + public bool DisableCollision = false; + + private Vector2? _originalZoomLimits { get; set; } = null; + bool delimitCameraHasOverride = false; + [IgnoreMember] + public bool DelimitCamera + { + get => _originalZoomLimits.HasValue; + set + { + if(IsActiveCamera == false) + return; + + if(value) + DelimitCameraStart(); + else + DelimitCameraStop(); + + delimitCameraHasOverride = value; + } + } + + private void DelimitCameraStop() + { + if(_originalZoomLimits.HasValue) + { + BrioCamera->Camera.MinDistance = _originalZoomLimits.Value.X; + BrioCamera->Camera.MaxDistance = _originalZoomLimits.Value.Y; + + if(BrioCamera->Camera.Distance < BrioCamera->Camera.MinDistance) + BrioCamera->Camera.Distance = BrioCamera->Camera.MinDistance; -public class VirtualCamera + _originalZoomLimits = null; + } + } + private void DelimitCameraStart() + { + _originalZoomLimits = new Vector2(BrioCamera->Camera.MinDistance, BrioCamera->Camera.MaxDistance); + + BrioCamera->Camera.MinDistance = 0f; + BrioCamera->Camera.MaxDistance = 500f; + } + + public void ActivateCamera() + { + if(IsActiveCamera) + return; + + LoadCameraState(); + + IsActiveCamera = true; + } + public void DeactivateCamera() + { + if(IsActiveCamera is false) + return; + IsActiveCamera = false; + + SaveCameraState(); + } + + public unsafe void ResetCamera() + { + PositionOffset = Vector3.Zero; + + DisableCollision = false; + DelimitCamera = false; + + PivotRotation = 0; + Zoom = 2.5f; + FoV = 0f; + Angle = Vector2.Zero; + Pan = Vector2.Zero; + } + + public void SaveCameraState() + { + PivotRotation = BrioCamera->Rotation; + Zoom = BrioCamera->Camera.Distance; + FoV = BrioCamera->FoV; + + Angle = BrioCamera->Angle; + Pan = BrioCamera->Pan; + } + public void LoadCameraState() + { + BrioCamera->Rotation = PivotRotation; + BrioCamera->Camera.Distance = Zoom; + BrioCamera->FoV = FoV; + + BrioCamera->Angle = Angle; + BrioCamera->Pan = Pan; + + DelimitCamera = delimitCameraHasOverride; + } + + public void SetCameraID(int id) + { + CameraID = id; + } + + public void ToFreeCam() + { + if(Position == Vector3.Zero) + Position = RealPosition; + IsFreeCamera = true; + } +} + +[MessagePackObject(keyAsPropertyName: true)] +public class FreeCamValues { - public bool IsActive { get; set; } = false; + public bool IsMovementEnabled = false; + public bool Move2D = false; + + public float MouseSensitivity = 0f; + public float MovementSpeed = 0f; - public CameraState State { get; set; } = new CameraState(Matrix4x4.Identity, 0.78f); + public bool DelimitAngle = false; } diff --git a/Brio/Game/Camera/VirtualCameraManager.cs b/Brio/Game/Camera/VirtualCameraManager.cs new file mode 100644 index 00000000..e473ab29 --- /dev/null +++ b/Brio/Game/Camera/VirtualCameraManager.cs @@ -0,0 +1,279 @@ +using Brio.Core; +using Brio.Entities; +using Brio.Entities.Camera; +using Brio.Game.GPose; +using Brio.Game.Input; +using Dalamud.Game.ClientState.Keys; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Numerics; + +namespace Brio.Game.Camera; + +public class VirtualCameraManager : IDisposable +{ + public const float DefaultMovementSpeed = 0.04f; + public const float DefaultMouseSensitivity = 0.1f; + + public VirtualCamera? CurrentCamera { get; private set; } + public FreeCamValues FreeCamValues => CurrentCamera?.FreeCamValues!; + + public int CamerasCount => _createdCameras.Count; + + private readonly IServiceProvider _serviceProvider; + private readonly GPoseService _gPoseService; + private readonly EntityManager _entityManager; + + public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPoseService, EntityManager entityManager) + { + _serviceProvider = serviceProvider; + _gPoseService = gPoseService; + _entityManager = entityManager; + + _gPoseService.OnGPoseStateChange += OnGPoseStateChange; + } + + private readonly Vector3 Up = new(0f, 1f, 0f); + + int _cameraId = 1; + private readonly Dictionary _createdCameras = []; + + private float _moveSpeed = DefaultMovementSpeed; + private float _mouseSensitivity = DefaultMouseSensitivity; + + public (bool, int) CreateCamera(CameraType cameraType, bool selectCamera = true, bool targetNewInHierarch = true, VirtualCamera? virtualCamera = null) + { + if(_entityManager.TryGetEntity("cameras", out var ent)) + { + CurrentCamera?.DeactivateCamera(); + + _cameraId++; + + var camEnt = ActivatorUtilities.CreateInstance(_serviceProvider, _cameraId, cameraType); + _entityManager.AttachEntity(camEnt, ent); + + if(virtualCamera is null) + { + if(cameraType == CameraType.Free) + { + camEnt.VirtualCamera.FreeCamValues.MovementSpeed = DefaultMovementSpeed; + camEnt.VirtualCamera.FreeCamValues.MouseSensitivity = DefaultMouseSensitivity; + camEnt.VirtualCamera.IsFreeCamera = true; + camEnt.VirtualCamera.ActivateCamera(); + camEnt.VirtualCamera.ToFreeCam(); + camEnt.VirtualCamera.DeactivateCamera(); + + _createdCameras.Add(_cameraId, camEnt); + } + } + else + { + var id = camEnt.SetVirtualCamera(virtualCamera); + + if(_createdCameras.TryAdd(id, camEnt) == false) + { + _createdCameras[id] = camEnt; + } + } + + CurrentCamera?.ActivateCamera(); + + + if(targetNewInHierarch) + _entityManager.SetSelectedEntity(camEnt); + else if(selectCamera) + SelectCamera(camEnt.VirtualCamera); + + return (true, _cameraId); + } + return (false, -1); + } + + public bool DestroyCamera(int cameraID) + { + if(cameraID == 0) + return false; + + Brio.Log.Verbose("Destroying Brio camera " + _cameraId); + + if(_entityManager.TryGetEntity("cameras", out var ent)) + { + if(_createdCameras.TryGetValue(cameraID, out CameraEntity? camEnt)) + { + if(_entityManager.SelectedEntity == camEnt && camEnt.VirtualCamera.IsActiveCamera) + { + if(_entityManager.TryGetEntity(new Entities.Core.CameraId(0), out var defaultCamEnt) && defaultCamEnt is CameraEntity cameraEnt) + { + SelectCamera(cameraEnt.VirtualCamera); + _entityManager.SetSelectedEntity(defaultCamEnt); + } + } + + ent.RemoveChild(camEnt); + + return true; + } + } + return false; + } + + public void SelectCamera(VirtualCamera virtualCamera) + { + CurrentCamera?.DeactivateCamera(); + + CurrentCamera = virtualCamera; + + CurrentCamera.ActivateCamera(); + } + + public void DestroyAll() + { + _cameraId = 0; + CurrentCamera = null; + foreach(var item in _createdCameras) + { + DestroyCamera(item.Key); + } + } + + public void SelectInHierarchy(CameraEntity selectedEntity) + { + if(selectedEntity is not null) + _entityManager.SetSelectedEntity(new Entities.Core.CameraId(selectedEntity.CameraID)); + } + + public IEnumerable GetAllCameras() + { + foreach(var item in _createdCameras.Values) + { + yield return item; + } + } + + // + // Free Cam + // + + public Vector3 _forward; + public Vector2 _lastMousePosition; + + public unsafe void Update(MouseFrame* mouseFrame, KeyboardFrame* keyboardFrame) + { + if((mouseFrame is null && keyboardFrame is null) || CurrentCamera is null) + { + return; + } + + // + // Handle mouse input + // + + if(mouseFrame->IsKeyDown(MouseState.Right)) + { + _lastMousePosition += mouseFrame->GetDeltaAsVector2(); + + mouseFrame->HandleDelta(); + } + + // + // Handle keyboard input + // + + if(FreeCamValues.IsMovementEnabled == false) + { + return; + } + + // Initialize forward and lateral movement variables + var forwardBackward = 0; + var leftRight = 0; + var upDown = 0; + + // Check for forward and backward movement + if(keyboardFrame->IsKeyDown(VirtualKey.W, true)) + forwardBackward -= 1; + if(keyboardFrame->IsKeyDown(VirtualKey.S, true)) + forwardBackward += 1; + + // Check for lateral movement + if(keyboardFrame->IsKeyDown(VirtualKey.A, true)) + leftRight -= 1; + if(keyboardFrame->IsKeyDown(VirtualKey.D, true)) + leftRight += 1; + + // Handle vertical movement (up and down) + if(keyboardFrame->IsKeyDown(VirtualKey.E, true)) + upDown += 1; + else if(keyboardFrame->IsKeyDown(VirtualKey.Q, true)) + upDown += -1; + + // Handle movement speed + if(keyboardFrame->IsKeyDown(VirtualKey.SHIFT, true)) + _moveSpeed = CurrentCamera.FreeCamValues.MovementSpeed * 3; + else if(keyboardFrame->IsKeyDown(VirtualKey.MENU, true)) + _moveSpeed = CurrentCamera.FreeCamValues.MovementSpeed * 0.3f; + + _forward = Vector3.Transform(new Vector3(leftRight, upDown, forwardBackward), + Quaternion.CreateFromYawPitchRoll(CurrentCamera!.Rotation.X, FreeCamValues.Move2D ? 0 : -CurrentCamera.Rotation.Y, CurrentCamera.Rotation.Z)); + } + public Matrix4x4 UpdateMatrix() + { + if(CurrentCamera is null) + { + throw new NullReferenceException("CurrentCamera can not be null"); + } + + _lastMousePosition *= CurrentCamera.FreeCamValues.MouseSensitivity * MathHelpers.DegreesToRadians; + CurrentCamera.Position += _forward * _moveSpeed; + + CurrentCamera.Rotation.X -= _lastMousePosition.X; + CurrentCamera.Rotation.Y = FreeCamValues.DelimitAngle ? CurrentCamera.Rotation.Y + _lastMousePosition.Y : Math.Clamp(CurrentCamera.Rotation.Y + _lastMousePosition.Y, -1.5f, 1.5f); + + _moveSpeed = CurrentCamera.FreeCamValues.MovementSpeed; + _lastMousePosition = Vector2.Zero; + _forward = Vector3.Zero; + + var lookVector = new Vector3( + MathF.Sin(CurrentCamera.Rotation.X) * MathF.Cos(CurrentCamera.Rotation.Y), + MathF.Sin(CurrentCamera.Rotation.Y), + MathF.Cos(CurrentCamera.Rotation.X) * MathF.Cos(CurrentCamera.Rotation.Y)); + + // Normalize the look direction + var lookDirection = Vector3.Normalize(lookVector); + var rightVector = Vector3.Normalize(Vector3.Cross(Up, lookDirection)); + var upVector = Vector3.Cross(lookDirection, rightVector); + + // Create the view matrix + return new Matrix4x4 + ( + rightVector.X, upVector.X, lookDirection.X, 0.0f, + rightVector.Y, upVector.Y, lookDirection.Y, 0.0f, + rightVector.Z, upVector.Z, lookDirection.Z, 0.0f, + + (-CurrentCamera.Position.X * rightVector.X) - (CurrentCamera.Position.Y * rightVector.Y) - (CurrentCamera.Position.Z * rightVector.Z), + (-CurrentCamera.Position.X * upVector.X) - (CurrentCamera.Position.Y * upVector.Y) - (CurrentCamera.Position.Z * upVector.Z), + (-CurrentCamera.Position.X * lookDirection.X) - (CurrentCamera.Position.Y * lookDirection.Y) - (CurrentCamera.Position.Z * lookDirection.Z), + 1f + ); + } + + private void OnGPoseStateChange(bool newState) + { + if(newState == false) + { + DestroyAll(); + } + else + { + var defaultCam = _entityManager.GetEntity(new Entities.Core.CameraId(0)); + if(defaultCam != null) + SelectCamera(defaultCam.VirtualCamera); + } + } + + public void Dispose() + { + _gPoseService.OnGPoseStateChange -= OnGPoseStateChange; + } +} diff --git a/Brio/Game/Chat/CommandHandlerService.cs b/Brio/Game/Chat/CommandHandlerService.cs index d6a2de65..acecd7ab 100644 --- a/Brio/Game/Chat/CommandHandlerService.cs +++ b/Brio/Game/Chat/CommandHandlerService.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Chat; -internal class CommandHandlerService : IDisposable +public class CommandHandlerService : IDisposable { private const string BrioCommandName = "/brio"; private const string XATCommandName = "/xat"; diff --git a/Brio/Game/Core/AutoSaveService.cs b/Brio/Game/Core/AutoSaveService.cs new file mode 100644 index 00000000..73abb008 --- /dev/null +++ b/Brio/Game/Core/AutoSaveService.cs @@ -0,0 +1,203 @@ +using Brio.Config; +using Brio.Files; +using Brio.Game.GPose; +using Brio.Game.Scene; +using Brio.UI; +using Dalamud.Plugin; +using Dalamud.Plugin.Services; +using Dalamud.Utility; +using MessagePack; +using System; +using System.IO; +using System.Linq; +using System.Timers; + +namespace Brio.Game.Core; + +public class AutoSaveService : IDisposable +{ + private readonly IDalamudPluginInterface _pluginInterface; + private readonly IFramework _framework; + private readonly GPoseService _gPoseService; + private readonly SceneService _sceneService; + + public bool IsEnabled = true; + + public AutoSaveService(IDalamudPluginInterface pluginInterface, IFramework framework, SceneService sceneService, GPoseService gPoseService) + { + _pluginInterface = pluginInterface; + _framework = framework; + _gPoseService = gPoseService; + _sceneService = sceneService; + + gPoseService.OnGPoseStateChange += GPoseService_OnGPoseStateChange; + } + + private Timer? _timer = null; + private string AutoSaveFolder => Path.Combine(_pluginInterface.GetPluginConfigDirectory(), "Data", "AutoSaves"); + + public void Start() + { + if(Directory.Exists(AutoSaveFolder) == false) + { + Directory.CreateDirectory(AutoSaveFolder); + } + + _timer = new Timer(TimeSpan.FromSeconds(ConfigurationService.Instance.Configuration.AutoSave.AutoSaveInterval)); + _timer.Elapsed += OnElapsed; + _timer.AutoReset = true; + + _timer.Start(); + } + + public void Stop() + { + _timer?.Stop(); + + if(ConfigurationService.Instance.Configuration.AutoSave.CleanAutoSaveOnLeavingGpose) + { + CleanAllSaves(); + } + else + { + CleanOldSaves(); + } + } + + private void OnElapsed(object? sender, ElapsedEventArgs e) + { + if(IsEnabled) + _framework.RunOnFrameworkThread(AutoSave); + } + + private void AutoSave() + { + try + { + var scene = _sceneService.GenerateSceneFile(); + + byte[] bytes = MessagePackSerializer.Serialize(scene); + + var path = Path.Combine(AutoSaveFolder, $"autosave-{DateTime.Now:yyyy-MM-dd}-{DateTime.Now:hh-mm-ss}.brioautosave"); + Brio.Log.Verbose($"AutoSaving: {path}"); + + File.WriteAllBytes(path, bytes); + + Brio.Log.Verbose($"AutoSaved!"); + + Update(); + CleanOldSaves(); + } + catch(Exception ex) + { + Brio.Log.Error(ex, "Exception AutoSaving!"); + } + } + + public void ShowAutoSaves() + { + IsEnabled = false; + UIManager.Instance.FileDialogManager.CustomSideBarItems.Clear(); + UIManager.Instance.FileDialogManager.OpenFileDialog( + "Load AutoSave", + ".brioautosave", + (success, paths) => + { + if(success && paths.Count == 1) + { + string path = paths[0]; + if(path.IsNullOrEmpty() == false) + { + try + { + var result = MessagePackSerializer.Deserialize(File.ReadAllBytes(path)); + _sceneService.LoadScene(result, true); + } + catch(Exception ex) + { + Brio.NotifyError("Brio AutoSave save was corrupted!"); + Brio.Log.Error(ex, "Exception while loading an AutoSave!"); + } + } + } + IsEnabled = true; + }, + 1, + AutoSaveFolder, + true); + } + + internal void Update() + { + var timeInterval = TimeSpan.FromSeconds(ConfigurationService.Instance.Configuration.AutoSave.AutoSaveInterval).TotalMilliseconds; + if(_timer is not null && _timer.Interval != timeInterval) + { + _timer.Interval = timeInterval; + } + } + + public void CleanOldSaves() + { + try + { + var saveFiles = Directory.EnumerateFiles(AutoSaveFolder) + .Select(f => new FileInfo(f)) + .OrderByDescending(f => f.LastWriteTime) + .ToList(); + + if(saveFiles.Count > ConfigurationService.Instance.Configuration.AutoSave.MaxAutoSaves) + { + + } + + // Keep the newest files and delete the rest + var filesToDelete = saveFiles.Skip(ConfigurationService.Instance.Configuration.AutoSave.MaxAutoSaves); + + foreach(var file in filesToDelete) + { + file.Delete(); + } + } + catch(Exception ex) + { + Brio.Log.Error(ex, "Exception While Cleaning old AutoSaves!"); + } + } + + public void CleanAllSaves() + { + try + { + var saveFiles = Directory.EnumerateFiles(AutoSaveFolder) + .Select(f => new FileInfo(f)) + .ToList(); + + foreach(var file in saveFiles) + { + file.Delete(); + } + } + catch(Exception ex) + { + Brio.Log.Error(ex, "Exception While Cleaning all AutoSaves!"); + } + } + + private void GPoseService_OnGPoseStateChange(bool newState) + { + if(newState) + { + Start(); + } + else + { + Stop(); + } + } + + public void Dispose() + { + Stop(); + _gPoseService.OnGPoseStateChange -= GPoseService_OnGPoseStateChange; + } +} diff --git a/Brio/Game/Core/FrameworkExtensions.cs b/Brio/Game/Core/FrameworkExtensions.cs index dca45056..e56892f5 100644 --- a/Brio/Game/Core/FrameworkExtensions.cs +++ b/Brio/Game/Core/FrameworkExtensions.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Core; -internal static class FrameworkExtensions +public static class FrameworkExtensions { public static Task RunUntilSatisfied( this IFramework framework, diff --git a/Brio/Game/Core/FrameworkScheduler.cs b/Brio/Game/Core/FrameworkScheduler.cs index b122ea77..16ed3446 100644 --- a/Brio/Game/Core/FrameworkScheduler.cs +++ b/Brio/Game/Core/FrameworkScheduler.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Core; -internal class FrameworkScheduler(IFramework framework, bool alwaysDefer) : TaskScheduler +public class FrameworkScheduler(IFramework framework, bool alwaysDefer) : TaskScheduler { private readonly IFramework _framework = framework; private readonly bool _alwaysDefer = alwaysDefer; diff --git a/Brio/Game/Core/ObjectMonitorService.cs b/Brio/Game/Core/ObjectMonitorService.cs index 57c0e07a..294d74b7 100644 --- a/Brio/Game/Core/ObjectMonitorService.cs +++ b/Brio/Game/Core/ObjectMonitorService.cs @@ -9,7 +9,7 @@ namespace Brio.Game.Core; -internal unsafe class ObjectMonitorService : IDisposable +public unsafe class ObjectMonitorService : IDisposable { public IObjectTable ObjectTable => _objectTable; diff --git a/Brio/Game/Core/ProjectSystem.cs b/Brio/Game/Core/ProjectSystem.cs new file mode 100644 index 00000000..4bddefd2 --- /dev/null +++ b/Brio/Game/Core/ProjectSystem.cs @@ -0,0 +1,151 @@ +using Brio.Files; +using Brio.Game.GPose; +using Brio.Game.Scene; +using Dalamud.Plugin; +using Dalamud.Plugin.Services; +using MessagePack; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Brio.Game.Core; + +[MessagePackObject] +public record class Project +{ + [Key(0)] public int Version { get; set; } = 1; + + [Key(1)] public required string Name { get; set; } + [Key(2)] public string? Description { get; set; } + + [Key(3)] public required string Path { get; set; } + [Key(4)] public string? ImagePath { get; set; } + + [Key(5)] public DateTime? Created { get; set; } +} + +[MessagePackObject] +public class BrioProjects +{ + [Key(0)] public List Projects { get; set; } = []; +} + +public class ProjectSystem : IDisposable +{ + private readonly IDalamudPluginInterface _pluginInterface; + private readonly IFramework _framework; + private readonly GPoseService _gPoseService; + private readonly SceneService _sceneService; + + public bool IsLoading => _sceneService.IsLoading; + + public bool IsEnabled = true; + + private string ProjectSaveFolder => Path.Combine(_pluginInterface.GetPluginConfigDirectory(), "Data", "Projects"); + private string BrioDataPath => Path.Combine(ProjectSaveFolder, "brio.data"); + + public BrioProjects BrioProjects { get; set; } = new BrioProjects(); + + public ProjectSystem(IDalamudPluginInterface pluginInterface, IFramework framework, SceneService sceneService, GPoseService gPoseService) + { + _pluginInterface = pluginInterface; + _framework = framework; + _gPoseService = gPoseService; + _sceneService = sceneService; + + Directory.CreateDirectory(ProjectSaveFolder); + + LoadProjectData(); + + gPoseService.OnGPoseStateChange += GPoseService_OnGPoseStateChange; + } + + + public void NewProject(string projectName, string? Description) + { + var path = Path.Combine(ProjectSaveFolder, $"{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.brioproj"); + + try + { + var scene = _sceneService.GenerateSceneFile(); + + Brio.Log.Verbose($"saving new project: {path}"); + + byte[] bytes = MessagePackSerializer.Serialize(scene); + File.WriteAllBytes(path, bytes); + + BrioProjects.Projects.Add(new Project { Name = projectName, Path = path, Description = Description, Created = DateTime.UtcNow }); + + SaveProjectData(); + } + catch(Exception ex) + { + Brio.Log.Error(ex, $"Exception while saving new project: {projectName}"); + } + } + + public void LoadProject(Project project, bool destroyAll) + { + var result = MessagePackSerializer.Deserialize(File.ReadAllBytes(project.Path)); + _sceneService.LoadScene(result, destroyAll); + } + + public void DeleteProject(Project project) + { + if(File.Exists(project.Path)) + { + File.Delete(project.Path); + + BrioProjects.Projects.Remove(project); + + SaveProjectData(); + } + } + + private void LoadProjectData() + { + if(File.Exists(BrioDataPath)) + { + var bytes = File.ReadAllBytes(BrioDataPath); + + BrioProjects = MessagePackSerializer.Deserialize(bytes); + } + } + + private void SaveProjectData() + { + byte[] bytes = MessagePackSerializer.Serialize(BrioProjects); + + File.WriteAllBytes(BrioDataPath, bytes); + } + + public void DeleteAllProjects() + { + try + { + var saveFiles = Directory.EnumerateFiles(ProjectSaveFolder) + .Select(f => new FileInfo(f)) + .ToList(); + + foreach(var file in saveFiles) + { + file.Delete(); + } + } + catch(Exception ex) + { + Brio.Log.Error(ex, "Exception While Cleaning all AutoSaves!"); + } + } + + private void GPoseService_OnGPoseStateChange(bool newState) + { + + } + + public void Dispose() + { + _gPoseService.OnGPoseStateChange -= GPoseService_OnGPoseStateChange; + } +} diff --git a/Brio/Game/Core/TargetService.cs b/Brio/Game/Core/TargetService.cs index 4d4a003d..0a7e6a9a 100644 --- a/Brio/Game/Core/TargetService.cs +++ b/Brio/Game/Core/TargetService.cs @@ -8,7 +8,7 @@ namespace Brio.Game.Core; -internal class TargetService : IDisposable +public class TargetService : IDisposable { private readonly EntityManager _entityManager; private readonly ITargetManager _targetManager; diff --git a/Brio/Game/Cutscene/CutsceneManager.cs b/Brio/Game/Cutscene/CutsceneManager.cs index 3fcf1374..24421760 100644 --- a/Brio/Game/Cutscene/CutsceneManager.cs +++ b/Brio/Game/Cutscene/CutsceneManager.cs @@ -16,7 +16,7 @@ namespace Brio.Game.Cutscene; -internal class CutsceneManager : IDisposable +public class CutsceneManager : IDisposable { private const double FRAME_STEP = 33.33333333333333; @@ -40,21 +40,18 @@ internal class CutsceneManager : IDisposable public bool IsRunning => Stopwatch.IsRunning; - public bool DelayStart = false; public int DelayTime = 0; + public bool DelayStart = false; - public bool DelayAnimationStart = false; public int DelayAnimationTime = 0; + public bool DelayAnimationStart = false; + public VirtualCamera VirtualCamera { get; } = new VirtualCamera(300); public CutsceneCameraSettings CameraSettings { get; } = new(); - public VirtualCamera VirtualCamera { get; } - - public XATCameraFile? CameraPath { get; set; } + public XATCameraFile? CameraPath { get; set; } = null; - public CutsceneManager(GPoseService gPoseService, VirtualCamera virtualCamera, EntityManager entityManager, ITargetManager targetManager, IFramework framework) + public CutsceneManager(GPoseService gPoseService, EntityManager entityManager, ITargetManager targetManager, IFramework framework) { - VirtualCamera = virtualCamera; - _targetManager = targetManager; _gPoseService = gPoseService; _entityManager = entityManager; @@ -123,7 +120,7 @@ public void StartPlayback() Stopwatch.Reset(); Stopwatch.Start(); - VirtualCamera.IsActive = true; + VirtualCamera.IsActiveCamera = true; } public void StopPlayback() { @@ -136,7 +133,7 @@ public void StopPlayback() Stopwatch.Reset(); _animationStarted = false; - VirtualCamera.IsActive = false; + VirtualCamera.IsActiveCamera = false; if(StartAllActorAnimationsOnPlay) { StopAllActors(); @@ -238,16 +235,10 @@ public void StopPlayback() // Create a matrix with the base position var basePositionMatrix = Matrix4x4.CreateTranslation(-BasePosition); - // Create the final matrix - var finalMat = basePositionMatrix * (localTranslationMatrix * invertedLocalRotationMatrix); - - this.VirtualCamera.State = new - ( - ViewMatrix: finalMat, - FoV: rawFoV - ); + VirtualCamera.FoV = rawFoV; - return finalMat; + // Create the final matrix + return basePositionMatrix * (localTranslationMatrix * invertedLocalRotationMatrix); } public void Dispose() @@ -256,6 +247,8 @@ public void Dispose() InputService.Instance.RemoveListener(KeyBindEvents.Interface_StartAllActorsAnimations, StartAllActors); InputService.Instance.RemoveListener(KeyBindEvents.Interface_StopAllActorsAnimations, StopAllActors); + _gPoseService.OnGPoseStateChange -= OnGPoseStateChange; + if(IsRunning) StopPlayback(); } diff --git a/Brio/Game/GPose/GPoseService.cs b/Brio/Game/GPose/GPoseService.cs index 06855b61..b59e365a 100644 --- a/Brio/Game/GPose/GPoseService.cs +++ b/Brio/Game/GPose/GPoseService.cs @@ -11,7 +11,7 @@ namespace Brio.Game.GPose; -internal unsafe class GPoseService : IDisposable +public unsafe class GPoseService : IDisposable { public bool IsGPosing => _isInFakeGPose || _isInGPose; diff --git a/Brio/Game/Input/GameInputService.cs b/Brio/Game/Input/GameInputService.cs new file mode 100644 index 00000000..40eb4efa --- /dev/null +++ b/Brio/Game/Input/GameInputService.cs @@ -0,0 +1,70 @@ +using Brio.Game.Camera; +using Brio.Game.GPose; +using Dalamud.Game; +using Dalamud.Game.ClientState.Keys; +using Dalamud.Hooking; +using Dalamud.Plugin.Services; +using System; + +namespace Brio.Game.Input; + +public class GameInputService : IDisposable +{ + private readonly GPoseService _gPoseService; + private readonly VirtualCameraManager _virtualCameraService; + + public bool AllowEscape { get; set; } = true; + public bool HandleAllKeys { get; set; } = false; + public bool HandleAllMouse { get; set; } = false; + + private unsafe delegate void HandleInputDelegate(IntPtr arg1, IntPtr arg2, IntPtr arg3, MouseFrame* mouseState, KeyboardFrame* keyboardState); + private readonly Hook _handleInputHook = null!; + + public unsafe GameInputService(GPoseService gPoseService, VirtualCameraManager virtualCameraService, ISigScanner scanner, IGameInteropProvider hooking) + { + _gPoseService = gPoseService; + _virtualCameraService = virtualCameraService; + + var inputHandleSig = "E8 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 87 6C 35"; + _handleInputHook = hooking.HookFromAddress(scanner.ScanText(inputHandleSig), HandleInputDetour); + _handleInputHook.Enable(); + } + + public unsafe void HandleInputDetour(IntPtr arg1, IntPtr arg2, IntPtr arg3, MouseFrame* mouseFrame, KeyboardFrame* keyboardFrame) + { + _handleInputHook.Original(arg1, arg2, arg3, mouseFrame, keyboardFrame); + + if(_gPoseService.IsGPosing == false) + return; + + if(_virtualCameraService.CurrentCamera?.IsFreeCamera == true) + _virtualCameraService.Update(mouseFrame, keyboardFrame); + + if(HandleAllKeys) + { + keyboardFrame->HandleAllKeys(); + } + else if(AllowEscape is false) + { + keyboardFrame->HandleKey(VirtualKey.ESCAPE); + } + + if(HandleAllMouse) + { + // TODO: Implement mouse handling logic + } + + if(Config.ConfigurationService.Instance.Configuration.Input.EnableKeyHandlingOnKeyMod) + { + if(keyboardFrame->IsKeyDown(VirtualKey.CONTROL, true) || keyboardFrame->IsKeyDown(VirtualKey.SHIFT, true) || keyboardFrame->IsKeyDown(VirtualKey.MENU, true)) + { + keyboardFrame->HandleAllKeys(); + } + } + } + + public void Dispose() + { + _handleInputHook.Dispose(); + } +} diff --git a/Brio/Game/Input/KeyboardFrame.cs b/Brio/Game/Input/KeyboardFrame.cs new file mode 100644 index 00000000..f3f4606c --- /dev/null +++ b/Brio/Game/Input/KeyboardFrame.cs @@ -0,0 +1,33 @@ +using Dalamud.Game.ClientState.Keys; +using System.Runtime.InteropServices; + +namespace Brio.Game.Input; + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct KeyboardFrame +{ + public const int KeyStateLength = 254; + + public byte Unknown1; + public fixed uint KeyState[KeyStateLength]; + + public readonly bool KeyDown(VirtualKey virtualKey) + => KeyState[(int)virtualKey] is not 0; + + public void HandleKey(VirtualKey virtualKey) + => KeyState[(int)virtualKey] = 0; + + public void HandleAllKeys() + { + for(int i = 0; i < KeyStateLength; i++) + KeyState[i] = 0; + } + + public bool IsKeyDown(VirtualKey virtualKey, bool handle) + { + var isDown = KeyDown(virtualKey); + if(handle) + HandleKey(virtualKey); + return isDown; + } +} diff --git a/Brio/Game/Input/MouseFrame.cs b/Brio/Game/Input/MouseFrame.cs new file mode 100644 index 00000000..b66ef51b --- /dev/null +++ b/Brio/Game/Input/MouseFrame.cs @@ -0,0 +1,39 @@ +using System.Numerics; +using System.Runtime.InteropServices; + +namespace Brio.Game.Input; + +[StructLayout(LayoutKind.Sequential)] +public struct MouseFrame +{ + public int PositionX; + public int PositionY; + public int ScrollValue; + public MouseState ButtonsPressed; + public MouseState ButtonsClicked; + public ulong Unknown1; + public int DeltaX; + public int DeltaY; + + public readonly bool IsKeyDown(MouseState mouseButton) + => ButtonsPressed.HasFlag(mouseButton); + + public readonly Vector2 GetDeltaAsVector2() + => new(DeltaX, DeltaY); + + public readonly Vector2 GetPositionAsVector2() + => new(PositionX, PositionY); + + public void HandleDelta() + { + DeltaX = DeltaY = 0; + } +} + +public enum MouseState +{ + None = 0, + Left = 1, + Middle = 2, + Right = 4, // Why is this like this??, it's a flag you dummy +} diff --git a/Brio/Game/Posing/BoneCategories.cs b/Brio/Game/Posing/BoneCategories.cs index 148e639c..7e5dccfe 100644 --- a/Brio/Game/Posing/BoneCategories.cs +++ b/Brio/Game/Posing/BoneCategories.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Posing; -internal class BoneCategories +public class BoneCategories { public IReadOnlyList Categories => _categories; @@ -21,16 +21,16 @@ public BoneCategories() } } - internal record class BoneCategory(string Id, string Name, BoneCategoryTypes Type, List Bones); + public record class BoneCategory(string Id, string Name, BoneCategoryTypes Type, List Bones); private class BoneCategoryFile { public Dictionary Categories { get; set; } = []; - internal record class BoneCategoryFileEntry(BoneCategoryTypes Type, List Bones); + public record class BoneCategoryFileEntry(BoneCategoryTypes Type, List Bones); } - internal enum BoneCategoryTypes + public enum BoneCategoryTypes { Filter } diff --git a/Brio/Game/Posing/BoneFilter.cs b/Brio/Game/Posing/BoneFilter.cs index 1013b406..d18982df 100644 --- a/Brio/Game/Posing/BoneFilter.cs +++ b/Brio/Game/Posing/BoneFilter.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Posing; -internal class BoneFilter +public class BoneFilter { private readonly PosingService _posingService; diff --git a/Brio/Game/Posing/IKService.cs b/Brio/Game/Posing/IKService.cs index c012dfff..ef6b6903 100644 --- a/Brio/Game/Posing/IKService.cs +++ b/Brio/Game/Posing/IKService.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; namespace Brio.Game.Posing; -internal unsafe class IKService : IDisposable +public unsafe class IKService : IDisposable { delegate* unmanaged _ccdSolverCtr; delegate* unmanaged*, hkaPose*, byte*> _ccdSolverSolve; diff --git a/Brio/Game/Posing/ModelTransformService.cs b/Brio/Game/Posing/ModelTransformService.cs index 1f93d2b4..fffad76f 100644 --- a/Brio/Game/Posing/ModelTransformService.cs +++ b/Brio/Game/Posing/ModelTransformService.cs @@ -13,7 +13,7 @@ namespace Brio.Game.Posing; -internal unsafe class ModelTransformService : IDisposable +public unsafe class ModelTransformService : IDisposable { public delegate void SetPositionDelegate(StructsGameObject* gameObject, float x, float y, float z); private readonly Hook _setPositionHook = null!; diff --git a/Brio/Game/Posing/PhysicsService.cs b/Brio/Game/Posing/PhysicsService.cs index 19696c63..26b9b674 100644 --- a/Brio/Game/Posing/PhysicsService.cs +++ b/Brio/Game/Posing/PhysicsService.cs @@ -27,128 +27,70 @@ using Brio.Game.GPose; using Dalamud.Game; +using Dalamud.Hooking; using Dalamud.Plugin.Services; using System; -using System.Diagnostics; -using System.Runtime.InteropServices; namespace Brio.Game.Posing; -internal unsafe partial class PhysicsService : IDisposable +public unsafe partial class PhysicsService : IDisposable { private readonly GPoseService _gPoseService; private readonly IFramework _framework; - // + private unsafe delegate void HandlePhysicsDelegate(IntPtr arg1, short arg2, IntPtr arg3, char arg4, char arg5); + private readonly Hook _handlePhysicsDelegate = null!; - const byte NOP = 0x90; public bool IsFreezeEnabled { get; private set; } = false; - // - - private readonly IntPtr freezeSkeletonPhysics1; - private readonly IntPtr freezeSkeletonPhysics2; - - private readonly byte[] originalFreezeBytes1; - private readonly byte[] originalFreezeBytes2; - - private readonly byte[] nopFreezeBytes1; - private readonly byte[] nopFreezeBytes2; - - public PhysicsService(ISigScanner scanner, IFramework framework, GPoseService gPoseService) + public PhysicsService(ISigScanner scanner, IFramework framework, GPoseService gPoseService, IGameInteropProvider hooking) { _gPoseService = gPoseService; _framework = framework; - // This signature is from Anamnesis (https://github.com/imchillin/Anamnesis) - // Found in AddressService.cs on line 159 - SkeletonFreezePhysics (1/2/3) - string freezePhysicsAddress = "0F 11 48 10 41 0F 10 44 24 ?? 0F 11 40 20 48 8B 46 28"; - - var freezePhysics = scanner.ScanText(freezePhysicsAddress); - - freezeSkeletonPhysics1 = freezePhysics; - freezeSkeletonPhysics2 = freezePhysics - 0x9; - _framework.Update += OnFrameworkUpdate; - (originalFreezeBytes1, originalFreezeBytes2) = FreezeReadBytes(); - - nopFreezeBytes1 = [ - NOP, - NOP, - NOP, - NOP - ]; - - nopFreezeBytes2 = [ - NOP, - NOP, - NOP - ]; - } + // This signature is from Anamnesis (https://github.com/imchillin/Anamnesis) + // Found in AddressService.cs on line 159 - SkeletonFreezePhysics (1/2/3) + //var oldFreezePhysicsAddress = "0F 11 48 10 41 0F 10 44 24 ?? 0F 11 40 20 48 8B 46 28"; - public (byte[], byte[]) FreezeReadBytes() - { - return ([ - Marshal.ReadByte(freezeSkeletonPhysics1, 0), - Marshal.ReadByte(freezeSkeletonPhysics1, 1), - Marshal.ReadByte(freezeSkeletonPhysics1, 2), - Marshal.ReadByte(freezeSkeletonPhysics1, 3) - ], [ - Marshal.ReadByte(freezeSkeletonPhysics2, 0), - Marshal.ReadByte(freezeSkeletonPhysics2, 1), - Marshal.ReadByte(freezeSkeletonPhysics2, 2) - ]); + // Thank you Winter! + var handlePhysicsSig = "E9 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 41 ?? ?? ?? 4C ?? ?? 45 ?? ?? 48 ?? ?? ?? ?? ?? ?? 41"; // e9 2d e0 09 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 41 0f b6 c0 4c 8b d1 45 8b c8 48 69 c8 20 02 00 00 + _handlePhysicsDelegate = hooking.HookFromAddress(scanner.ScanText(handlePhysicsSig), HandlePhysicsDetour); + _handlePhysicsDelegate.Enable(); } - public bool FreezeToggle() => IsFreezeEnabled ? FreezeRevert() : FreezeEnable(); - - public bool FreezeRevert() + public unsafe void HandlePhysicsDetour(IntPtr arg1, short arg2, IntPtr arg3, char arg4, char arg5) { - IsFreezeEnabled = false; - - try - { - using Process currentProcess = Process.GetCurrentProcess(); - - WriteProcessMemory(currentProcess.Handle, freezeSkeletonPhysics1, originalFreezeBytes1, originalFreezeBytes1.Length, out _); - - WriteProcessMemory(currentProcess.Handle, freezeSkeletonPhysics2, originalFreezeBytes2, originalFreezeBytes2.Length, out _); - } - catch(Exception ex) + if(IsFreezeEnabled) { - Brio.Log.Fatal($"Brio encountered Fatal Error, FreezeRevert faild: {ex}"); + return; } - return IsFreezeEnabled; + _handlePhysicsDelegate.Original(arg1, arg2, arg3, arg4, arg5); } - public bool FreezeEnable() - { - using Process currentProcess = Process.GetCurrentProcess(); - - WriteProcessMemory(currentProcess.Handle, freezeSkeletonPhysics1, nopFreezeBytes1, nopFreezeBytes1.Length, out _); + public bool FreezeToggle() => IsFreezeEnabled ? FreezeRevert() : FreezeEnable(); - WriteProcessMemory(currentProcess.Handle, freezeSkeletonPhysics2, nopFreezeBytes2, nopFreezeBytes2.Length, out _); + public bool FreezeRevert() => IsFreezeEnabled = false; + public bool FreezeEnable() => IsFreezeEnabled = true; - return IsFreezeEnabled = true; + private void OnFrameworkUpdate(IFramework framework) + { + if(IsFreezeEnabled && _gPoseService.IsGPosing == false) + { + FreezeRevert(); + } } public void Dispose() { if(IsFreezeEnabled) + { FreezeRevert(); + } _framework.Update -= OnFrameworkUpdate; + _handlePhysicsDelegate.Dispose(); } - - private void OnFrameworkUpdate(IFramework framework) - { - if(IsFreezeEnabled && _gPoseService.IsGPosing == false) - FreezeRevert(); - } - - [LibraryImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten); } diff --git a/Brio/Game/Posing/PoseImporter.cs b/Brio/Game/Posing/PoseImporter.cs index 4350aba4..8432132d 100644 --- a/Brio/Game/Posing/PoseImporter.cs +++ b/Brio/Game/Posing/PoseImporter.cs @@ -4,7 +4,7 @@ namespace Brio.Game.Posing; -internal class PoseImporter(PoseFile poseFile, PoseImporterOptions options, bool expressionPhase = false) +public class PoseImporter(PoseFile poseFile, PoseImporterOptions options, bool expressionPhase = false) { public void ApplyBone(Bone bone, BonePoseInfo poseInfo) { @@ -63,7 +63,7 @@ public void ApplyBone(Bone bone, BonePoseInfo poseInfo) } } -internal class PoseImporterOptions(BoneFilter filter, TransformComponents transformComponents, bool applyModelTransform) +public class PoseImporterOptions(BoneFilter filter, TransformComponents transformComponents, bool applyModelTransform) { public BoneFilter BoneFilter { get; set; } = filter; public TransformComponents TransformComponents { get; set; } = transformComponents; diff --git a/Brio/Game/Posing/PoseInfo.cs b/Brio/Game/Posing/PoseInfo.cs index 80de69e8..6d90d001 100644 --- a/Brio/Game/Posing/PoseInfo.cs +++ b/Brio/Game/Posing/PoseInfo.cs @@ -7,7 +7,7 @@ namespace Brio.Game.Posing; -internal class PoseInfo +public class PoseInfo { private readonly Dictionary _poses = []; @@ -58,7 +58,7 @@ public PoseInfo Clone() } } -internal class BonePoseInfo(BonePoseInfoId id, PoseInfo parent) +public class BonePoseInfo(BonePoseInfoId id, PoseInfo parent) { public BonePoseInfoId Id { get; } = id; public PoseInfo Parent { get; } = parent; @@ -178,7 +178,7 @@ private int GetTransformIndex(TransformComponents components, BoneIKInfo ikInfo, } } -internal enum PoseInfoSlot +public enum PoseInfoSlot { Character, MainHand, @@ -187,14 +187,14 @@ internal enum PoseInfoSlot Unknown } -internal enum PoseMirrorMode +public enum PoseMirrorMode { None, Mirror, Copy } -internal record struct BonePoseInfoId(string BoneName, int Partial, PoseInfoSlot Slot) +public record struct BonePoseInfoId(string BoneName, int Partial, PoseInfoSlot Slot) { public override readonly string ToString() => $"{BoneName}/{Partial}/{(int)Slot}"; @@ -215,9 +215,9 @@ internal record struct BonePoseInfoId(string BoneName, int Partial, PoseInfoSlot return null; } } -internal record struct BonePoseTransformInfo(TransformComponents PropagateComponents, BoneIKInfo IKInfo, Transform Transform); +public record struct BonePoseTransformInfo(TransformComponents PropagateComponents, BoneIKInfo IKInfo, Transform Transform); -internal struct BoneIKInfo +public struct BoneIKInfo { public bool Enabled = false; diff --git a/Brio/Game/Posing/PosingSelectionType.cs b/Brio/Game/Posing/PosingSelectionType.cs index 396a7d5f..0e1e771b 100644 --- a/Brio/Game/Posing/PosingSelectionType.cs +++ b/Brio/Game/Posing/PosingSelectionType.cs @@ -5,7 +5,7 @@ namespace Brio.Game.Posing; [GenerateOneOf] -internal partial class PosingSelectionType : OneOfBase +public partial class PosingSelectionType : OneOfBase { public static None None { get; } = new None(); public static ModelTransformSelection ModelTransform { get; } = new(); @@ -56,4 +56,4 @@ public override bool Equals(object? obj) public override int GetHashCode() => UniqueId.GetHashCode(); } -internal record struct ModelTransformSelection(); +public record struct ModelTransformSelection(); diff --git a/Brio/Game/Posing/PosingService.cs b/Brio/Game/Posing/PosingService.cs index fa55c16d..b6415551 100644 --- a/Brio/Game/Posing/PosingService.cs +++ b/Brio/Game/Posing/PosingService.cs @@ -3,7 +3,7 @@ namespace Brio.Game.Posing; -internal class PosingService +public class PosingService { public PosingOperation Operation { get; set; } = PosingOperation.Rotate; @@ -28,9 +28,11 @@ internal class PosingService public PosingService() { OverlayFilter = new BoneFilter(this); + OverlayFilter.DisableCategory("ex"); DefaultImporterOptions = new PoseImporterOptions(new BoneFilter(this), TransformComponents.Rotation, false); DefaultImporterOptions.BoneFilter.DisableCategory("weapon"); + DefaultImporterOptions.BoneFilter.DisableCategory("ex"); DefaultIPCImporterOptions = new PoseImporterOptions(new BoneFilter(this), TransformComponents.All, false); @@ -40,16 +42,20 @@ public PosingService() BodyOptions.BoneFilter.DisableCategory("weapon"); BodyOptions.BoneFilter.DisableCategory("head"); BodyOptions.BoneFilter.DisableCategory("ears"); + BodyOptions.BoneFilter.DisableCategory("hair"); BodyOptions.BoneFilter.DisableCategory("face"); BodyOptions.BoneFilter.DisableCategory("eyes"); BodyOptions.BoneFilter.DisableCategory("lips"); BodyOptions.BoneFilter.DisableCategory("jaw"); BodyOptions.BoneFilter.DisableCategory("head"); + BodyOptions.BoneFilter.DisableCategory("legacy"); + BodyOptions.BoneFilter.DisableCategory("ex"); ExpressionOptions = new PoseImporterOptions(new BoneFilter(this), TransformComponents.All, false); ExpressionOptions.BoneFilter.DisableAll(); ExpressionOptions.BoneFilter.EnableCategory("head"); ExpressionOptions.BoneFilter.EnableCategory("ears"); + ExpressionOptions.BoneFilter.EnableCategory("hair"); ExpressionOptions.BoneFilter.EnableCategory("face"); ExpressionOptions.BoneFilter.EnableCategory("eyes"); ExpressionOptions.BoneFilter.EnableCategory("lips"); @@ -59,15 +65,18 @@ public PosingService() ExpressionOptions2.BoneFilter.DisableAll(); ExpressionOptions2.BoneFilter.EnableCategory("head"); } + + public PoseImporterOptions GetNewPoseImporterOptions(TransformComponents transformComponents, bool applyModelTransform) + => new PoseImporterOptions(new BoneFilter(this), transformComponents, applyModelTransform); } -internal enum PosingCoordinateMode +public enum PosingCoordinateMode { Local, World } -internal enum PosingOperation +public enum PosingOperation { Translate, Rotate, @@ -75,7 +84,7 @@ internal enum PosingOperation Universal } -internal static class PosingExtensions +public static class PosingExtensions { public static MODE AsGizmoMode(this PosingCoordinateMode mode) => mode switch { diff --git a/Brio/Game/Posing/SkeletonService.cs b/Brio/Game/Posing/SkeletonService.cs index e669caef..e112e8d5 100644 --- a/Brio/Game/Posing/SkeletonService.cs +++ b/Brio/Game/Posing/SkeletonService.cs @@ -21,7 +21,7 @@ namespace Brio.Game.Posing; -internal unsafe class SkeletonService : IDisposable +public unsafe class SkeletonService : IDisposable { public delegate void SkeletonUpdateEvent(); public event SkeletonUpdateEvent? SkeletonUpdateStart; diff --git a/Brio/Game/Posing/Skeletons/Bone.cs b/Brio/Game/Posing/Skeletons/Bone.cs index 7a35bc7f..73b15810 100644 --- a/Brio/Game/Posing/Skeletons/Bone.cs +++ b/Brio/Game/Posing/Skeletons/Bone.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Posing.Skeletons; -internal class Bone(int index, Skeleton skeleton, PartialSkeleton partial) +public class Bone(int index, Skeleton skeleton, PartialSkeleton partial) { public int Index = index; public string Name = null!; diff --git a/Brio/Game/Posing/Skeletons/PartialSkeleton.cs b/Brio/Game/Posing/Skeletons/PartialSkeleton.cs index 4c699bd7..2205311f 100644 --- a/Brio/Game/Posing/Skeletons/PartialSkeleton.cs +++ b/Brio/Game/Posing/Skeletons/PartialSkeleton.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Posing.Skeletons; -internal unsafe class PartialSkeleton(Skeleton skeleton, int id) +public unsafe class PartialSkeleton(Skeleton skeleton, int id) { public int Id { get; } = id; diff --git a/Brio/Game/Posing/Skeletons/Skeleton.cs b/Brio/Game/Posing/Skeletons/Skeleton.cs index ef82f2e8..6bc9427a 100644 --- a/Brio/Game/Posing/Skeletons/Skeleton.cs +++ b/Brio/Game/Posing/Skeletons/Skeleton.cs @@ -8,7 +8,7 @@ namespace Brio.Game.Posing.Skeletons; -internal class Skeleton : IDisposable +public class Skeleton : IDisposable { public List Partials { get; } = []; @@ -191,7 +191,7 @@ public void Dispose() } [Flags] -internal enum CacheTypes +public enum CacheTypes { None = 0, LastTransform = 1 << 0, @@ -199,7 +199,7 @@ internal enum CacheTypes All = LastTransform | LastRawTransform, } -internal enum SkeletonType +public enum SkeletonType { Character, MainHandWeapon, diff --git a/Brio/Game/Scene/SceneService.cs b/Brio/Game/Scene/SceneService.cs index dc73acc8..3240a441 100644 --- a/Brio/Game/Scene/SceneService.cs +++ b/Brio/Game/Scene/SceneService.cs @@ -1,12 +1,16 @@ using Brio.Capabilities.Actor; using Brio.Capabilities.Posing; +using Brio.Capabilities.World; using Brio.Config; using Brio.Entities; using Brio.Entities.Actor; using Brio.Entities.Core; +using Brio.Entities.World; using Brio.Files; +using Brio.Game.Actor; using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; +using Brio.Game.Camera; using Brio.Game.Core; using Brio.Game.Posing; using Dalamud.Plugin.Services; @@ -14,13 +18,15 @@ namespace Brio.Game.Scene; -internal class SceneService(EntityManager _entityManager, PosingService _posingService, IClientState _clientState, IFramework _framework) +public class SceneService(EntityManager _entityManager, VirtualCameraManager _virtualCameraManager, PosingService _posingService, ActorSpawnService _actorSpawnService, IClientState _clientState, IFramework _framework) { - internal static SceneFile GenerateSceneFile(EntityManager entityManager) + public bool IsLoading { get; private set; } + + public SceneFile GenerateSceneFile() { SceneFile sceneFile = new(); - var entity = entityManager.GetEntity("actorContainer")!; + var entity = _entityManager.GetEntity("actorContainer")!; foreach(var child in entity.Children) { @@ -30,34 +36,122 @@ internal static SceneFile GenerateSceneFile(EntityManager entityManager) } } + foreach(var camera in _virtualCameraManager.GetAllCameras()) + { + sceneFile.GameCameras.Add(new GameCameraFile { Camera = camera.VirtualCamera, CameraType = camera.CameraType }); + } + + var environmentEntity = _entityManager.GetEntity("environment"); + + if(environmentEntity is not null) + { + var tc = environmentEntity.GetCapability(); + var wc = environmentEntity.GetCapability(); + var wrc = environmentEntity.GetCapability(); + sceneFile.EnvironmentData = new EnvironmentData + { + CurrentWeather = wc.WeatherService.CurrentWeather, + IsTimeFrozen = tc.TimeService.IsTimeFrozen, + EorzeaTime = tc.TimeService.EorzeaTime, + DayOfMonth = tc.TimeService.DayOfMonth, + MinuteOfDay = tc.TimeService.MinuteOfDay, + IsWaterFrozen = wrc.WorldRenderingService.IsWaterFrozen + }; + } + return sceneFile; } - internal unsafe void LoadScene(SceneFile sceneFile) + public unsafe void LoadScene(SceneFile sceneFile, bool destroyAll = false) { + IsLoading = true; + ActorContainerEntity actorContainerEntity = _entityManager.GetEntity("actorContainer")!; var actorCapability = actorContainerEntity.GetCapability(); - if(ConfigurationService.Instance.Configuration.SceneDestoryActorsBeforeImport) + if(ConfigurationService.Instance.Configuration.SceneDestoryActorsBeforeImport || destroyAll) { actorCapability.DestroyAll(); + _virtualCameraManager.DestroyAll(); } foreach(ActorFile actorFile in sceneFile.Actors) { - var (actorId, actor) = actorCapability.CreateCharacter(actorFile.HasChild, false, forceSpawnActorWithoutCompanion: !actorFile.HasChild); + if(actorFile.IsProp) + { + var (actorId, actor) = actorCapability.CreateProp(false); + + _framework.RunUntilSatisfied( + () => actor.Native()->IsReadyToDraw(), + (__) => + { + _ = LoadProp(actorId, actorFile); + }, + 100, + dontStartFor: 2 + ); + } + else + { + var (actorId, actor) = actorCapability.CreateCharacter(actorFile.HasChild, false, forceSpawnActorWithoutCompanion: !actorFile.HasChild); + + _framework.RunUntilSatisfied( + () => actor.Native()->IsReadyToDraw(), + (__) => + { + _ = ApplyDataToActor(actorId, actorFile); + }, + 100, + dontStartFor: 2 + ); + } + } - _framework.RunUntilSatisfied( - () => actor.Native()->IsReadyToDraw(), - (__) => - { - _ = ApplyDataToActor(actorId, actorFile); - }, - 100, - dontStartFor: 2 - ); + foreach(GameCameraFile item in sceneFile.GameCameras) + { + _virtualCameraManager.CreateCamera(item.CameraType, false, false, item.Camera); + } + + if(sceneFile.EnvironmentData is not null) + { + var environmentEntity = _entityManager.GetEntity("environment")!; + var tc = environmentEntity.GetCapability(); + var wc = environmentEntity.GetCapability(); + var wrc = environmentEntity.GetCapability(); + + wc.WeatherService.CurrentWeather = sceneFile.EnvironmentData.CurrentWeather; + tc.TimeService.IsTimeFrozen = sceneFile.EnvironmentData.IsTimeFrozen; + tc.TimeService.EorzeaTime = sceneFile.EnvironmentData.EorzeaTime; + tc.TimeService.DayOfMonth = sceneFile.EnvironmentData.DayOfMonth; + tc.TimeService.MinuteOfDay = sceneFile.EnvironmentData.MinuteOfDay; + wrc.WorldRenderingService.IsWaterFrozen = sceneFile.EnvironmentData.IsWaterFrozen; } + + _framework.RunOnTick(() => + { + IsLoading = false; + }, delayTicks: 250); + } + + private async Task LoadProp(EntityId actorId, ActorFile actorFile) + { + var attachedActor = _entityManager.GetEntity(actorId)!; + var modelCapability = attachedActor.GetCapability(); + var appearanceCapability = attachedActor.GetCapability(); + + await _framework.RunOnTick(async () => + { + if(actorFile.PropData is not null) + modelCapability.Transform += actorFile.PropData.PropTransformDifference; + + await appearanceCapability.SetAppearance(actorFile.AnamnesisCharaFile, AppearanceImportOptions.Weapon); + + await _framework.RunOnTick(() => + { + appearanceCapability.AttachWeapon(); + }, delayTicks: 10); + }, delayTicks: 2); } private async Task ApplyDataToActor(EntityId actorId, ActorFile actorFile) @@ -82,7 +176,7 @@ await _framework.RunOnTick(async () => mountPose = true; if(mountPose == false) - posingCapability.ImportPose(actorFile.PoseFile, null, asScene: true); + posingCapability.ImportPose(actorFile.PoseFile, asScene: true); if(attachedActor.HasCapability() == true && actorFile.HasChild && actorFile.Child is not null) { @@ -98,15 +192,15 @@ await _framework.RunOnTick(() => if(companionEntity is not null && companionEntity.TryGetCapability(out var posingCapability)) { - posingCapability.ImportPose(actorFile.Child.PoseFile, null, asScene: true, freezeOnLoad: true); + posingCapability.ImportPose(actorFile.Child.PoseFile, asScene: true, freezeOnLoad: true); } } if(mountPose == true) - posingCapability.ImportPose(actorFile.PoseFile, null, asScene: true); + posingCapability.ImportPose(actorFile.PoseFile, asScene: true); }); } - }, delayTicks: 10); // I dont like having to-do set delayTicks to this but I dont think I have another way without rework + }, delayTicks: 10); // I don't like having to set delayTicks to this but I don't think I have another way without more rework }); } } diff --git a/Brio/Game/Types/ActionTimelineTypes.cs b/Brio/Game/Types/ActionTimelineTypes.cs index f954ecab..180cdd8c 100644 --- a/Brio/Game/Types/ActionTimelineTypes.cs +++ b/Brio/Game/Types/ActionTimelineTypes.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Types; [GenerateOneOf] -internal partial class ActionTimelineUnion : OneOfBase +public partial class ActionTimelineUnion : OneOfBase { public static implicit operator ActionTimelineUnion(ActionTimelineId actionTimelineId) { @@ -17,7 +17,7 @@ public static implicit operator ActionTimelineUnion(ActionTimelineId actionTimel } } -internal record struct ActionTimelineId(ushort Id) +public record struct ActionTimelineId(ushort Id) { public static ActionTimelineId None { get; } = new(0); diff --git a/Brio/Game/Types/ActorAppearanceTypes.cs b/Brio/Game/Types/ActorAppearanceTypes.cs index df545b1e..8c28c535 100644 --- a/Brio/Game/Types/ActorAppearanceTypes.cs +++ b/Brio/Game/Types/ActorAppearanceTypes.cs @@ -8,7 +8,7 @@ namespace Brio.Game.Types; [GenerateOneOf] -internal partial class ActorAppearanceUnion : OneOfBase +public partial class ActorAppearanceUnion : OneOfBase { public static implicit operator ActorAppearance(ActorAppearanceUnion union) => union.Match( bnpc => ActorAppearance.FromBNpc(bnpc), diff --git a/Brio/Game/Types/CompanionTypes.cs b/Brio/Game/Types/CompanionTypes.cs index 64613ee1..a0600ead 100644 --- a/Brio/Game/Types/CompanionTypes.cs +++ b/Brio/Game/Types/CompanionTypes.cs @@ -1,12 +1,13 @@ using Brio.Resources; using Lumina.Excel.Sheets; +using MessagePack; using OneOf; using OneOf.Types; namespace Brio.Game.Types; [GenerateOneOf] -internal partial class CompanionRowUnion : OneOfBase +public partial class CompanionRowUnion : OneOfBase { public static implicit operator CompanionRowUnion(CompanionContainer container) { @@ -25,7 +26,7 @@ public static implicit operator CompanionRowUnion(CompanionContainer container) } -internal enum CompanionKind +public enum CompanionKind { Companion, Mount, @@ -33,7 +34,8 @@ internal enum CompanionKind None } -internal record struct CompanionContainer(CompanionKind Kind, ushort Id) +[MessagePackObject(keyAsPropertyName: true)] +public record struct CompanionContainer(CompanionKind Kind, ushort Id) { public static CompanionContainer None { get; } = new CompanionContainer(CompanionKind.None, 0); diff --git a/Brio/Game/Types/DyeTypes.cs b/Brio/Game/Types/DyeTypes.cs index 5225428f..fd02ff47 100644 --- a/Brio/Game/Types/DyeTypes.cs +++ b/Brio/Game/Types/DyeTypes.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Types; [GenerateOneOf] -internal partial class DyeUnion : OneOfBase +public partial class DyeUnion : OneOfBase { public static implicit operator DyeUnion(DyeId dyeId) { @@ -17,7 +17,7 @@ public static implicit operator DyeUnion(DyeId dyeId) } } -internal record struct DyeId(byte Id) +public record struct DyeId(byte Id) { public static DyeId None { get; } = new(0); diff --git a/Brio/Game/Types/FacewearTypes.cs b/Brio/Game/Types/FacewearTypes.cs index 9482b68d..8f0258a3 100644 --- a/Brio/Game/Types/FacewearTypes.cs +++ b/Brio/Game/Types/FacewearTypes.cs @@ -6,7 +6,7 @@ namespace Brio.Game.Types; [GenerateOneOf] -internal partial class FacewearUnion : OneOfBase +public partial class FacewearUnion : OneOfBase { public static implicit operator FacewearUnion(FacewearId facewearId) { @@ -17,7 +17,7 @@ public static implicit operator FacewearUnion(FacewearId facewearId) } } -internal record struct FacewearId(byte Id) +public record struct FacewearId(byte Id) { public static FacewearId None { get; } = new(0); diff --git a/Brio/Game/Types/ItemTypes.cs b/Brio/Game/Types/ItemTypes.cs index 3359abcb..9d47d892 100644 --- a/Brio/Game/Types/ItemTypes.cs +++ b/Brio/Game/Types/ItemTypes.cs @@ -5,6 +5,6 @@ namespace Brio.Game.Types; [GenerateOneOf] -internal partial class ItemUnion : OneOfBase +public partial class ItemUnion : OneOfBase { } diff --git a/Brio/Game/Types/WeatherTypes.cs b/Brio/Game/Types/WeatherTypes.cs index cb985713..27393950 100644 --- a/Brio/Game/Types/WeatherTypes.cs +++ b/Brio/Game/Types/WeatherTypes.cs @@ -1,12 +1,13 @@ using Brio.Resources; using Lumina.Excel.Sheets; +using MessagePack; using OneOf; using OneOf.Types; namespace Brio.Game.Types; [GenerateOneOf] -internal partial class WeatherUnion : OneOfBase +public partial class WeatherUnion : OneOfBase { public static implicit operator WeatherUnion(WeatherId weatherId) { @@ -17,7 +18,8 @@ public static implicit operator WeatherUnion(WeatherId weatherId) } } -internal record struct WeatherId(byte Id) +[MessagePackObject(keyAsPropertyName: true)] +public record struct WeatherId(byte Id) { public static WeatherId None { get; } = new(0); diff --git a/Brio/Game/World/FestivalService.cs b/Brio/Game/World/FestivalService.cs index f74c931c..0ed2ce4b 100644 --- a/Brio/Game/World/FestivalService.cs +++ b/Brio/Game/World/FestivalService.cs @@ -11,7 +11,7 @@ namespace Brio.Game.World; -internal unsafe class FestivalService : IDisposable +public unsafe class FestivalService : IDisposable { public const int MaxFestivals = 4; @@ -71,7 +71,7 @@ private void OnFrameworkUpdate(IFramework framework) { var pending = _pendingChanges.Dequeue(); if(pending != null) - InternalApply(pending); + publicApply(pending); } } @@ -126,7 +126,7 @@ public unsafe void ResetFestivals(bool tryThisFrame = false) { if(tryThisFrame) { - InternalApply(_originalState, false); + publicApply(_originalState, false); } else { @@ -137,7 +137,7 @@ public unsafe void ResetFestivals(bool tryThisFrame = false) } } - private void InternalApply(uint[] festivals, bool applyNow = true) + private void publicApply(uint[] festivals, bool applyNow = true) { if(applyNow) { diff --git a/Brio/Game/World/TimeService.cs b/Brio/Game/World/TimeService.cs index 2ec63c32..9c3f9bbe 100644 --- a/Brio/Game/World/TimeService.cs +++ b/Brio/Game/World/TimeService.cs @@ -8,7 +8,7 @@ namespace Brio.Game.World; -internal class TimeService : IDisposable +public class TimeService : IDisposable { public bool IsTimeFrozen { diff --git a/Brio/Game/World/WeatherService.cs b/Brio/Game/World/WeatherService.cs index ac96d2d6..0b29277a 100644 --- a/Brio/Game/World/WeatherService.cs +++ b/Brio/Game/World/WeatherService.cs @@ -15,7 +15,7 @@ namespace Brio.Game.World; -internal class WeatherService : IDisposable +public class WeatherService : IDisposable { public ReadOnlyCollection TerritoryWeatherTable { @@ -98,7 +98,6 @@ public WeatherService(IClientState clientState, GameDataProvider gameDataProvide var twAddress = scanner.ScanText("48 89 5C 24 ?? 55 56 57 48 83 EC ?? 48 8B F9 48 8D 0D"); _updateTerritoryWeatherHook = hooking.HookFromAddress(twAddress, UpdateTerritoryWeatherDetour); - UpdateWeathersForCurrentTerritory(); _clientState.TerritoryChanged += OnTerritoryChanged; diff --git a/Brio/Game/World/WorldRenderingService.cs b/Brio/Game/World/WorldRenderingService.cs index 7eacb987..018a388c 100644 --- a/Brio/Game/World/WorldRenderingService.cs +++ b/Brio/Game/World/WorldRenderingService.cs @@ -7,7 +7,7 @@ namespace Brio.Game.World; -internal class WorldRenderingService : IDisposable +public class WorldRenderingService : IDisposable { private readonly GPoseService _gPoseService; @@ -61,7 +61,7 @@ public void Dispose() _updateWaterRendererHook?.Dispose(); } - internal nint UpdateWaterRenderer(IntPtr a1) + public nint UpdateWaterRenderer(IntPtr a1) { return 0; } diff --git a/Brio/IPC/BrioIPCService.cs b/Brio/IPC/BrioIPCService.cs index 166c7d9b..0f726cd2 100644 --- a/Brio/IPC/BrioIPCService.cs +++ b/Brio/IPC/BrioIPCService.cs @@ -20,7 +20,7 @@ using System.Threading.Tasks; namespace Brio.IPC; -internal class BrioIPCService : IDisposable +public class BrioIPCService : IDisposable { public static readonly (int, int) CurrentApiVersion = (2, 0); @@ -318,13 +318,11 @@ private void DisposeIPC() } return character; - } return null; } - private Task DespawnActorAsync_Impl(IGameObject gameObject) => _framework.RunOnTick(() => DespawnActor(gameObject)); private bool DespawnActor(IGameObject gameObject) { if(_gPoseService.IsGPosing == false) return false; @@ -429,7 +427,7 @@ private unsafe bool LoadFromJson_Impl(IGameObject gameObject, string json, bool } else { - posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: false); + posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: true); } return true; diff --git a/Brio/IPC/CustomizePlusService.cs b/Brio/IPC/CustomizePlusService.cs new file mode 100644 index 00000000..b432bcbc --- /dev/null +++ b/Brio/IPC/CustomizePlusService.cs @@ -0,0 +1,129 @@ + +// From Tuples.cs from "CustomizePlus" https://github.com/Aether-Tools/CustomizePlus + +global using IPCProfileDataTuple = ( + System.Guid UniqueId, + string Name, + string VirtualPath, + System.Collections.Generic.List<(string Name, ushort WorldId, byte CharacterType, ushort CharacterSubType)> Characters, + int Priority, + bool IsEnabled); + +// --------------------------------------------------------------------------------- + +using Brio.Config; +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Plugin; +using Dalamud.Plugin.Ipc; +using System; +using System.Collections.Generic; + +namespace Brio.IPC; + +public class CustomizePlusService : BrioIPC +{ + public override string Name { get; } = "Customize+"; + + public override bool IsAvailable + => CheckStatus() == IPCStatus.Available; + public override bool AllowIntegration + => _configurationService.Configuration.IPC.AllowCustomizePlusIntegration; + + public override int APIMajor => 6; + public override int APIMinor => 0; + + public override (int Major, int Minor) GetAPIVersion() + => _customizeplusApiVersion.InvokeFunc(); + + public override IDalamudPluginInterface GetPluginInterface() + => _pluginInterface; + // + + private readonly ConfigurationService _configurationService; + private readonly IDalamudPluginInterface _pluginInterface; + + private readonly ICallGateSubscriber _customizeplusSetTemporaryProfile; + private readonly ICallGateSubscriber> _customizeplusGetAllProfiles; + private readonly ICallGateSubscriber _customizeplusGetActiveProfileId; + private readonly ICallGateSubscriber _customizeplusGetProfileById; + private readonly ICallGateSubscriber _customizeplusDeleteTemporaryProfile; + private readonly ICallGateSubscriber<(int, int)> _customizeplusApiVersion; + private readonly ICallGateSubscriber _customizeplusIsValid; + + public CustomizePlusService(IDalamudPluginInterface pluginInterface, ConfigurationService configurationService) + { + _pluginInterface = pluginInterface; + _configurationService = configurationService; + + _customizeplusApiVersion = _pluginInterface.GetIpcSubscriber<(int, int)>("CustomizePlus.General.GetApiVersion"); + _customizeplusIsValid = _pluginInterface.GetIpcSubscriber("CustomizePlus.General.IsValid"); + + _customizeplusSetTemporaryProfile = _pluginInterface.GetIpcSubscriber("CustomizePlus.Profile.SetTemporaryProfileOnCharacter"); + _customizeplusDeleteTemporaryProfile = _pluginInterface.GetIpcSubscriber("CustomizePlus.Profile.DeleteTemporaryProfileOnCharacter"); + + _customizeplusGetAllProfiles = _pluginInterface.GetIpcSubscriber>("CustomizePlus.Profile.GetList"); + _customizeplusGetActiveProfileId = _pluginInterface.GetIpcSubscriber("CustomizePlus.Profile.GetActiveProfileIdOnCharacter"); + _customizeplusGetProfileById = _pluginInterface.GetIpcSubscriber("CustomizePlus.Profile.GetByUniqueId"); + + _configurationService.OnConfigurationChanged += OnConfigurationChanged; + OnConfigurationChanged(); + } + + public bool RemoveTemporaryProfile(IGameObject? character) + { + if(IsAvailable == false && character is not null) + return false; + + _customizeplusDeleteTemporaryProfile.InvokeFunc(character!.ObjectIndex); + + return true; + } + + public (string?, Guid?) GetActiveProfile(IGameObject? character) + { + if(IsAvailable == false && character is not null) + return (string.Empty, null); + + var (_, id) = _customizeplusGetActiveProfileId.InvokeFunc(character!.ObjectIndex); + + var data = string.Empty; + if(id != null) + (_, data) = _customizeplusGetProfileById.InvokeFunc(id.Value); + + return (data, id); + } + + public (int, string?) GetProfile(Guid id) + { + if(IsAvailable == false && id != default) + return (255, string.Empty); + + return _customizeplusGetProfileById.InvokeFunc(id); + } + + public bool SetProfile(IGameObject? character, string profileData) + { + if(IsAvailable == false && string.IsNullOrEmpty(profileData) && character is not null) + return false; + + _customizeplusSetTemporaryProfile.InvokeFunc(character!.ObjectIndex, profileData); + + return true; + } + + public IEnumerable GetProfiles() + { + if(IsAvailable == false) + return []; + + return _customizeplusGetAllProfiles.InvokeFunc(); + } + + private void OnConfigurationChanged() + => CheckStatus(); + + public override void Dispose() + { + _configurationService.OnConfigurationChanged -= OnConfigurationChanged; + } +} diff --git a/Brio/IPC/GlamourerService.cs b/Brio/IPC/GlamourerService.cs index 873084f4..fa4d34c3 100644 --- a/Brio/IPC/GlamourerService.cs +++ b/Brio/IPC/GlamourerService.cs @@ -1,125 +1,107 @@ using Brio.Config; using Brio.Game.Actor; -using Brio.Game.GPose; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin; using Dalamud.Plugin.Services; using System; -using System.Linq; +using System.Collections.Generic; using System.Threading.Tasks; namespace Brio.IPC; -internal class GlamourerService : IDisposable +public class GlamourerService : BrioIPC { - public bool IsGlamourerAvailable { get; private set; } = false; + public override string Name { get; } = "Glamourer"; - private const int GlamourerApiMajor = 1; - private const int GlamourerApiMinor = 1; + public override bool IsAvailable + => CheckStatus() == IPCStatus.Available; + + public override bool AllowIntegration + => _configurationService.Configuration.IPC.AllowGlamourerIntegration; + + public override int APIMajor => 1; + public override int APIMinor => 4; + + public override (int Major, int Minor) GetAPIVersion() + => _glamourerApiVersion.Invoke(); + + public override IDalamudPluginInterface GetPluginInterface() + => _pluginInterface; + + // - private readonly IDalamudPluginInterface _pluginInterface; private readonly ConfigurationService _configurationService; - private readonly GPoseService _gPoseService; - private readonly IFramework _framework; + private readonly IDalamudPluginInterface _pluginInterface; private readonly ActorRedrawService _redrawService; - private readonly PenumbraService _penumbraService; + private readonly IFramework _framework; + + // + // private readonly Glamourer.Api.Helpers.EventSubscriber _glamourerInitializedSubscriber; - private readonly Glamourer.Api.IpcSubscribers.ApiVersion _glamourerApiVersions; private readonly Glamourer.Api.IpcSubscribers.RevertState _glamourerRevertCharacter; + private readonly Glamourer.Api.IpcSubscribers.ApiVersion _glamourerApiVersion; private readonly Glamourer.Api.IpcSubscribers.GetState _glamourerGetState; - private readonly uint UnLockCode = 0x6D617265; // From MareSynchronos's IpcCallerGlamourer.cs + private readonly Glamourer.Api.IpcSubscribers.GetDesignList _glamourerGetDesignList; + private readonly Glamourer.Api.IpcSubscribers.ApplyDesign _glamourerApplyDesign; + + // + + public readonly uint BrioKey = 0x11625; + private readonly uint _unlock = 0x6D617265; // From MareSynchronos's IpcCallerGlamourer.cs - public GlamourerService(IDalamudPluginInterface pluginInterface, ConfigurationService configurationService, GPoseService gPoseService, IFramework framework, PenumbraService penumbraService, ActorRedrawService redrawService) + public GlamourerService(IDalamudPluginInterface pluginInterface, ConfigurationService configurationService, IFramework framework, ActorRedrawService redrawService) { _pluginInterface = pluginInterface; _configurationService = configurationService; - _gPoseService = gPoseService; _framework = framework; _redrawService = redrawService; - _penumbraService = penumbraService; - _glamourerInitializedSubscriber = Glamourer.Api.IpcSubscribers.Initialized.Subscriber(pluginInterface, RefreshGlamourerStatus); + _glamourerInitializedSubscriber = Glamourer.Api.IpcSubscribers.Initialized.Subscriber(pluginInterface, OnConfigurationChanged); - _glamourerApiVersions = new Glamourer.Api.IpcSubscribers.ApiVersion(pluginInterface); + _glamourerApiVersion = new Glamourer.Api.IpcSubscribers.ApiVersion(pluginInterface); _glamourerRevertCharacter = new Glamourer.Api.IpcSubscribers.RevertState(pluginInterface); _glamourerGetState = new Glamourer.Api.IpcSubscribers.GetState(pluginInterface); - RefreshGlamourerStatus(); - - _configurationService.OnConfigurationChanged += RefreshGlamourerStatus; - _gPoseService.OnGPoseStateChange += OnGPoseStateChange; - } - - public void RefreshGlamourerStatus() - { - if(_configurationService.Configuration.IPC.AllowGlamourerIntegration) - { - IsGlamourerAvailable = ConnectToGlamourer(); - } - else - { - IsGlamourerAvailable = false; - } - - bool ConnectToGlamourer() - { - try - { - bool glamourerInstalled = _pluginInterface.InstalledPlugins.Any(x => x.Name == "Glamourer" && x.IsLoaded == true); - if(!glamourerInstalled) - { - Brio.Log.Debug("Glamourer not present"); - return false; - } - - var (major, minor) = _glamourerApiVersions.Invoke(); - if(major != GlamourerApiMajor || minor < GlamourerApiMinor) - { - Brio.Log.Warning($"Glamourer API mismatch, found v{major}.{minor}"); - return false; - } + _glamourerGetDesignList = new Glamourer.Api.IpcSubscribers.GetDesignList(pluginInterface); + _glamourerApplyDesign = new Glamourer.Api.IpcSubscribers.ApplyDesign(pluginInterface); + OnConfigurationChanged(); - Brio.Log.Debug("Glamourer integration initialized"); - - return true; - } - catch(Exception ex) - { - Brio.Log.Debug(ex, "Glamourer initialize error"); - return false; - } - } + _configurationService.OnConfigurationChanged += OnConfigurationChanged; } - public bool CheckForLock(ICharacter? character) + public bool CheckForLock(IGameObject? character) { - if(IsGlamourerAvailable == false || character is null) + if(IsAvailable == false || character is null) return false; - var success = _glamourerGetState.Invoke(character!.ObjectIndex); + var (key, _) = _glamourerGetState.Invoke(character!.ObjectIndex); - Brio.Log.Warning("Glamourer CheckForLock... " + success.Item1); + Brio.Log.Verbose("Glamourer CheckForLock... " + key); - return success.Item1 == Glamourer.Api.Enums.GlamourerApiEc.InvalidKey; + return key == Glamourer.Api.Enums.GlamourerApiEc.InvalidKey; } - public Task UnlockAndRevertCharacter(ICharacter? character) + public Task UnlockAndRevertCharacter(IGameObject? character) { - if(IsGlamourerAvailable == false || character is null) + if(IsAvailable == false || character is null) return Task.CompletedTask; - Brio.Log.Warning("Starting glamourer UnlockAndRevert..."); + Brio.Log.Debug("Starting glamourer UnlockAndRevert..."); - var success = _glamourerRevertCharacter.Invoke(character!.ObjectIndex, UnLockCode); + var success = _glamourerRevertCharacter.Invoke(character!.ObjectIndex, _unlock); if(success == Glamourer.Api.Enums.GlamourerApiEc.InvalidKey) { - Brio.Log.Fatal("Glamourer revert failed! Please report this to the Brio Devs!"); - return Task.CompletedTask; + var success2 = _glamourerRevertCharacter.Invoke(character!.ObjectIndex, BrioKey); + if(success2 == Glamourer.Api.Enums.GlamourerApiEc.InvalidKey) + { + Brio.Log.Fatal("Glamourer revert failed! Please report this to the Brio Devs!"); + return Task.CompletedTask; + } } return _framework.RunOnTick(async () => @@ -127,41 +109,61 @@ public Task UnlockAndRevertCharacter(ICharacter? character) await _redrawService.WaitForDrawing(character!); Brio.Log.Debug("Glamourer revert complete"); }, delayTicks: 5); - } - public Task RevertCharacter(ICharacter? character) + public Task RevertCharacter(IGameObject? character) { - if(IsGlamourerAvailable == false || character is null) + if(IsAvailable == false || character is null) return Task.CompletedTask; - Brio.Log.Warning("Starting glamourer Revert..."); + Brio.Log.Debug("Starting glamourer Revert..."); var success = _glamourerRevertCharacter.Invoke(character!.ObjectIndex); if(success == Glamourer.Api.Enums.GlamourerApiEc.InvalidKey) { + Brio.Log.Info("Glamourer character was locked.."); UnlockAndRevertCharacter(character); return Task.CompletedTask; } - return _framework.RunOnTick(async () => + if(success == Glamourer.Api.Enums.GlamourerApiEc.Success) { - await _redrawService.WaitForDrawing(character!); - Brio.Log.Debug("Glamourer revert complete"); - }, delayTicks: 5); + Brio.Log.Debug("Glamourer revert Started"); + return _framework.RunOnTick(async () => + { + await _redrawService.WaitForDrawing(character!); + Brio.Log.Debug("Glamourer revert complete"); + }, delayTicks: 5); + } + return Task.CompletedTask; } - private void OnGPoseStateChange(bool newState) + public Dictionary? GetDesignList() { - RefreshGlamourerStatus(); + if(IsAvailable == false) + return null; + + return _glamourerGetDesignList.Invoke(); } - public void Dispose() + public bool ApplyDesign(Guid design, IGameObject? character) + { + if(IsAvailable == false || character is null) + return false; + + _glamourerApplyDesign.Invoke(design, character!.ObjectIndex); + + return true; + } + + private void OnConfigurationChanged() + => CheckStatus(); + + public override void Dispose() { - _configurationService.OnConfigurationChanged -= RefreshGlamourerStatus; - _gPoseService.OnGPoseStateChange -= OnGPoseStateChange; + _configurationService.OnConfigurationChanged -= OnConfigurationChanged; _glamourerInitializedSubscriber.Dispose(); } diff --git a/Brio/IPC/Interface/IBrioIPC.cs b/Brio/IPC/Interface/IBrioIPC.cs new file mode 100644 index 00000000..beb72c29 --- /dev/null +++ b/Brio/IPC/Interface/IBrioIPC.cs @@ -0,0 +1,90 @@ +using Dalamud.Plugin; +using System; +using System.Linq; + +namespace Brio.IPC; + +public interface IBrioIPC : IDisposable +{ + string Name { get; } + bool IsAvailable { get; } + bool AllowIntegration { get; } + + public IPCStatus CheckStatus(bool force = false); + (int Major, int Minor) GetAPIVersion(); + IDalamudPluginInterface GetPluginInterface(); + + int APIMajor { get; } + int APIMinor { get; } +} + +public enum IPCStatus +{ + None = 0, + Available = 1, + Disabled = 2, + NotInstalled = 3, + VersionMismatch = 4, + Error = 5, + + Unavailable = None | Disabled | NotInstalled | VersionMismatch | Error +} + +public abstract class BrioIPC : IBrioIPC +{ + public abstract string Name { get; } + public abstract bool IsAvailable { get; } + public abstract bool AllowIntegration { get; } + + public virtual bool Disabled { get; set; } = false; + + public abstract void Dispose(); + public abstract (int Major, int Minor) GetAPIVersion(); + public abstract IDalamudPluginInterface GetPluginInterface(); + + public abstract int APIMajor { get; } + public abstract int APIMinor { get; } + + TimeSpan _interval = TimeSpan.FromSeconds(10); + DateTime _lastCheckTime = DateTime.MinValue; + IPCStatus _lastIPCStatus = IPCStatus.None; + public IPCStatus CheckStatus(bool force = false) + { + if(force == false) + { + if(AllowIntegration == false || Disabled) + { + return IPCStatus.Disabled; + } + + if(_lastIPCStatus != IPCStatus.None && (DateTime.Now - _lastCheckTime < _interval)) + { + return _lastIPCStatus; + } + } + _lastCheckTime = DateTime.Now; + + try + { + bool installed = GetPluginInterface().InstalledPlugins.Any(x => x.Name == Name && x.IsLoaded == true); + if(!installed) + { + Brio.Log.Debug($"{Name} not present"); + return _lastIPCStatus = IPCStatus.NotInstalled; + } + + var (major, minor) = GetAPIVersion(); + if(major != APIMajor || minor < APIMinor) + { + Brio.Log.Warning($"{Name} API Version mismatch, found v{major}.{minor}"); + return _lastIPCStatus = IPCStatus.VersionMismatch; + } + return _lastIPCStatus = IPCStatus.Available; + } + catch(Exception ex) + { + Brio.Log.Debug(ex, $"{Name} initialize error"); + return _lastIPCStatus = IPCStatus.Error; + } + } +} diff --git a/Brio/IPC/MareService.cs b/Brio/IPC/MareService.cs index d80f3297..eba06467 100644 --- a/Brio/IPC/MareService.cs +++ b/Brio/IPC/MareService.cs @@ -1,54 +1,60 @@ using Brio.Config; +using Brio.Game.Core; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using System; -using System.Linq; +using System.Collections.Generic; namespace Brio.IPC; -internal class MareService : IDisposable +public class MareService : BrioIPC { - public bool IsMareAvailable { get; private set; } = false; + public override string Name { get; } = "Mare Synchronos"; + + public override bool IsAvailable + => CheckStatus() == IPCStatus.Available; + + public override bool AllowIntegration + => _configurationService.Configuration.IPC.AllowMareIntegration; + + public override int APIMajor => 1; + public override int APIMinor => 0; + + public override (int Major, int Minor) GetAPIVersion() + => (1, 0); + + public override IDalamudPluginInterface GetPluginInterface() + => _pluginInterface; + + // + // private readonly IDalamudPluginInterface _pluginInterface; private readonly ConfigurationService _configurationService; + private readonly ObjectMonitorService _objectMonitorService; private readonly ICallGateSubscriber _mareApplyMcdf; + private readonly ICallGateSubscriber> _mareGetHandledAddresses; - public MareService(IDalamudPluginInterface pluginInterface, ConfigurationService configurationService) + public MareService(IDalamudPluginInterface pluginInterface, ObjectMonitorService objectMonitorService, ConfigurationService configurationService) { _pluginInterface = pluginInterface; _configurationService = configurationService; + _objectMonitorService = objectMonitorService; _mareApplyMcdf = pluginInterface.GetIpcSubscriber("MareSynchronos.LoadMcdf"); + _mareGetHandledAddresses = pluginInterface.GetIpcSubscriber>("MareSynchronos.GetHandledAddresses"); - RefreshMareStatus(); - - _configurationService.OnConfigurationChanged += RefreshMareStatus; - } + OnConfigurationChanged(); - public void RefreshMareStatus() - { - if(_configurationService.Configuration.IPC.AllowMareIntegration) - { - IsMareAvailable = ConnectToMare(); - } - else - { - IsMareAvailable = false; - } + _configurationService.OnConfigurationChanged += OnConfigurationChanged; } public bool LoadMcdfAsync(string fileName, IGameObject target) { - RefreshMareStatus(); - - if(IsMareAvailable == false) - { - Brio.Log.Error($"Failed load MCDF file, Mare is not available"); + if(IsAvailable == false || target is null) return false; - } try { @@ -61,31 +67,40 @@ public bool LoadMcdfAsync(string fileName, IGameObject target) } } - private bool ConnectToMare() + public bool HandledByMare(IGameObject obj) { - try - { - bool mareInstalled = _pluginInterface.InstalledPlugins.Any(x => x.Name == "Mare Synchronos" && x.IsLoaded == true); + if(IsAvailable == false || obj is null) + return false; - if(!mareInstalled) - { - Brio.Log.Debug("Mare Synchronos not present"); - return false; - } - Brio.Log.Debug("Mare Synchronos integration initialized"); + Brio.Log.Error($"HandledByMareIPC"); - return true; - } - catch(Exception ex) + var pointers = _mareGetHandledAddresses.InvokeFunc(); + + foreach(var address in pointers) { - Brio.Log.Debug(ex, "Mare Synchronos initialize error"); - return false; + try + { + Brio.Log.Error($"HandledByMareIPC address: {address}"); + + var mareObj = _objectMonitorService.ObjectTable.CreateObjectReference(address); + if(mareObj is not null && mareObj.ObjectIndex == obj.ObjectIndex) + { + return true; + } + } + catch + { + } } + return false; } - public void Dispose() + private void OnConfigurationChanged() + => CheckStatus(); + + public override void Dispose() { - _configurationService.OnConfigurationChanged -= RefreshMareStatus; + _configurationService.OnConfigurationChanged -= OnConfigurationChanged; } } diff --git a/Brio/IPC/PenumbraService.cs b/Brio/IPC/PenumbraService.cs index f19ca155..02cf304c 100644 --- a/Brio/IPC/PenumbraService.cs +++ b/Brio/IPC/PenumbraService.cs @@ -5,115 +5,100 @@ using Penumbra.Api.IpcSubscribers; using System; using System.Collections.Generic; -using System.Linq; namespace Brio.IPC; -internal class PenumbraService : IDisposable +public class PenumbraService : BrioIPC { - public bool IsPenumbraAvailable { get; private set; } = false; + public override string Name { get; } = "Penumbra"; - private const int PenumbraApiMajor = 5; - private const int PenumbraApiMinor = 0; + public override bool IsAvailable + => CheckStatus() == IPCStatus.Available; + + public override bool AllowIntegration + => _configurationService.Configuration.IPC.AllowPenumbraIntegration; + + public override int APIMajor => 5; + public override int APIMinor => 0; + + public override (int Major, int Minor) GetAPIVersion() + => _penumbraApiVersion.Invoke(); + + public override IDalamudPluginInterface GetPluginInterface() + => _pluginInterface; + + // + // - private readonly IDalamudPluginInterface _pluginInterface; private readonly ConfigurationService _configurationService; + private readonly IDalamudPluginInterface _pluginInterface; public delegate void PenumbraRedrawEvent(int gameObjectId); public event PenumbraRedrawEvent? OnPenumbraRedraw; + private readonly EventSubscriber _penumbraRedrawEvent; private readonly EventSubscriber _penumbraInitializedSubscriber; private readonly EventSubscriber _penumbraDisposedSubscriber; - private readonly EventSubscriber _penumbraRedrawEvent; - private readonly ApiVersion _penumbraApiVersion; - private readonly GetCollections _penumbraGetCollections; private readonly SetCollectionForObject _penumbraSetCollectionForObject; private readonly GetCollectionForObject _penumbraGetCollectionForObject; + private readonly GetCollections _penumbraGetCollections; private readonly OpenMainWindow _penumbraOpenMainWindow; + private readonly ApiVersion _penumbraApiVersion; public PenumbraService(IDalamudPluginInterface pluginInterface, ConfigurationService configurationService) { _pluginInterface = pluginInterface; _configurationService = configurationService; - _penumbraInitializedSubscriber = Penumbra.Api.IpcSubscribers.Initialized.Subscriber(pluginInterface, RefreshPenumbraStatus); - _penumbraDisposedSubscriber = Penumbra.Api.IpcSubscribers.Disposed.Subscriber(pluginInterface, RefreshPenumbraStatus); - _penumbraRedrawEvent = Penumbra.Api.IpcSubscribers.GameObjectRedrawn.Subscriber(pluginInterface, HandlePenumbraRedraw); - - _penumbraOpenMainWindow = new Penumbra.Api.IpcSubscribers.OpenMainWindow(pluginInterface); - _penumbraGetCollectionForObject = new Penumbra.Api.IpcSubscribers.GetCollectionForObject(_pluginInterface); - _penumbraSetCollectionForObject = new Penumbra.Api.IpcSubscribers.SetCollectionForObject(_pluginInterface); - _penumbraGetCollections = new Penumbra.Api.IpcSubscribers.GetCollections(_pluginInterface); - _penumbraApiVersion = new Penumbra.Api.IpcSubscribers.ApiVersion(_pluginInterface); - - _configurationService.OnConfigurationChanged += RefreshPenumbraStatus; + _penumbraInitializedSubscriber = Initialized.Subscriber(pluginInterface, OnConfigurationChanged); + _penumbraDisposedSubscriber = Disposed.Subscriber(pluginInterface, OnConfigurationChanged); + _penumbraRedrawEvent = GameObjectRedrawn.Subscriber(pluginInterface, HandlePenumbraRedraw); - RefreshPenumbraStatus(); - } + _penumbraGetCollectionForObject = new GetCollectionForObject(_pluginInterface); + _penumbraSetCollectionForObject = new SetCollectionForObject(_pluginInterface); + _penumbraGetCollections = new GetCollections(_pluginInterface); + _penumbraOpenMainWindow = new OpenMainWindow(pluginInterface); + _penumbraApiVersion = new ApiVersion(_pluginInterface); - public void RefreshPenumbraStatus() - { - if(_configurationService.Configuration.IPC.AllowPenumbraIntegration) - { - IsPenumbraAvailable = ConnectToPenumbra(); - } - else - { - IsPenumbraAvailable = false; - } - - bool ConnectToPenumbra() - { - try - { - bool penumbraInstalled = _pluginInterface.InstalledPlugins.Any(x => x.Name == "Penumbra" && x.IsLoaded == true); - if(penumbraInstalled == false) - { - Brio.Log.Debug("Penumbra not present"); - return false; - } - - var (major, minor) = _penumbraApiVersion.Invoke(); - if(major != PenumbraApiMajor || minor < PenumbraApiMinor) - { - Brio.Log.Warning($"Penumbra API mismatch!, found v{major}.{minor}"); - return false; - } - - Brio.Log.Debug("Penumbra integration initialized"); - - return true; - } - catch(Exception ex) - { - Brio.Log.Error(ex, "Penumbra initialize error"); - return false; - } - } + _configurationService.OnConfigurationChanged += OnConfigurationChanged; + OnConfigurationChanged(); } public void OpenPenumbra() { + if(IsAvailable == false) + return; + _penumbraOpenMainWindow.Invoke(Penumbra.Api.Enums.TabType.Mods); } public string GetCollectionForObject(IGameObject gameObject) { + if(IsAvailable == false || gameObject is null) + return string.Empty; + var (_, _, collection) = _penumbraGetCollectionForObject.Invoke(gameObject.ObjectIndex); return collection.Name; } public Guid SetCollectionForObject(IGameObject gameObject, Guid collectionName) { + if(IsAvailable == false || gameObject is null) + return Guid.Empty; + Brio.Log.Debug($"Setting GameObject {gameObject.ObjectIndex} collection to {collectionName}"); + var (_, oldCollection) = _penumbraSetCollectionForObject.Invoke(gameObject.ObjectIndex, collectionName, true, true); return oldCollection!.Value.Id; // TODO Fix null reference } public Dictionary GetCollections() { + if(IsAvailable == false) + return null!; + return _penumbraGetCollections.Invoke(); } @@ -123,9 +108,12 @@ private void HandlePenumbraRedraw(nint arg1, int arg2) OnPenumbraRedraw?.Invoke(arg2); } - public void Dispose() + private void OnConfigurationChanged() + => CheckStatus(); + + public override void Dispose() { - _configurationService.OnConfigurationChanged -= RefreshPenumbraStatus; + _configurationService.OnConfigurationChanged -= OnConfigurationChanged; _penumbraInitializedSubscriber.Dispose(); _penumbraDisposedSubscriber.Dispose(); } diff --git a/Brio/Input/InputService.cs b/Brio/Input/InputService.cs index aab332aa..704b3b55 100644 --- a/Brio/Input/InputService.cs +++ b/Brio/Input/InputService.cs @@ -1,4 +1,5 @@ using Brio.Config; +using Brio.Game.Camera; using Brio.Game.GPose; using Dalamud.Game.ClientState.Keys; using Dalamud.Plugin.Services; @@ -7,25 +8,27 @@ namespace Brio.Input; -internal class InputService +public class InputService { private readonly IKeyState _keyState; private readonly IFramework _framework; private readonly ConfigurationService _configService; private readonly GPoseService _gPoseService; + private readonly VirtualCameraManager _virtualCameraManager; private readonly HashSet _eventsDown = new(); private readonly Dictionary> _listeners = new(); public static InputService Instance { get; private set; } = null!; - public InputService(IKeyState keyState, IFramework framework, ConfigurationService configService, GPoseService gPoseService) + public InputService(IKeyState keyState, IFramework framework, ConfigurationService configService, VirtualCameraManager virtualCameraManager, GPoseService gPoseService) { Instance = this; _keyState = keyState; _framework = framework; _configService = configService; _gPoseService = gPoseService; + _virtualCameraManager = virtualCameraManager; _framework.Update += OnFrameworkUpdate; } @@ -76,7 +79,16 @@ public void RemoveListener(KeyBindEvents evt, Action callback) private void OnFrameworkUpdate(IFramework framework) { - if(_gPoseService.IsGPosing && _configService.Configuration.Input.EnableKeybinds) + if(_gPoseService.IsGPosing == false) + return; + + bool disable = false; + if(_virtualCameraManager.CurrentCamera is not null && _virtualCameraManager.CurrentCamera.FreeCamValues.IsMovementEnabled) + { + disable = true; + } + + if(_configService.Configuration.Input.EnableKeybinds && disable == false) { foreach(var evt in Enum.GetValues()) { diff --git a/Brio/Input/KeyBind.cs b/Brio/Input/KeyBind.cs index e701f2a5..32302c79 100644 --- a/Brio/Input/KeyBind.cs +++ b/Brio/Input/KeyBind.cs @@ -2,7 +2,7 @@ namespace Brio.Input; -internal class KeyBind +public class KeyBind { public VirtualKey Key { get; set; } public bool Control { get; set; } diff --git a/Brio/Input/KeyBindEvents.cs b/Brio/Input/KeyBindEvents.cs index 6358934c..12f23c8c 100644 --- a/Brio/Input/KeyBindEvents.cs +++ b/Brio/Input/KeyBindEvents.cs @@ -1,6 +1,6 @@ namespace Brio.Input; -internal enum KeyBindEvents +public enum KeyBindEvents { Interface_ToggleBrioWindow, Interface_ToggleBindPromptWindow, @@ -20,5 +20,6 @@ internal enum KeyBindEvents Posing_Translate, Posing_Rotate, Posing_Scale, - Posing_Universal + Posing_Universal, + Poseing_Esc } diff --git a/Brio/Input/KeybindEditor.cs b/Brio/Input/KeybindEditor.cs index ba72e3c6..079df57b 100644 --- a/Brio/Input/KeybindEditor.cs +++ b/Brio/Input/KeybindEditor.cs @@ -6,7 +6,7 @@ namespace Brio.Input; -internal static class KeybindEditor +public static class KeybindEditor { private static string[] virtualKeyNames; private static List virtualKeys; diff --git a/Brio/Library/EntryBase.cs b/Brio/Library/EntryBase.cs index 26024114..7d367e10 100644 --- a/Brio/Library/EntryBase.cs +++ b/Brio/Library/EntryBase.cs @@ -11,7 +11,7 @@ namespace Brio.Library; /// /// An entry is a library object /// -internal abstract class EntryBase : ITagged +public abstract class EntryBase : ITagged { private SourceBase? _source; @@ -28,7 +28,7 @@ public EntryBase(SourceBase? source) public SourceBase? Source => _source; public string? SourceInfo { get; set; } - public string Identifier => $"{this.Source?.GetInternalId()}||{GetInternalId()}"; + public string Identifier => $"{this.Source?.GetpublicId()}||{GetpublicId()}"; public abstract bool PassesFilters(params FilterBase[] filters); @@ -85,5 +85,5 @@ public virtual bool InvokeDefaultAction(object? args) return false; } - protected abstract string GetInternalId(); + protected abstract string GetpublicId(); } diff --git a/Brio/Library/Filters/FilterBase.cs b/Brio/Library/Filters/FilterBase.cs index b0cab0b1..fa162ad0 100644 --- a/Brio/Library/Filters/FilterBase.cs +++ b/Brio/Library/Filters/FilterBase.cs @@ -1,6 +1,6 @@ namespace Brio.Library.Filters; -internal abstract class FilterBase +public abstract class FilterBase { public readonly string Name; diff --git a/Brio/Library/Filters/SearchQueryFilter.cs b/Brio/Library/Filters/SearchQueryFilter.cs index 3ea5a73e..4abcc336 100644 --- a/Brio/Library/Filters/SearchQueryFilter.cs +++ b/Brio/Library/Filters/SearchQueryFilter.cs @@ -1,6 +1,6 @@ namespace Brio.Library.Filters; -internal class SearchQueryFilter : FilterBase +public class SearchQueryFilter : FilterBase { public string[]? Query; diff --git a/Brio/Library/Filters/TagFilter.cs b/Brio/Library/Filters/TagFilter.cs index 83415b08..9191e588 100644 --- a/Brio/Library/Filters/TagFilter.cs +++ b/Brio/Library/Filters/TagFilter.cs @@ -2,7 +2,7 @@ namespace Brio.Library.Filters; -internal class TagFilter : FilterBase +public class TagFilter : FilterBase { public TagCollection? Tags; diff --git a/Brio/Library/Filters/TypeFilter.cs b/Brio/Library/Filters/TypeFilter.cs index 52cfe8b3..3ae99a3a 100644 --- a/Brio/Library/Filters/TypeFilter.cs +++ b/Brio/Library/Filters/TypeFilter.cs @@ -3,7 +3,7 @@ namespace Brio.Library.Filters; -internal class TypeFilter : FilterBase +public class TypeFilter : FilterBase { private HashSet _types = new(); diff --git a/Brio/Library/GroupEntryBase.cs b/Brio/Library/GroupEntryBase.cs index cdb375c4..0b0b20e1 100644 --- a/Brio/Library/GroupEntryBase.cs +++ b/Brio/Library/GroupEntryBase.cs @@ -8,7 +8,7 @@ namespace Brio.Library; /// /// An group entry is an entry in the library that contains other entries, such as a directory or folder. /// -internal abstract class GroupEntryBase : EntryBase +public abstract class GroupEntryBase : EntryBase { private List _allEntries = new List(); private List _filteredEntries = new List(); diff --git a/Brio/Library/ItemEntryBase.cs b/Brio/Library/ItemEntryBase.cs index 0811d5a5..968e54ba 100644 --- a/Brio/Library/ItemEntryBase.cs +++ b/Brio/Library/ItemEntryBase.cs @@ -18,7 +18,7 @@ namespace Brio.Library; /// /// An item entry is an entry in teh library that the user can load, or otherwise perform actions on. /// -internal abstract class ItemEntryBase : EntryBase +public abstract class ItemEntryBase : EntryBase { protected ItemEntryBase(SourceBase? source) : base(source) diff --git a/Brio/Library/LibraryFavoritesFilter.cs b/Brio/Library/LibraryFavoritesFilter.cs index 0a36bd54..12a0feb2 100644 --- a/Brio/Library/LibraryFavoritesFilter.cs +++ b/Brio/Library/LibraryFavoritesFilter.cs @@ -3,7 +3,7 @@ namespace Brio.Library; -internal class LibraryFavoritesFilter : FilterBase +public class LibraryFavoritesFilter : FilterBase { private ConfigurationService _configurationService; diff --git a/Brio/Library/LibraryManager.cs b/Brio/Library/LibraryManager.cs index e885dd03..8fcf082e 100644 --- a/Brio/Library/LibraryManager.cs +++ b/Brio/Library/LibraryManager.cs @@ -8,6 +8,7 @@ using Brio.UI.Windows; using Dalamud.Interface; using Dalamud.Plugin.Services; +using MessagePack; using System; using System.Collections.Generic; using System.IO; @@ -16,7 +17,7 @@ namespace Brio.Library; -internal class LibraryManager : IDisposable +public class LibraryManager : IDisposable { private static LibraryManager? _instance; @@ -25,7 +26,7 @@ internal class LibraryManager : IDisposable private readonly IFramework _framework; private readonly LibraryRoot _rootItem; private readonly List _sources = new(); - private readonly IEnumerable _internalSources; + private readonly IEnumerable _publicSources; private LibraryWindow? _window; @@ -39,14 +40,14 @@ public LibraryManager( FileService fileService, ConfigurationService configurationService, IFramework framework, - IEnumerable internalSources) + IEnumerable publicSources) { _instance = this; _fileService = fileService; _configurationService = configurationService; _framework = framework; _rootItem = new(); - _internalSources = internalSources; + _publicSources = publicSources; _configurationService.Configuration.Library.ReEstablishDefaultPaths(); _configurationService.OnConfigurationChanged += OnConfigurationChanged; @@ -84,14 +85,14 @@ public void RegisterWindow(LibraryWindow window) _window = window; } - public static void GetWithFilePicker(FilterBase filter, Action callback) + public static void GetWithFilePicker(FilterBase filter, Action callback, bool loadMessagePack = false) { if(_instance == null || _instance._window == null) return; - _instance.ShowFilePicker(filter, callback); + _instance.ShowFilePicker(filter, callback, loadMessagePack); } - private void ShowFilePicker(FilterBase filter, Action callback) + private void ShowFilePicker(FilterBase filter, Action callback, bool loadMessagePack) { string title = $"Import {filter.Name}###import_browse"; @@ -144,7 +145,6 @@ private void ShowFilePicker(FilterBase filter, Action callback) filterBuilder.Append("){"); filterBuilder.Append(typeInfo.Extension); filterBuilder.Append("}"); - } } @@ -175,8 +175,12 @@ private void ShowFilePicker(FilterBase filter, Action callback) { if(success && paths.Count == 1) { - var path = paths[0]; - object? result = _fileService.Load(path); + string path = paths[0]; + object? result; + if(loadMessagePack) + result = MessagePackSerializer.Deserialize(File.ReadAllBytes(path)); + else + result = _fileService.Load(path); if(result is null) return; @@ -218,7 +222,7 @@ public void Dispose() { Tag.ClearTagCache(); - foreach(SourceBase source in _internalSources) + foreach(SourceBase source in _publicSources) { source.Dispose(); } @@ -245,7 +249,7 @@ public void LoadSources() AddSource(new FileSource(_fileService, sourceConfig)); } - foreach(SourceBase source in _internalSources) + foreach(SourceBase source in _publicSources) { _rootItem.Add(source); } @@ -278,7 +282,7 @@ public async Task ScanAsync() try { List scanTasks = new(); - foreach(SourceBase source in _internalSources) + foreach(SourceBase source in _publicSources) { scanTasks.Add(Task.Run(() => ScanSource(source))); } diff --git a/Brio/Library/LibraryRoot.cs b/Brio/Library/LibraryRoot.cs index 3581fa53..f6b65bd8 100644 --- a/Brio/Library/LibraryRoot.cs +++ b/Brio/Library/LibraryRoot.cs @@ -3,7 +3,7 @@ namespace Brio.Library; -internal class LibraryRoot : GroupEntryBase +public class LibraryRoot : GroupEntryBase { public LibraryRoot() : base(null) @@ -18,7 +18,7 @@ public override void DrawInfo(LibraryWindow window) base.DrawInfo(window); } - protected override string GetInternalId() + protected override string GetpublicId() { return "Root"; } diff --git a/Brio/Library/Sources/FileSource.cs b/Brio/Library/Sources/FileSource.cs index 37bbb844..bc6bd709 100644 --- a/Brio/Library/Sources/FileSource.cs +++ b/Brio/Library/Sources/FileSource.cs @@ -14,7 +14,7 @@ namespace Brio.Library.Sources; -internal class FileSource : SourceBase +public class FileSource : SourceBase { public readonly string DirectoryPath = string.Empty; @@ -57,9 +57,9 @@ public FileSource(FileService fileService, string name, params string[] paths) public override IDalamudTextureWrap? Icon => ResourceProvider.Instance.GetResourceImage("Images.ProviderIcon_Directory.png"); public override string Description => DirectoryPath; - protected override string GetInternalId() + protected override string GetpublicId() { - // All file sources share the same internal Id, as the files themselves are unique on the + // All file sources share the same public Id, as the files themselves are unique on the // file system. return $"File"; } @@ -108,7 +108,7 @@ public interface IFileMetadata void GetAutoTags(ref TagCollection tags); } -internal class DirectoryEntry : GroupEntryBase +public class DirectoryEntry : GroupEntryBase { private string _name; private IDalamudTextureWrap _icon; @@ -130,7 +130,7 @@ public DirectoryEntry(FileSource source, string path) public override string Name => _name; public override IDalamudTextureWrap? Icon => _icon; - protected override string GetInternalId() + protected override string GetpublicId() { return _path; } @@ -154,7 +154,7 @@ public override void DrawActions(bool isModal) } } -internal class FileEntry : ItemEntryBase +public class FileEntry : ItemEntryBase { public readonly string FilePath; @@ -276,7 +276,7 @@ public override void Dispose() _previewImage?.Dispose(); } - protected override string GetInternalId() + protected override string GetpublicId() { return FilePath; } diff --git a/Brio/Library/Sources/GameDataAppearanceEntry.cs b/Brio/Library/Sources/GameDataAppearanceEntry.cs index b78c3c7b..f43c4c8c 100644 --- a/Brio/Library/Sources/GameDataAppearanceEntry.cs +++ b/Brio/Library/Sources/GameDataAppearanceEntry.cs @@ -11,7 +11,7 @@ namespace Brio.Library.Sources; -internal class GameDataAppearanceEntry : ItemEntryBase +public class GameDataAppearanceEntry : ItemEntryBase { private string _name; private uint _icon; @@ -91,7 +91,7 @@ public override bool Search(string[] query) return match; } - protected override string GetInternalId() => _id; + protected override string GetpublicId() => _id; public override bool InvokeDefaultAction(object? args) { diff --git a/Brio/Library/Sources/GameDataAppearanceSourceBase.cs b/Brio/Library/Sources/GameDataAppearanceSourceBase.cs index 3bf4351f..7283dfb3 100644 --- a/Brio/Library/Sources/GameDataAppearanceSourceBase.cs +++ b/Brio/Library/Sources/GameDataAppearanceSourceBase.cs @@ -4,7 +4,7 @@ namespace Brio.Library.Sources; -internal abstract class GameDataAppearanceSourceBase : SourceBase +public abstract class GameDataAppearanceSourceBase : SourceBase { private GameDataProvider _lumina; private EntityManager _entityManager; diff --git a/Brio/Library/Sources/GameDataCompanionSource.cs b/Brio/Library/Sources/GameDataCompanionSource.cs index d4acbb0a..50ccd3c0 100644 --- a/Brio/Library/Sources/GameDataCompanionSource.cs +++ b/Brio/Library/Sources/GameDataCompanionSource.cs @@ -3,7 +3,7 @@ namespace Brio.Library.Sources; -internal class GameDataCompanionSource : GameDataAppearanceSourceBase +public class GameDataCompanionSource : GameDataAppearanceSourceBase { public GameDataCompanionSource(GameDataProvider lumina, EntityManager entityManager) : base(lumina, entityManager) @@ -25,7 +25,7 @@ public override void Scan() } } - protected override string GetInternalId() + protected override string GetpublicId() { return "Companions"; } diff --git a/Brio/Library/Sources/GameDataMountSource.cs b/Brio/Library/Sources/GameDataMountSource.cs index ad7ed334..3207ef48 100644 --- a/Brio/Library/Sources/GameDataMountSource.cs +++ b/Brio/Library/Sources/GameDataMountSource.cs @@ -3,7 +3,7 @@ namespace Brio.Library.Sources; -internal class GameDataMountSource : GameDataAppearanceSourceBase +public class GameDataMountSource : GameDataAppearanceSourceBase { public GameDataMountSource(GameDataProvider lumina, EntityManager entityManager) : base(lumina, entityManager) @@ -34,7 +34,7 @@ public override void Scan() } } - protected override string GetInternalId() + protected override string GetpublicId() { return "Mounts"; } diff --git a/Brio/Library/Sources/GameDataNpcSource.cs b/Brio/Library/Sources/GameDataNpcSource.cs index b61098c3..5576493d 100644 --- a/Brio/Library/Sources/GameDataNpcSource.cs +++ b/Brio/Library/Sources/GameDataNpcSource.cs @@ -4,7 +4,7 @@ namespace Brio.Library.Sources; -internal class GameDataNpcSource : GameDataAppearanceSourceBase +public class GameDataNpcSource : GameDataAppearanceSourceBase { public GameDataNpcSource(GameDataProvider lumina, EntityManager entityManager) : base(lumina, entityManager) @@ -79,7 +79,7 @@ public override void Scan() return null; } - protected override string GetInternalId() + protected override string GetpublicId() { return "NPCs"; } diff --git a/Brio/Library/Sources/GameDataOrnamentSource.cs b/Brio/Library/Sources/GameDataOrnamentSource.cs index 309e35e2..12c1b519 100644 --- a/Brio/Library/Sources/GameDataOrnamentSource.cs +++ b/Brio/Library/Sources/GameDataOrnamentSource.cs @@ -3,7 +3,7 @@ namespace Brio.Library.Sources; -internal class GameDataOrnamentSource : GameDataAppearanceSourceBase +public class GameDataOrnamentSource : GameDataAppearanceSourceBase { public GameDataOrnamentSource(GameDataProvider lumina, EntityManager entityManager) : base(lumina, entityManager) @@ -26,7 +26,7 @@ public override void Scan() } - protected override string GetInternalId() + protected override string GetpublicId() { return "Ornaments"; } diff --git a/Brio/Library/Sources/SourceBase.cs b/Brio/Library/Sources/SourceBase.cs index a58bf655..400cac7b 100644 --- a/Brio/Library/Sources/SourceBase.cs +++ b/Brio/Library/Sources/SourceBase.cs @@ -3,7 +3,7 @@ namespace Brio.Library.Sources; -internal abstract class SourceBase : GroupEntryBase +public abstract class SourceBase : GroupEntryBase { public SourceBase() : base(null) diff --git a/Brio/Library/Tags/TagCollection.cs b/Brio/Library/Tags/TagCollection.cs index b5eb799f..ef62c4ad 100644 --- a/Brio/Library/Tags/TagCollection.cs +++ b/Brio/Library/Tags/TagCollection.cs @@ -1,9 +1,12 @@ -using System.Collections; +using MessagePack; +using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; namespace Brio.Library.Tags; + +[MessagePackObject(keyAsPropertyName: true)] public class TagCollection : IEnumerable, INotifyCollectionChanged { public static readonly TagCollection Empty = new(); diff --git a/Brio/Resources/Embedded/Data/BoneCategories.json b/Brio/Resources/Embedded/Data/BoneCategories.json index bbe825a4..51c85267 100644 --- a/Brio/Resources/Embedded/Data/BoneCategories.json +++ b/Brio/Resources/Embedded/Data/BoneCategories.json @@ -111,6 +111,8 @@ "ears": { "Type": "Filter", "Bones": [ + "n_ear_a_", + "n_ear_b_", "n_ear_", "j_mimi", "j_zer" @@ -175,6 +177,35 @@ "Bones": [ "iv_" ] + }, + "ex": { + "Type": "Filter", + "Bones": [ + "j_f_noanim_ago", + "J_f_eyeprm_01_", + "j_f_eyeprm_02_", + "j_f_irisprm_", + "j_f_irisprm_", + "j_f_noanim_eyesize_", + "j_f_eyeprmroll_r" + ] + }, + "legacy": { + "Type": "Filter", + "Bones": [ + "j_ago", + "j_f_dmab_", + "j_f_umab_", + "j_f_memoto", + "j_f_miken_r", + "j_f_miken_l", + "j_f_ulip_b", + "j_f_lip_l", + "j_f_lip_r", + "j_f_dlip_b", + "j_f_dlip_a", + "j_f_ulip_a" + ] }, "other": { "Type": "Filter", diff --git a/Brio/Resources/Embedded/Data/BrioAPose.pose b/Brio/Resources/Embedded/Data/BrioAPose.pose new file mode 100644 index 00000000..a08e8189 --- /dev/null +++ b/Brio/Resources/Embedded/Data/BrioAPose.pose @@ -0,0 +1,1297 @@ +{ + "TypeName": "Brio Pose", + "ModelDifference": { + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 1", + "Scale": "0, 0, 0" + }, + "ModelAbsoluteValues": { + "Position": "-0.0070150536, 41.386536, -138.16553", + "Rotation": "0, 0.010434319, 0, 0.9999456", + "Scale": "1, 1, 1" + }, + "Bones": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "-5.9604536E-14, 1.0767692, 4.7067012E-14", + "Rotation": "0, 0, 0, 0.9999998", + "Scale": "0.9999999, 0.9999999, 0.9999999" + }, + "n_throw": { + "Position": "-5.9604584E-14, 3.105873E-28, -7.1054185E-21", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + }, + "j_kosi": { + "Position": "-6.053587E-14, 1.0767692, 4.706694E-14", + "Rotation": "-0.55081683, 0.443518, -0.55081683, 0.44327536", + "Scale": "0.9999997, 0.9999997, 0.9999998" + }, + "j_sebo_a": { + "Position": "-6.053587E-14, 1.0767692, 4.706694E-14", + "Rotation": "0.47380355, 0.52476853, 0.47380355, 0.5250124", + "Scale": "0.9999998, 0.9999998, 0.9999998" + }, + "j_asi_a_l": { + "Position": "0.09297474, 0.9623664, 0.02498788", + "Rotation": "-0.50759006, 0.49240208, -0.5076124, 0.49216047", + "Scale": "0.9999995, 0.9999995, 0.99999976" + }, + "j_asi_a_r": { + "Position": "-0.09302521, 0.9624161, 0.02502802", + "Rotation": "-0.50759006, 0.49240208, -0.5076124, 0.49216047", + "Scale": "0.9999995, 0.9999995, 0.99999976" + }, + "j_buki2_kosi_l": { + "Position": "0.16842723, 1.0478883, 0.023239058", + "Rotation": "-0.00024428964, 9.697676E-05, -0.70721126, 0.70700186", + "Scale": "0.99999964, 1.0000004, 0.9999989" + }, + "j_buki2_kosi_r": { + "Position": "-0.16843261, 1.0479783, 0.023311779", + "Rotation": "-0.7070223, 0.7071909, -9.214878E-05, -5.5253506E-05", + "Scale": "0.99999964, 1.0000004, 0.99999905" + }, + "j_buki_kosi_l": { + "Position": "0.16842723, 1.0478883, 0.023239058", + "Rotation": "9.4503164E-05, 0.70718277, -9.4503164E-05, 0.70703065", + "Scale": "0.99999964, 0.9999998, 0.99999976" + }, + "j_buki_kosi_r": { + "Position": "-0.16843261, 1.0479783, 0.023311779", + "Rotation": "9.4503164E-05, 0.70718277, -9.4503164E-05, 0.70703065", + "Scale": "0.99999964, 0.9999998, 0.99999976" + }, + "j_sebo_b": { + "Position": "3.752533E-05, 1.2228317, -0.014982477", + "Rotation": "0.4947296, 0.50508845, 0.4947395, 0.5053321", + "Scale": "0.99999976, 0.99999976, 0.99999976" + }, + "j_sk_b_a_l": { + "Position": "0.07997715, 1.0799724, -0.11001764", + "Rotation": "-0.4700484, 0.52836084, -0.47011524, 0.5280919", + "Scale": "0.9999999, 0.9999999, 1" + }, + "j_sk_b_a_r": { + "Position": "-0.0800228, 1.0800152, -0.10998311", + "Rotation": "-0.4700499, 0.5283591, -0.4701135, 0.5280938", + "Scale": "1, 0.99999994, 1" + }, + "j_sk_f_a_l": { + "Position": "0.08002887, 1.0799842, 0.12998258", + "Rotation": "0.47007188, -0.5270122, -0.4619491, 0.53655714", + "Scale": "1.0000185, 1.0000005, 1" + }, + "j_sk_f_a_r": { + "Position": "-0.07997111, 1.080027, 0.13001712", + "Rotation": "0.46169394, -0.5365715, -0.47033405, 0.52698725", + "Scale": "1.0000185, 1.0000004, 1" + }, + "j_sk_s_a_l": { + "Position": "0.16500302, 1.0791545, 0.011075876", + "Rotation": "-0.0076098023, -0.008706265, -0.65191627, 0.75820273", + "Scale": "0.99999994, 0.99999994, 1.0000002" + }, + "j_sk_s_a_r": { + "Position": "-0.16499692, 1.0792428, 0.011147104", + "Rotation": "-0.6517092, 0.7583807, -0.0074501163, -0.008851693", + "Scale": "0.9999997, 0.9999999, 1" + }, + "j_asi_b_l": { + "Position": "0.092875496, 0.5820191, 0.036645804", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.99999946, 0.9999997" + }, + "j_asi_b_r": { + "Position": "-0.093124464, 0.5820699, 0.036685914", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.99999946, 0.9999997" + }, + "j_mune_l": { + "Position": "0.03640786, 1.2890183, -0.011461224", + "Rotation": "-0.03110633, -0.62148196, 0.030779313, 0.782205", + "Scale": "0.9999992, 0.99999946, 0.9999996" + }, + "j_mune_r": { + "Position": "-0.036304086, 1.2890351, -0.011479795", + "Rotation": "0.030968033, 0.7823568, -0.03095483, -0.6212889", + "Scale": "0.9999997, 0.9999996, 0.9999996" + }, + "j_sebo_c": { + "Position": "7.1252245E-05, 1.3658082, -0.017978534", + "Rotation": "0.51190376, 0.4876743, 0.51192206, 0.4879175", + "Scale": "0.9999997, 0.9999997, 0.9999997" + }, + "j_sk_b_b_l": { + "Position": "0.07991265, 0.89558774, -0.13156919", + "Rotation": "-0.47053638, 0.5279669, -0.4709563, 0.5273013", + "Scale": "0.99999994, 0.9999999, 0.99999994" + }, + "j_sk_b_b_r": { + "Position": "-0.080086015, 0.89563036, -0.13153468", + "Rotation": "-0.4705171, 0.5279863, -0.47095898, 0.52729666", + "Scale": "0.9999999, 1, 1" + }, + "j_sk_f_b_l": { + "Position": "0.087386265, 0.6686974, 0.1844472", + "Rotation": "0.46925646, -0.53002137, -0.49664685, 0.5022129", + "Scale": "1.0000182, 1.0000002, 1.0000001" + }, + "j_sk_f_b_r": { + "Position": "-0.0875386, 0.6687354, 0.1844766", + "Rotation": "0.49583337, -0.5028778, -0.47013128, 0.52937686", + "Scale": "1.0000185, 1.0000004, 1" + }, + "j_sk_s_b_l": { + "Position": "0.19773212, 0.8632799, 0.016126242", + "Rotation": "0.006299262, 0.005907367, -0.67595154, 0.7368954", + "Scale": "0.9999998, 0.9999998, 1.0000002" + }, + "j_sk_s_b_r": { + "Position": "-0.19784294, 0.8633859, 0.016200112", + "Rotation": "-0.6751037, 0.7376727, 0.0063984194, 0.005745247", + "Scale": "0.99999994, 0.99999994, 1" + }, + "j_asi_c_l": { + "Position": "0.09285854, 0.51930535, 0.035845548", + "Rotation": "-0.47089425, 0.5276041, -0.47093394, 0.5273647", + "Scale": "0.99999946, 0.99999946, 0.99999964" + }, + "j_asi_c_r": { + "Position": "-0.093141414, 0.519356, 0.03588566", + "Rotation": "-0.47089425, 0.5276041, -0.47093394, 0.5273647", + "Scale": "0.99999946, 0.99999946, 0.99999964" + }, + "j_buki_sebo_l": { + "Position": "0.10011753, 1.4759586, -0.09983562", + "Rotation": "-0.017234165, -0.017045029, 0.70689195, -0.70690554", + "Scale": "0.9999995, 0.9999998, 0.9999993" + }, + "j_buki_sebo_r": { + "Position": "-0.09988232, 1.4760047, -0.09988671", + "Rotation": "0.70682347, -0.7069784, -0.017047137, -0.017059475", + "Scale": "0.9999995, 0.99999994, 0.9999994" + }, + "j_kubi": { + "Position": "0.00010235656, 1.5083792, -0.01109577", + "Rotation": "0.6044724, 0.3667217, 0.6045424, 0.36695534", + "Scale": "0.9999997, 0.99999964, 0.99999964" + }, + "j_sako_l": { + "Position": "0.028292827, 1.3940656, -0.03391999", + "Rotation": "7.31647E-05, -8.925796E-06, 9.402633E-06, 0.99999976", + "Scale": "0.9999998, 0.9999995, 0.99999917" + }, + "j_sako_r": { + "Position": "-0.02812813, 1.3940786, -0.0339344", + "Rotation": "0.00024054945, 0.99999964, 7.31796E-05, 0.00024709105", + "Scale": "0.9999998, 0.9999995, 0.99999917" + }, + "j_sk_b_c_l": { + "Position": "0.07957715, 0.5918067, -0.16630101", + "Rotation": "-0.47747585, 0.5211603, -0.47242135, 0.5265233", + "Scale": "0.99999994, 1, 1" + }, + "j_sk_b_c_r": { + "Position": "-0.080435894, 0.5918505, -0.16627608", + "Rotation": "-0.47112718, 0.52800465, -0.47715226, 0.52112967", + "Scale": "0.99999976, 0.9999998, 1" + }, + "j_sk_f_c_l": { + "Position": "0.08076182, 0.54902947, 0.19240732", + "Rotation": "0.47693494, -0.52007973, -0.47352305, 0.52709204", + "Scale": "1.0000185, 1.0000004, 1" + }, + "j_sk_f_c_r": { + "Position": "-0.08126962, 0.5490456, 0.19243091", + "Rotation": "0.4794822, -0.52020794, -0.47086975, 0.5270315", + "Scale": "1.0000182, 1, 1" + }, + "j_sk_s_c_l": { + "Position": "0.22123979, 0.59133446, 0.011424584", + "Rotation": "0.0006687059, -0.00041553803, -0.67057216, 0.7418439", + "Scale": "0.99999994, 0.99999976, 1.0000002" + }, + "j_sk_s_c_r": { + "Position": "-0.22197738, 0.5914949, 0.01152758", + "Rotation": "-0.6714458, 0.741053, 0.00084999664, -0.000441946", + "Scale": "0.9999998, 0.9999999, 1" + }, + "n_hizasoubi_l": { + "Position": "0.09286739, 0.55202156, 0.03626301", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.99999946, 0.99999964" + }, + "n_hizasoubi_r": { + "Position": "-0.09313257, 0.5520723, 0.03630312", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.99999946, 0.99999964" + }, + "j_asi_d_l": { + "Position": "0.092733294, 0.090574145, -0.012895629", + "Rotation": "-0.6834413, 0.18170166, -0.6833428, 0.18147981", + "Scale": "0.9999994, 0.9999996, 0.9999996" + }, + "j_asi_d_r": { + "Position": "-0.09326666, 0.09062475, -0.01285553", + "Rotation": "-0.6834413, 0.18170166, -0.6833428, 0.18147981", + "Scale": "0.9999993, 0.99999946, 0.9999996" + }, + "j_kao": { + "Position": "0.000112611, 1.6139672, 0.043865114", + "Rotation": "0.70701605, -1.4394522E-05, 0.7071971, 0.00014907122", + "Scale": "0.9999995, 0.99999946, 0.9999996" + }, + "j_ude_a_l": { + "Position": "0.15606773, 1.4353812, -0.021994675", + "Rotation": "-0.63816273, 0.30412975, -0.2362931, 0.66664726", + "Scale": "0.9999994, 0.99999964, 0.99999875" + }, + "j_ude_a_r": { + "Position": "-0.1558911, 1.4354533, -0.022074489", + "Rotation": "-0.2359756, 0.666624, -0.63829345, 0.30415285", + "Scale": "0.99999976, 0.99999976, 0.9999986" + }, + "n_kataarmor_l": { + "Position": "0.12227181, 1.4961883, -0.033903375", + "Rotation": "7.31647E-05, -8.925796E-06, 9.402633E-06, 0.99999976", + "Scale": "0.99999976, 0.99999946, 0.9999991" + }, + "n_kataarmor_r": { + "Position": "-0.122058965, 1.4962447, -0.033965886", + "Rotation": "0.00024054945, 0.99999964, 7.31796E-05, 0.00024709105", + "Scale": "0.99999976, 0.99999946, 0.9999991" + }, + "j_ago": { + "Position": "0.0001141856, 1.6110313, 0.035112772", + "Rotation": "0.7009652, -0.09229821, 0.70116615, -0.09215978", + "Scale": "0.9999999, 0.9999997, 0.9999996" + }, + "j_asi_e_l": { + "Position": "0.092741266, 0.017036304, 0.11570899", + "Rotation": "-0.7071827, 0.00016985834, -0.70703065, -1.9267201E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "j_asi_e_r": { + "Position": "-0.09325869, 0.017086908, 0.11574906", + "Rotation": "-0.7071827, 0.00016985834, -0.70703065, -1.9267201E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "j_kami_a": { + "Position": "0.00014656092, 1.626336, -0.0773012", + "Rotation": "-0.4123524, 0.57414585, -0.4124616, 0.5746282", + "Scale": "1.0000001, 1, 0.99999994" + }, + "j_kami_f_l": { + "Position": "0.07411033, 1.6270804, 0.009847552", + "Rotation": "0.575087, -0.4174346, 0.59873456, -0.36951363", + "Scale": "1.0000007, 1, 1.0000004" + }, + "j_kami_f_r": { + "Position": "-0.07386159, 1.6271147, 0.009809714", + "Rotation": "0.59645015, -0.37107992, 0.57788444, -0.41544738", + "Scale": "1.0000002, 0.99999994, 1.0000002" + }, + "j_mimi_l": { + "Position": "0.07014951, 1.7249885, -9.4130635E-05", + "Rotation": "-0.30316788, 0.2962366, 0.35009825, 0.83532256", + "Scale": "0.99999934, 0.99999946, 0.9999993" + }, + "j_mimi_r": { + "Position": "-0.069850385, 1.725021, -0.00012890622", + "Rotation": "0.35036892, 0.8351658, -0.30314666, 0.2963804", + "Scale": "0.99999976, 0.9999994, 0.9999995" + }, + "j_ude_b_l": { + "Position": "0.35792658, 1.2335579, -0.05181618", + "Rotation": "-0.6676344, 0.23240232, -0.30788898, 0.63675535", + "Scale": "0.99999934, 0.9999996, 0.99999857" + }, + "j_ude_b_r": { + "Position": "-0.35782814, 1.2337235, -0.05199936", + "Rotation": "-0.30757084, 0.636767, -0.66776687, 0.23241097", + "Scale": "0.9999997, 0.9999997, 0.99999857" + }, + "n_hkata_l": { + "Position": "0.15606771, 1.435381, -0.021994686", + "Rotation": "-0.63816273, 0.30412975, -0.2362931, 0.66664726", + "Scale": "0.99999934, 0.9999996, 0.9999987" + }, + "n_hkata_r": { + "Position": "-0.15589108, 1.4354534, -0.022074483", + "Rotation": "-0.2359756, 0.666624, -0.63829345, 0.30415285", + "Scale": "0.9999997, 0.9999997, 0.99999857" + }, + "j_kami_b": { + "Position": "0.0001920081, 1.533431, -0.108646326", + "Rotation": "-0.4733645, 0.52504796, -0.47352272, 0.52538264", + "Scale": "1.0000004, 0.99999994, 1" + }, + "j_te_l": { + "Position": "0.5399853, 1.0514908, -0.02196987", + "Rotation": "-0.6531325, 0.27048934, -0.27068356, 0.65343964", + "Scale": "0.9999993, 0.9999996, 0.9999987" + }, + "j_te_r": { + "Position": "-0.53998643, 1.0517406, -0.022246324", + "Rotation": "-0.2703653, 0.653433, -0.6532642, 0.2705056", + "Scale": "0.99999964, 0.99999964, 0.9999985" + }, + "n_buki_tate_l": { + "Position": "0.46086907, 1.2298174, -0.043035906", + "Rotation": "-0.23240232, -0.6676344, -0.63675535, -0.30788898", + "Scale": "0.9999993, 0.9999995, 0.9999987" + }, + "n_buki_tate_r": { + "Position": "-0.46077675, 1.2300304, -0.043271743", + "Rotation": "0.23241097, -0.66776687, -0.636767, 0.30757084", + "Scale": "0.99999964, 0.99999964, 0.9999985" + }, + "n_ear_a_l": { + "Position": "0.10815677, 1.7399638, -0.06009558", + "Rotation": "-0.0001501143, -3.758073E-05, -8.788705E-05, 0.99999976", + "Scale": "0.9999993, 0.9999994, 0.9999993" + }, + "n_ear_a_r": { + "Position": "-0.1078199, 1.7400143, -0.060149852", + "Rotation": "-0.00014945865, -0.0002194941, -0.0001468733, 0.99999964", + "Scale": "0.9999999, 0.99999964, 0.9999995" + }, + "n_hhiji_l": { + "Position": "0.35792676, 1.233558, -0.05181617", + "Rotation": "-0.65390116, 0.26862583, -0.27254575, 0.65266514", + "Scale": "0.9999993, 0.9999995, 0.9999987" + }, + "n_hhiji_r": { + "Position": "-0.35782817, 1.2337235, -0.051999353", + "Rotation": "-0.27222747, 0.6526594, -0.65403295, 0.2686417", + "Scale": "0.99999964, 0.99999964, 0.99999857" + }, + "n_hijisoubi_l": { + "Position": "0.35792676, 1.233558, -0.05181617", + "Rotation": "-0.65390116, 0.26862583, -0.27254575, 0.65266514", + "Scale": "0.9999993, 0.9999995, 0.99999857" + }, + "n_hijisoubi_r": { + "Position": "-0.35782817, 1.2337235, -0.051999353", + "Rotation": "-0.27222747, 0.6526594, -0.65403295, 0.2686417", + "Scale": "0.99999964, 0.99999964, 0.9999985" + }, + "n_hte_l": { + "Position": "0.5399853, 1.0514908, -0.02196987", + "Rotation": "-0.6531325, 0.27048934, -0.27068356, 0.65343964", + "Scale": "0.9999993, 0.9999996, 0.9999987" + }, + "n_hte_r": { + "Position": "-0.53998643, 1.0517406, -0.022246324", + "Rotation": "-0.2703653, 0.653433, -0.6532642, 0.2705056", + "Scale": "0.9999995, 0.99999964, 0.9999985" + }, + "j_hito_a_l": { + "Position": "0.6070483, 0.98599917, 0.008063894", + "Rotation": "0.00010442734, -9.062886E-05, -0.38266706, 0.92388606", + "Scale": "0.9999992, 0.9999997, 0.9999985" + }, + "j_hito_a_r": { + "Position": "-0.6070942, 0.98628056, 0.007753091", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.99999976, 0.9999981" + }, + "j_ko_a_l": { + "Position": "0.60282516, 0.98532414, -0.06040907", + "Rotation": "0.0003299415, -0.00018402934, -0.38266703, 0.92388606", + "Scale": "0.9999992, 0.9999997, 0.9999985" + }, + "j_ko_a_r": { + "Position": "-0.60283726, 0.985603, -0.06071772", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.99999976, 0.9999981" + }, + "j_kusu_a_l": { + "Position": "0.6076609, 0.9868111, -0.0380916", + "Rotation": "0.0003299415, -0.00018402934, -0.38266703, 0.92388606", + "Scale": "0.9999992, 0.9999997, 0.9999985" + }, + "j_kusu_a_r": { + "Position": "-0.6076822, 0.9870922, -0.038402718", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.99999946, 0.99999976, 0.9999981" + }, + "j_naka_a_l": { + "Position": "0.60858804, 0.9874173, -0.014920043", + "Rotation": "0.00010442734, -9.062886E-05, -0.38266706, 0.92388606", + "Scale": "0.9999992, 0.9999997, 0.9999985" + }, + "j_naka_a_r": { + "Position": "-0.6086217, 0.98769814, -0.015231624", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.99999976, 0.9999981" + }, + "j_oya_a_l": { + "Position": "0.53773797, 1.0265636, 0.009202816", + "Rotation": "0.4310843, -0.5650048, -0.26267788, 0.65263766", + "Scale": "0.9999991, 0.9999996, 0.9999987" + }, + "j_oya_a_r": { + "Position": "-0.5377664, 1.0268126, 0.008926483", + "Rotation": "-0.26263738, 0.6528429, 0.43114772, -0.5647381", + "Scale": "0.99999934, 0.9999996, 0.99999845" + }, + "n_buki_l": { + "Position": "0.5811418, 0.9671061, -0.021977555", + "Rotation": "0.27048934, 0.6531325, 0.65343964, 0.27068356", + "Scale": "0.9999992, 0.9999996, 0.9999986" + }, + "n_buki_r": { + "Position": "-0.5811813, 0.96737576, -0.022275139", + "Rotation": "-0.653433, -0.2703653, -0.2705056, -0.6532642", + "Scale": "0.9999996, 0.9999996, 0.99999845" + }, + "n_ear_b_l": { + "Position": "0.10815521, 1.731884, -0.060093183", + "Rotation": "0.00041749948, -3.9945036E-05, -0.0033133556, 0.9999944", + "Scale": "1, 0.99999976, 0.99999976" + }, + "n_ear_b_r": { + "Position": "-0.1078222, 1.7319342, -0.06014764", + "Rotation": "0.00032707697, -0.0002211007, -0.0026048047, 0.9999966", + "Scale": "1.0000004, 1.0000004, 1.0000001" + }, + "j_hito_b_l": { + "Position": "0.6409905, 0.95205915, 0.008068095", + "Rotation": "0.00010442734, -9.062886E-05, -0.38266706, 0.92388606", + "Scale": "0.99999917, 0.99999964, 0.99999845" + }, + "j_hito_b_r": { + "Position": "-0.64105225, 0.95235634, 0.0077399076", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.9999997, 0.9999981" + }, + "j_ko_b_l": { + "Position": "0.62898904, 0.95916206, -0.060405828", + "Rotation": "0.0003299415, -0.00018402934, -0.38266703, 0.92388606", + "Scale": "0.9999992, 0.99999964, 0.99999845" + }, + "j_ko_b_r": { + "Position": "-0.6290134, 0.9594531, -0.060727887", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.9999997, 0.9999981" + }, + "j_kusu_b_l": { + "Position": "0.6423103, 0.95216405, -0.038087316", + "Rotation": "0.0003299415, -0.00018402934, -0.38266703, 0.92388606", + "Scale": "0.9999992, 0.99999964, 0.99999845" + }, + "j_kusu_b_r": { + "Position": "-0.6423478, 0.9524612, -0.038416173", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.99999946, 0.9999997, 0.9999981" + }, + "j_naka_b_l": { + "Position": "0.64465165, 0.951356, -0.014915579", + "Rotation": "0.00010442734, -9.062886E-05, -0.38266706, 0.92388606", + "Scale": "0.99999917, 0.99999964, 0.99999845" + }, + "j_naka_b_r": { + "Position": "-0.64470226, 0.95165366, -0.015245633", + "Rotation": "-0.3824535, 0.9239745, 6.5863132E-06, 0.00014589727", + "Scale": "0.9999996, 0.9999997, 0.9999981" + }, + "j_oya_b_l": { + "Position": "0.55450344, 0.96431375, 0.047528945", + "Rotation": "0.4310843, -0.5650048, -0.26267788, 0.65263766", + "Scale": "0.99999905, 0.9999996, 0.9999987" + }, + "j_oya_b_r": { + "Position": "-0.5545803, 0.96457064, 0.047243915", + "Rotation": "-0.26263738, 0.6528429, 0.43114772, -0.5647381", + "Scale": "0.99999934, 0.9999997, 0.99999857" + }, + "n_sippo_a": { + "Position": "-4.0620565E-05, 1.0035336, -0.09755956", + "Rotation": "-0.18408701, 0.6828026, -0.18422988, 0.68260646", + "Scale": "0.9999995, 0.9999997, 0.99999976" + }, + "n_sippo_b": { + "Position": "-8.87354E-05, 0.92809814, -0.22721095", + "Rotation": "-0.18408814, 0.68280244, -0.18423112, 0.6826062", + "Scale": "0.9999998, 0.99999994, 0.99999994" + }, + "n_sippo_c": { + "Position": "-0.0001368579, 0.8526621, -0.3568622", + "Rotation": "-0.18408315, 0.6828035, -0.18422642, 0.6826077", + "Scale": "0.99999994, 1, 0.99999994" + }, + "n_sippo_d": { + "Position": "-0.00018497353, 0.77722794, -0.48651442", + "Rotation": "-0.18402074, 0.68301296, -0.18427597, 0.6824016", + "Scale": "0.99999994, 1.0000002, 0.9999998" + }, + "n_sippo_e": { + "Position": "-0.0003243792, 0.7017962, -0.6161682", + "Rotation": "-0.18415578, 0.6825913, -0.18418664, 0.6828111", + "Scale": "0.9999998, 1.0000001, 0.99999994" + }, + "iv_ko_c_l": { + "Position": "0.64207095, 0.9460809, -0.060404208", + "Rotation": "0.00032994148, -0.00018402933, -0.382667, 0.923886", + "Scale": "0.9999992, 0.99999964, 0.99999845" + }, + "iv_kusu_c_l": { + "Position": "0.6596351, 0.9348404, -0.03808513", + "Rotation": "0.00032994148, -0.00018402933, -0.382667, 0.923886", + "Scale": "0.9999992, 0.99999964, 0.99999845" + }, + "iv_naka_c_l": { + "Position": "0.66268367, 0.9333253, -0.014913357", + "Rotation": "0.00010442733, -9.0628855E-05, -0.38266703, 0.923886", + "Scale": "0.99999917, 0.99999964, 0.99999845" + }, + "iv_hito_c_l": { + "Position": "0.6579618, 0.93508905, 0.008070189", + "Rotation": "0.00010442733, -9.0628855E-05, -0.38266703, 0.923886", + "Scale": "0.99999917, 0.9999996, 0.99999845" + }, + "iv_ko_c_r": { + "Position": "-0.6421012, 0.9463781, -0.060732976", + "Rotation": "-0.38245347, 0.92397445, 6.586313E-06, 0.00014589725", + "Scale": "0.9999996, 0.9999997, 0.9999981" + }, + "iv_kusu_c_r": { + "Position": "-0.6596806, 0.93514585, -0.038422912", + "Rotation": "-0.38245347, 0.92397445, 6.586313E-06, 0.00014589725", + "Scale": "0.9999994, 0.99999964, 0.9999981" + }, + "iv_naka_c_r": { + "Position": "-0.66274256, 0.9336313, -0.015252642", + "Rotation": "-0.38245347, 0.92397445, 6.586313E-06, 0.00014589725", + "Scale": "0.9999997, 0.9999998, 0.9999981" + }, + "iv_hito_c_r": { + "Position": "-0.6580312, 0.9353943, 0.007733307", + "Rotation": "-0.38245347, 0.92397445, 6.586313E-06, 0.00014589725", + "Scale": "0.9999996, 0.99999964, 0.9999981" + }, + "iv_asi_oya_a_l": { + "Position": "0.058350407, 0.034072954, 0.12689526", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_oya_b_l": { + "Position": "0.058355644, 0.03406776, 0.15127933", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_hito_a_l": { + "Position": "0.08285475, 0.030941889, 0.13303469", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_hito_b_l": { + "Position": "0.08285766, 0.030939, 0.14660925", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999934, 0.9999995" + }, + "iv_asi_naka_a_l": { + "Position": "0.09957546, 0.03093845, 0.12811662", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_naka_b_l": { + "Position": "0.099578366, 0.030935561, 0.1416912", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_kusu_a_l": { + "Position": "0.11638246, 0.030936172, 0.117682725", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.99999934, 0.9999995" + }, + "iv_asi_kusu_b_l": { + "Position": "0.11638538, 0.030933289, 0.1312573", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999934, 0.9999995" + }, + "iv_asi_ko_a_l": { + "Position": "0.13096008, 0.030933835, 0.11031701", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_ko_b_l": { + "Position": "0.13096234, 0.030931571, 0.12095666", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999994, 0.9999995" + }, + "iv_asi_oya_a_r": { + "Position": "-0.05885524, 0.034105003, 0.12692048", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_oya_b_r": { + "Position": "-0.058850005, 0.034099802, 0.15130456", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_hito_a_r": { + "Position": "-0.083358616, 0.030987076, 0.13307048", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_hito_b_r": { + "Position": "-0.08335572, 0.030984174, 0.14664504", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999917, 0.9999995" + }, + "iv_asi_naka_a_r": { + "Position": "-0.10008144, 0.030992605, 0.12815963", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_naka_b_r": { + "Position": "-0.10007851, 0.03098971, 0.1417342", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_kusu_a_r": { + "Position": "-0.11689292, 0.030999335, 0.11773295", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_kusu_b_r": { + "Position": "-0.11689, 0.03099644, 0.13130753", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_ko_a_r": { + "Position": "-0.1314737, 0.031004813, 0.11037355", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_asi_ko_b_r": { + "Position": "-0.1314714, 0.031002542, 0.121013194", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.9999993, 0.9999995" + }, + "iv_nitoukin_l": { + "Position": "0.25699717, 1.3344693, -0.036905415", + "Rotation": "0.00013931096, -0.70723253, -0.00011552125, 0.70698065", + "Scale": "0.9999994, 0.9999996, 0.99999875" + }, + "iv_nitoukin_r": { + "Position": "-0.2568596, 1.3345883, -0.037036948", + "Rotation": "-0.49999493, -0.49982435, -0.50025374, 0.4999263", + "Scale": "0.9999997, 0.9999997, 0.99999857" + }, + "iv_c_mune_l": { + "Position": "0.036407854, 1.289018, -0.011461202", + "Rotation": "-0.031106329, -0.6214819, 0.030779311, 0.7822049", + "Scale": "0.9999992, 0.9999996, 0.9999996" + }, + "iv_c_mune_r": { + "Position": "-0.036304105, 1.2890348, -0.011479724", + "Rotation": "0.03096803, 0.78235674, -0.030954828, -0.62128884", + "Scale": "0.9999997, 0.9999996, 0.9999996" + }, + "iv_kougan_l": { + "Position": "0.014819197, 0.9197874, 0.09152882", + "Rotation": "-0.4421702, 0.55170435, 0.44241285, -0.5517048", + "Scale": "0.99999946, 0.9999996, 0.9999997" + }, + "iv_kougan_r": { + "Position": "-0.0148643665, 0.91979533, 0.09153518", + "Rotation": "-0.5517049, 0.44241285, -0.5517044, 0.4421702", + "Scale": "0.9999997, 0.9999997, 0.9999998" + }, + "iv_ochinko_a": { + "Position": "-2.0354986E-05, 0.92741126, 0.09153166", + "Rotation": "-0.7026655, -0.07980326, -0.70249295, -0.07997388", + "Scale": "0.9999996, 0.9999996, 0.9999998" + }, + "iv_ochinko_b": { + "Position": "-1.208307E-05, 0.934303, 0.12144411", + "Rotation": "-0.70266545, -0.07980325, -0.7024929, -0.07997387", + "Scale": "0.9999996, 0.9999996, 0.9999998" + }, + "iv_ochinko_c": { + "Position": "-3.817204E-06, 0.94119465, 0.15135658", + "Rotation": "-0.69620144, -0.12414011, -0.69601846, -0.12429947", + "Scale": "0.9999996, 0.9999995, 0.9999998" + }, + "iv_ochinko_d": { + "Position": "5.587276E-06, 0.95226896, 0.181398", + "Rotation": "-0.6962014, -0.124140106, -0.6960184, -0.12429946", + "Scale": "0.9999996, 0.9999995, 0.9999998" + }, + "iv_ochinko_e": { + "Position": "1.49867265E-05, 0.9633433, 0.21143936", + "Rotation": "-0.6929134, -0.14134388, -0.69272655, -0.14149866", + "Scale": "0.9999996, 0.9999995, 0.9999998" + }, + "iv_ochinko_f": { + "Position": "2.2541364E-05, 0.9731529, 0.23446652", + "Rotation": "-0.69291335, -0.14134386, -0.6927265, -0.14149864", + "Scale": "0.9999996, 0.9999995, 0.9999998" + }, + "iv_kuritto": { + "Position": "-0.00083508156, 0.92975783, 0.07405292", + "Rotation": "0.3021356, -0.63880265, -0.3022032, 0.6397801", + "Scale": "1, 1, 1.0000001" + }, + "iv_inshin_l": { + "Position": "0.006354536, 0.9138817, 0.034682162", + "Rotation": "-0.4031899, 0.58080137, 0.4034319, -0.58081853", + "Scale": "0.9999982, 0.99999964, 0.9999998" + }, + "iv_inshin_r": { + "Position": "-0.006427265, 0.9138851, 0.03468492", + "Rotation": "-0.58081865, 0.40343177, -0.5808015, 0.40318975", + "Scale": "0.9999996, 0.9999996, 0.9999998" + }, + "iv_omanko": { + "Position": "0.00012332597, 0.9182067, 0.029764563", + "Rotation": "-0.39297858, 0.5877584, 0.3932203, -0.5877798", + "Scale": "1.0000054, 0.9999998, 0.9999998" + }, + "iv_koumon": { + "Position": "0.001106808, 0.92932034, -0.002746269", + "Rotation": "-0.66488343, 0.24046259, 0.6650908, -0.24033655", + "Scale": "0.99999964, 0.99999964, 0.9999998" + }, + "iv_koumon_l": { + "Position": "0.001106808, 0.92932034, -0.002746269", + "Rotation": "-0.51024485, 0.5031933, -0.33634496, 0.6109979", + "Scale": "0.9999997, 0.9999998, 0.9999998" + }, + "iv_koumon_r": { + "Position": "0.001106808, 0.92932034, -0.002746269", + "Rotation": "-0.33597973, 0.6331165, -0.50881463, 0.47685254", + "Scale": "0.9999997, 0.9999997, 0.9999998" + }, + "iv_shiri_l": { + "Position": "0.06619707, 0.96816134, -0.036543373", + "Rotation": "-0.7070306, 9.4658455E-05, 0.707183, 9.4369454E-05", + "Scale": "1, 1, 1.0000001" + }, + "iv_shiri_r": { + "Position": "-0.06627128, 0.96819675, -0.036514875", + "Rotation": "9.44797E-05, 0.70718277, -9.454945E-05, 0.7070308", + "Scale": "0.9999997, 0.9999997, 1" + }, + "iv_kyokin_phys_l": { + "Position": "0.04522211, 1.351867, 0.044153605", + "Rotation": "0.083912715, -0.37790436, -0.07120927, 0.91928023", + "Scale": "0.9999998, 1, 1" + }, + "iv_kyokin_phys_r": { + "Position": "-0.045646947, 1.3518671, 0.044069238", + "Rotation": "-0.07327869, 0.9197509, 0.07852894, -0.37752017", + "Scale": "1.0000006, 1.0000001, 1.0000006" + }, + "iv_fukubu_phys": { + "Position": "-6.8582594E-06, 1.1145278, 0.06086532", + "Rotation": "0.0001090765, 0.70719707, 5.4329634E-05, -0.7070161", + "Scale": "0.99999976, 0.99999994, 0.9999998" + }, + "iv_fukubu_phys_l": { + "Position": "0.059006903, 1.1131427, 0.042821597", + "Rotation": "-5.567074E-05, -0.14863701, -0.00010892749, 0.98889154", + "Scale": "0.9999998, 0.9999998, 0.9999998" + }, + "iv_fukubu_phys_r": { + "Position": "-0.059446655, 1.1131704, 0.04279129", + "Rotation": "0.00012047589, 0.9889297, -2.1025538E-05, -0.14838323", + "Scale": "0.99999976, 0.9999996, 0.9999997" + }, + "iv_daitai_phys_l": { + "Position": "0.09297473, 0.96236646, 0.02498791", + "Rotation": "-0.5120628, 0.48774907, -0.51208293, 0.48750725", + "Scale": "0.99999946, 0.9999995, 0.99999976" + }, + "iv_daitai_phys_r": { + "Position": "-0.093025215, 0.9624161, 0.025028005", + "Rotation": "-0.5120626, 0.48774922, -0.51208276, 0.4875074", + "Scale": "0.99999946, 0.99999946, 0.99999976" + }, + "iv_kintama_phys_l": { + "Position": "0.0062771905, 0.9117084, 0.09036183", + "Rotation": "0.57773304, -0.46160096, -0.407706, 0.53565377", + "Scale": "1.0000014, 0.9999998, 1.0000002" + }, + "iv_kintama_phys_r": { + "Position": "-0.00632718, 0.91171175, 0.090364546", + "Rotation": "-0.43167, 0.554614, 0.5600548, -0.43863747", + "Scale": "1.0000006, 1, 1" + }, + "iv_funyachin_phy_a": { + "Position": "-1.3286248E-05, 0.9537829, 0.091530375", + "Rotation": "0.6508869, -0.276562, 0.65076226, -0.27634788", + "Scale": "0.99999976, 0.99999964, 1" + }, + "iv_funyachin_phy_b": { + "Position": "-1.2026159E-05, 0.93309647, 0.11148659", + "Rotation": "0.6078272, -0.36151153, 0.6077232, -0.36128658", + "Scale": "0.99999976, 0.99999976, 1" + }, + "iv_funyachin_phy_c": { + "Position": "-1.3081755E-05, 0.90737504, 0.12546752", + "Rotation": "0.5531777, -0.44062304, 0.5530718, -0.44040585", + "Scale": "0.9999999, 0.9999998, 0.99999994" + }, + "iv_funyachin_phy_d": { + "Position": "-1.5011868E-05, 0.88199484, 0.13129511", + "Rotation": "0.5151944, -0.48448965, 0.515098, -0.48427123", + "Scale": "0.99999976, 0.9999995, 0.9999998" + }, + "j_f_face": { + "Position": "0.000112607246, 1.6139671, 0.043865107", + "Rotation": "-0.00014907238, -0.7071968, -1.4395755E-05, 0.7070157", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_ago": { + "Position": "0.000114985545, 1.6213628, 0.041264974", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_dhoho_l": { + "Position": "0.038902134, 1.5927389, 0.06507908", + "Rotation": "0.031417534, -0.21123749, -0.039405283, 0.97613347", + "Scale": "0.9999995, 0.99999976, 0.99999994" + }, + "j_f_dhoho_r": { + "Position": "-0.038697653, 1.5927567, 0.065059096", + "Rotation": "-0.03918769, 0.9761965, 0.03145625, -0.2109802", + "Scale": "0.999999, 0.99999976, 0.9999993" + }, + "j_f_dmemoto_l": { + "Position": "0.01719988, 1.6265608, 0.10486888", + "Rotation": "0.0007044769, -0.70595753, -0.02158063, 0.7079232", + "Scale": "0.9999995, 1.0121775, 0.9999996" + }, + "j_f_dmemoto_r": { + "Position": "-0.017000267, 1.6265687, 0.10486007", + "Rotation": "0.021417165, -0.70810884, -0.0008621334, 0.70577604", + "Scale": "0.9999995, 1.0121775, 0.9999996" + }, + "j_f_dmiken_l": { + "Position": "0.012912092, 1.641157, 0.10368254", + "Rotation": "0.0335657, -0.69154125, -0.023953069, 0.7211573", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_dmiken_r": { + "Position": "-0.012705118, 1.6411632, 0.10367596", + "Rotation": "0.023794971, -0.7213399, -0.033719417, 0.6913487", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_dslip_l": { + "Position": "0.024521125, 1.5889056, 0.09225019", + "Rotation": "-0.04831263, -0.4445836, 0.011357896, 0.89436", + "Scale": "0.9999999, 0.99999976, 0.99999994" + }, + "j_f_dslip_r": { + "Position": "-0.024332406, 1.5889169, 0.09223759", + "Rotation": "0.011576998, 0.8944712, -0.04820695, -0.44436568", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eye_l": { + "Position": "0.026410615, 1.647968, 0.08186531", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eye_r": { + "Position": "-0.026189249, 1.6479801, 0.08185175", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eyeprm_01_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eyeprm_01_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eyeprmroll_l": { + "Position": "0.020108366, 1.613955, 0.04386906", + "Rotation": "0.010839883, -0.70708984, 0.013420034, 0.70691144", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_eyeprmroll_r": { + "Position": "-0.01988261, 1.6139642, 0.043858767", + "Rotation": "-0.013580662, -0.7070894, -0.011006768, 0.70690626", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_hagukiup": { + "Position": "0.000105752304, 1.591605, 0.095923424", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_hana_l": { + "Position": "0.0062143677, 1.6163039, 0.11473243", + "Rotation": "0.0008271346, -0.7020261, 0.0078014047, 0.7121062", + "Scale": "1.0048707, 1.010656, 1.0048707" + }, + "j_f_hana_r": { + "Position": "-0.006024571, 1.6163068, 0.11472926", + "Rotation": "-0.007965798, -0.71228415, -0.0009914093, 0.70184356", + "Scale": "1.0048707, 1.010656, 1.0048708" + }, + "j_f_hoho_l": { + "Position": "0.042155366, 1.629632, 0.0877333", + "Rotation": "0.040782902, -0.4229029, 0.0066511766, 0.90523094", + "Scale": "0.9999999, 0.9999996, 0.99999994" + }, + "j_f_hoho_r": { + "Position": "-0.041945506, 1.6296514, 0.08771165", + "Rotation": "0.0068499786, 0.9053377, 0.040882368, -0.42266142", + "Scale": "0.99999917, 0.9999996, 0.99999946" + }, + "j_f_mab_l": { + "Position": "0.026411895, 1.6479573, 0.08183228", + "Rotation": "0.003650308, -0.5807935, 0.0007264107, 0.81404096", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_mab_r": { + "Position": "-0.026190516, 1.6479695, 0.08181872", + "Rotation": "-0.0009136457, -0.81418943, -0.0037847494, 0.5805841", + "Scale": "0.9999995, 0.99999976, 0.99999946" + }, + "j_f_mayu_l": { + "Position": "0.048579052, 1.6582426, 0.088389665", + "Rotation": "0.033031374, -0.30136967, -0.014410832, 0.95282483", + "Scale": "0.9999995, 0.9999996, 0.99999994" + }, + "j_f_mayu_r": { + "Position": "-0.048356295, 1.658265, 0.08836469", + "Rotation": "-0.014199032, 0.9529053, 0.03309734, -0.30111784", + "Scale": "0.9999988, 0.9999996, 0.9999993" + }, + "j_f_miken_01_l": { + "Position": "0.013166276, 1.6536878, 0.11349205", + "Rotation": "0.0020516089, -0.7205807, -0.021260263, 0.69304013", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_miken_01_r": { + "Position": "-0.012958565, 1.6536939, 0.11348534", + "Rotation": "0.02110059, -0.69322956, -0.0022127284, 0.72040266", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_mmayu_l": { + "Position": "0.035007473, 1.6572086, 0.10392463", + "Rotation": "0.015731214, -0.4992463, -0.045106318, 0.86514074", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_mmayu_r": { + "Position": "-0.034793194, 1.6572245, 0.103906676", + "Rotation": "-0.044910368, 0.8652791, 0.01583507, -0.499021", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_shoho_l": { + "Position": "0.03204558, 1.5863262, 0.082305625", + "Rotation": "0.10643038, -0.30995685, -0.14611596, 0.9334061", + "Scale": "0.9999995, 1.0361826, 1.0240045" + }, + "j_f_shoho_r": { + "Position": "-0.031375196, 1.5865569, 0.08196854", + "Rotation": "-0.14592743, 0.93351924, 0.10646456, -0.30969307", + "Scale": "0.9999988, 1.0361826, 1.0240041" + }, + "j_f_uhana": { + "Position": "9.783661E-05, 1.6360886, 0.12106626", + "Rotation": "-0.11958073, -0.69701314, 0.11938902, 0.69686216", + "Scale": "0.9999995, 0.9999996, 0.9999996" + }, + "j_f_ulip_01_l": { + "Position": "0.004325908, 1.6035151, 0.105870545", + "Rotation": "-0.015177502, -0.7070355, 0.010614744, 0.70693374", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_ulip_01_r": { + "Position": "-0.0041374685, 1.6035173, 0.10586837", + "Rotation": "-0.010782042, -0.7071123, 0.015011349, 0.7068579", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_umlip_01_l": { + "Position": "0.014791088, 1.600932, 0.0995685", + "Rotation": "-0.047341153, -0.46318358, 0.00340644, 0.884989", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_umlip_01_r": { + "Position": "-0.0146006085, 1.600939, 0.09956093", + "Rotation": "0.0036231333, 0.8851069, -0.04723321, -0.46296784", + "Scale": "0.9999988, 0.99999976, 0.9999989" + }, + "j_f_uslip_l": { + "Position": "0.024279285, 1.5906982, 0.09263888", + "Rotation": "-0.025707869, -0.4441135, -0.03427092, 0.89494437", + "Scale": "0.9999999, 0.99999976, 0.99999994" + }, + "j_f_uslip_r": { + "Position": "-0.024089951, 1.5907096, 0.09262639", + "Rotation": "-0.03405747, 0.8950661, -0.025613979, -0.44389004", + "Scale": "0.9999995, 0.99999976, 0.9999996" + }, + "j_f_bero_01": { + "Position": "0.00010529465, 1.5871644, 0.04817146", + "Rotation": "-0.080205, -0.70263326, 0.08002205, 0.7024717", + "Scale": "0.99999934, 1, 0.9999993" + }, + "j_f_dago": { + "Position": "0.00011273738, 1.6116389, 0.041266825", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_dlip_01_l": { + "Position": "0.0040838923, 1.576418, 0.099785626", + "Rotation": "0.0983288, -0.69986254, -0.10247822, 0.7000133", + "Scale": "0.99999917, 0.9999997, 0.9999996" + }, + "j_f_dlip_01_r": { + "Position": "-0.0039049855, 1.5764198, 0.099783555", + "Rotation": "0.10234161, -0.7002163, -0.09846431, 0.69966036", + "Scale": "0.99999917, 0.9999997, 0.9999996" + }, + "j_f_dmlip_01_l": { + "Position": "0.0145608345, 1.5804873, 0.0968233", + "Rotation": "0.15507792, -0.4600188, -0.04749111, 0.8729688", + "Scale": "0.9999999, 1, 0.9999996" + }, + "j_f_dmlip_01_r": { + "Position": "-0.014378482, 1.5804942, 0.09681579", + "Rotation": "-0.047329072, 0.87309754, 0.15517211, -0.45975924", + "Scale": "0.99999917, 1, 0.9999993" + }, + "j_f_eyeprm_02_l": { + "Position": "-0.00022141234, 1.6132183, 0.035054144", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_eyeprm_02_r": { + "Position": "0.0004508185, 1.6132182, 0.035054304", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_eyepuru_l": { + "Position": "0.02641062, 1.6479682, 0.081865326", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_eyepuru_r": { + "Position": "-0.026189256, 1.6479802, 0.081851766", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_hagukidn": { + "Position": "0.00016645683, 1.5806464, 0.092767544", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_irisprm_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_irisprm_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_mabdn_01_l": { + "Position": "0.026554275, 1.6477264, 0.08072915", + "Rotation": "0.08673231, -0.5740041, -0.14078902, 0.8019799", + "Scale": "0.99999934, 1, 0.99999946" + }, + "j_f_mabdn_01_r": { + "Position": "-0.026332425, 1.6477381, 0.08071551", + "Rotation": "0.14062496, -0.80215925, -0.0868302, 0.573779", + "Scale": "0.999999, 1, 0.9999993" + }, + "j_f_mabup_01_l": { + "Position": "0.027048966, 1.6481377, 0.08215118", + "Rotation": "-0.03478828, -0.5797013, 0.05558555, 0.81218415", + "Scale": "0.9999995, 0.9999997, 0.9999996" + }, + "j_f_mabup_01_r": { + "Position": "-0.026827669, 1.6481502, 0.08213729", + "Rotation": "-0.055782244, -0.81231964, 0.034640078, 0.5795012", + "Scale": "0.9999995, 1, 0.99999946" + }, + "j_f_miken_02_l": { + "Position": "0.007249107, 1.6505802, 0.11339834", + "Rotation": "-0.099926114, -0.72576153, -0.1617233, 0.6611557", + "Scale": "0.9999995, 1, 0.93676156" + }, + "j_f_miken_02_r": { + "Position": "-0.007042804, 1.6505837, 0.11339468", + "Rotation": "0.16154484, -0.66137886, 0.09979977, 0.7256152", + "Scale": "0.9999995, 1, 0.93676144" + }, + "j_f_ulip_02_l": { + "Position": "0.0042815693, 1.5947366, 0.10614734", + "Rotation": "-0.01300136, -0.70559555, 0.009362291, 0.70843124", + "Scale": "0.9920276, 1, 0.9999996" + }, + "j_f_ulip_02_r": { + "Position": "-0.0040973253, 1.594739, 0.106145196", + "Rotation": "-0.009529378, -0.7086098, 0.012835858, 0.7054171", + "Scale": "0.9920276, 1, 0.9999996" + }, + "j_f_umlip_02_l": { + "Position": "0.01452633, 1.593964, 0.10017712", + "Rotation": "-0.047341116, -0.46318325, 0.003406437, 0.88498837", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_umlip_02_r": { + "Position": "-0.014339351, 1.5939709, 0.10016974", + "Rotation": "0.003623134, 0.88510644, -0.04723318, -0.46296757", + "Scale": "0.9999988, 1, 0.9999989" + }, + "j_f_bero_02": { + "Position": "0.000102072554, 1.5907667, 0.063760616", + "Rotation": "0.006022282, -0.70717007, -0.0061841905, 0.70698744", + "Scale": "0.9999997, 0.9999997, 0.9999995" + }, + "j_f_dlip_02_l": { + "Position": "0.004142296, 1.5860144, 0.10259663", + "Rotation": "0.098328725, -0.69986206, -0.10247816, 0.7000128", + "Scale": "0.99198145, 0.9919818, 0.9999996" + }, + "j_f_dlip_02_r": { + "Position": "-0.0039604404, 1.5860167, 0.10259461", + "Rotation": "0.102341525, -0.7002158, -0.09846424, 0.6996599", + "Scale": "0.99198145, 0.99198174, 0.9999996" + }, + "j_f_dmlip_02_l": { + "Position": "0.01414252, 1.5871191, 0.0990245", + "Rotation": "0.15507784, -0.46001858, -0.047491092, 0.87296826", + "Scale": "0.99198174, 0.991982, 0.9999996" + }, + "j_f_dmlip_02_r": { + "Position": "-0.013958249, 1.5871264, 0.09901732", + "Rotation": "-0.047329046, 0.873097, 0.15517202, -0.459759", + "Scale": "0.99198127, 0.991982, 0.9999992" + }, + "j_f_mabdn_02out_l": { + "Position": "0.025609216, 1.6477492, 0.0810552", + "Rotation": "0.07413168, -0.6417167, -0.14781244, 0.74890006", + "Scale": "0.9999997, 0.9999997, 0.9999998" + }, + "j_f_mabdn_02out_r": { + "Position": "-0.025387498, 1.6477606, 0.08104196", + "Rotation": "0.14765757, -0.74909836, -0.07424349, 0.6415082", + "Scale": "0.9999996, 0.9999997, 0.9999995" + }, + "j_f_mabdn_03in_l": { + "Position": "0.024664097, 1.6477715, 0.08138111", + "Rotation": "0.07413168, -0.6417167, -0.14781244, 0.74890006", + "Scale": "0.9999997, 0.9999997, 0.9999998" + }, + "j_f_mabdn_03in_r": { + "Position": "-0.024442576, 1.6477829, 0.08136841", + "Rotation": "0.14765757, -0.74909836, -0.07424349, 0.6415082", + "Scale": "0.9999996, 0.9999997, 0.9999995" + }, + "j_f_mabup_02out_l": { + "Position": "0.026103463, 1.6481296, 0.08247669", + "Rotation": "-0.02981129, -0.64828163, 0.058406003, 0.7585689", + "Scale": "0.99999934, 0.99999964, 0.9999996" + }, + "j_f_mabup_02out_r": { + "Position": "-0.025882322, 1.6481422, 0.08246326", + "Rotation": "-0.058589056, -0.75872135, 0.02964651, 0.648094", + "Scale": "0.9999995, 0.9999997, 0.9999998" + }, + "j_f_mabup_03in_l": { + "Position": "0.02515794, 1.648122, 0.08280219", + "Rotation": "-0.02981129, -0.64828163, 0.058406003, 0.7585689", + "Scale": "0.99999934, 0.99999964, 0.9999996" + }, + "j_f_mabup_03in_r": { + "Position": "-0.024937, 1.6481339, 0.082789235", + "Rotation": "-0.058589056, -0.75872135, 0.02964651, 0.648094", + "Scale": "0.9999995, 0.9999997, 0.9999998" + }, + "j_f_bero_03": { + "Position": "9.808998E-05, 1.5905075, 0.07875828", + "Rotation": "0.04302443, -0.70588523, -0.043176543, 0.7056944", + "Scale": "0.99999994, 0.99999994, 0.9999995" + }, + "j_f_noanim_ago": { + "Position": "0.00011411109, 1.6110312, 0.035112683", + "Rotation": "0.70096475, -0.09229817, 0.7011657, -0.09215975", + "Scale": "0.99999917, 0.9999994, 0.99999946" + }, + "j_f_noanim_eyesize_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "0.007872224, -0.70719, 0.0030719552, 0.70697063", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_f_noanim_eyesize_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "0.007872224, -0.70719, 0.0030719552, 0.70697063", + "Scale": "0.9999995, 1, 0.9999996" + }, + "j_ex_h0179_back_01_c": { + "Position": "0.0001646834, 1.6804804, -0.09852052", + "Rotation": "-0.40489617, 0.58183366, -0.4115368, 0.57285684", + "Scale": "0.9999994, 0.9999994, 0.9999998" + }, + "j_ex_h0179_side_a01_l": { + "Position": "0.043938704, 1.6911907, 0.10895225", + "Rotation": "-0.4973582, 0.5025045, -0.50208265, 0.49803212", + "Scale": "0.9999995, 1, 0.9999997" + }, + "j_ex_h0179_side_a01_r": { + "Position": "-0.043316215, 1.6909308, 0.10854824", + "Rotation": "-0.49735835, 0.50250435, -0.5020826, 0.49803203", + "Scale": "0.9999995, 1, 0.9999997" + }, + "j_ex_h0179_side_b01_l": { + "Position": "0.06829355, 1.6992975, 0.08048706", + "Rotation": "-0.23847865, 0.55965537, -0.17277128, 0.7746373", + "Scale": "0.99999976, 1, 0.9999996" + }, + "j_ex_h0179_side_b01_r": { + "Position": "-0.06758577, 1.6996939, 0.0803228", + "Rotation": "-0.17245916, 0.7747028, -0.2387056, 0.5595641", + "Scale": "0.9999995, 0.99999994, 1" + } + }, + "MainHand": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + } + }, + "OffHand": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + } + }, + "Position": "-0.0070150536, 41.386536, -138.16553", + "Rotation": "0, 0.010434319, 0, 0.9999456", + "Scale": "1, 1, 1", + "Author": null, + "Description": null, + "Version": null, + "Base64Image": null, + "Tags": null +} \ No newline at end of file diff --git a/Brio/Resources/Embedded/Data/BrioPropChar.chara b/Brio/Resources/Embedded/Data/BrioPropChar.chara new file mode 100644 index 00000000..3d36f18e --- /dev/null +++ b/Brio/Resources/Embedded/Data/BrioPropChar.chara @@ -0,0 +1,113 @@ +{ + "ModelType": 0, + "Race": "Miqote", + "Gender": "Masculine", + "Age": "Normal", + "Tribe": "SeekerOfTheSun", + "Height": 0, + "Head": 1, + "Hair": 1, + "EnableHighlights": true, + "Skintone": 105, + "REyeColor": 162, + "HairTone": 44, + "Highlights": 47, + "FacialFeatures": "None", + "LimbalEyes": 153, + "Eyebrows": 1, + "LEyeColor": 161, + "Eyes": 129, + "Nose": 1, + "Jaw": 1, + "Mouth": 129, + "LipsToneFurPattern": 183, + "EarMuscleTailSize": 0, + "TailEarsType": 1, + "Bust": 0, + "FacePaint": 0, + "FacePaintColor": 169, + "MainHand": { + "Color": "0, 0, 0", + "Scale": "0, 0, 0", + "ModelSet": 3001, + "ModelBase": 1, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "OffHand": { + "Color": "0, 0, 0", + "Scale": "0, 0, 0", + "ModelSet": 3051, + "ModelBase": 1, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "HeadGear": { + "ModelBase": 279, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Body": { + "ModelBase": 2, + "ModelVariant": 45, + "DyeId": 0, + "DyeId2": 0 + }, + "Hands": { + "ModelBase": 279, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Legs": { + "ModelBase": 10, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 6 + }, + "Feet": { + "ModelBase": 279, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Ears": { + "ModelBase": 53, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Neck": { + "ModelBase": 53, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Wrists": { + "ModelBase": 53, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "LeftRing": { + "ModelBase": 53, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "RightRing": { + "ModelBase": 53, + "ModelVariant": 1, + "DyeId": 0, + "DyeId2": 0 + }, + "Glasses": { + "GlassesId": 0 + }, + "Transparency": 1, + "HeightMultiplier": 0.91, + "MuscleTone": 1 +} \ No newline at end of file diff --git a/Brio/Resources/Embedded/Data/BrioPropPose.pose b/Brio/Resources/Embedded/Data/BrioPropPose.pose index d519436a..675ea950 100644 --- a/Brio/Resources/Embedded/Data/BrioPropPose.pose +++ b/Brio/Resources/Embedded/Data/BrioPropPose.pose @@ -1,1285 +1,1294 @@ { + "TypeName": "Brio Pose", "ModelDifference": { - "Position": "-0.036890507, 0.44, -1.2195563", - "Rotation": "0, 0.47909713, 0, 0.8777619", + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 1", "Scale": "0, 0, 0" }, + "ModelAbsoluteValues": { + "Position": "-78.538475, 1.060323, 36.018433", + "Rotation": "0, 0.3695864, 0, 0.92919636", + "Scale": "1, 1, 1" + }, "Bones": { "n_root": { - "Position": "0, -1000, 0", + "Position": "0, 0, 0", "Rotation": "0, 0, 0, 0.99999994", "Scale": "1, 1, 1" }, "n_hara": { - "Position": "-0.007895907, -2000.0002, 0.024643952", - "Rotation": "0, 0, 0, 0.9999997", - "Scale": "0.9999998, 0.9999998, 0.9999998" + "Position": "2.514571E-08, -1550, 1.1175871E-08", + "Rotation": "0, 0, 0, 0.9999998", + "Scale": "0.9999999, 0.9999999, 0.9999999" }, "n_throw": { - "Position": "-5.9604584E-14, -2000, -7.1054185E-21", + "Position": "-5.9604584E-14, 3.105873E-28, -7.1054185E-21", "Rotation": "0, 0, 0, 0.99999994", "Scale": "0.99999994, 0.99999994, 0.99999994" }, "j_kosi": { - "Position": "-0.007895907, -3001.0532, 0.024643952", - "Rotation": "-0.672558, 0.5710922, -0.380241, 0.2773729", - "Scale": "0.99999976, 0.99999976, 0.99999976" + "Position": "2.5145706E-08, -1550, 1.3038516E-08", + "Rotation": "-0.67442095, 0.5654794, -0.38461328, 0.27831918", + "Scale": "0.9999998, 0.9999998, 0.9999998" }, "j_sebo_a": { - "Position": "-0.007895907, -3001.0532, 0.024643952", - "Rotation": "0.50186145, 0.6877104, 0.25116888, 0.4605465", - "Scale": "0.99999976, 0.99999976, 0.99999976" + "Position": "2.5145706E-08, -1550, 1.3038516E-08", + "Rotation": "0.49585527, 0.6902235, 0.25166118, 0.46301755", + "Scale": "0.9999998, 0.9999998, 0.9999998" }, "j_asi_a_l": { - "Position": "0.07598785, -4002.1064, -0.0043630805", - "Rotation": "-0.6728054, 0.5992326, -0.22591123, 0.37042776", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "2.2351742E-08, -1550, 1.3038516E-08", + "Rotation": "-0.66943854, 0.6027599, -0.22387162, 0.3720399", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_asi_a_r": { - "Position": "-0.078072004, -4002.1062, 0.09923182", - "Rotation": "-0.5515414, 0.62412304, -0.4455438, 0.32827237", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "2.2351742E-08, -1550, 1.4901161E-08", + "Rotation": "-0.5510766, 0.6244869, -0.44527307, 0.32872784", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_buki2_kosi_l": { - "Position": "0.16194119, -4002.1064, -0.06507463", - "Rotation": "0.0011875927, 0.19942282, -0.6340559, 0.74712896", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "0.17115694, -1550.0632, -0.08771059", + "Rotation": "0.0016364449, 0.19253056, -0.6313459, 0.7512198", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_buki2_kosi_r": { - "Position": "-0.16853471, -4002.106, 0.13079254", - "Rotation": "-0.5911194, 0.7888559, 0.15551966, -0.06400986", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "-0.16127764, -1550.0424, 0.10516709", + "Rotation": "-0.59396267, 0.7879513, 0.1489971, -0.06434527", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_buki_kosi_l": { - "Position": "0.18790014, -4002.1064, -0.056461833", - "Rotation": "-0.46324474, 0.63256633, -0.21672076, 0.58163214", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "0.1974328, -1550.1183, -0.07833205", + "Rotation": "-0.46555367, 0.6300091, -0.21663995, 0.5825934", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_buki_kosi_r": { - "Position": "-0.17421864, -4002.1062, 0.1406332", - "Rotation": "-0.39239866, 0.74109375, -0.3761621, 0.39408767", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "-0.16696016, -1550.0457, 0.11495648", + "Rotation": "-0.3944436, 0.7379766, -0.37760782, 0.39650556", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_sebo_b": { - "Position": "-0.018476984, -4002.1057, -0.031347923", - "Rotation": "0.54790694, 0.64591336, 0.35599363, 0.39479345", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "2.514571E-08, -1550, 1.1175871E-08", + "Rotation": "0.54604065, 0.64621204, 0.35834914, 0.39475963", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_sk_b_a_l": { - "Position": "-0.0026923548, -4002.1052, -0.11130857", - "Rotation": "-0.5637514, 0.67429745, -0.29811212, 0.37233812", - "Scale": "0.9999999, 0.9999999, 1" + "Position": "0.006381455, -1550.0007, -0.13590145", + "Rotation": "-0.5641227, 0.67194366, -0.3065963, 0.36912718", + "Scale": "0.99999994, 0.9999999, 0.99999994" }, "j_sk_b_a_r": { - "Position": "-0.13521694, -4002.1052, -0.022194626", - "Rotation": "-0.55426663, 0.6872354, -0.3295356, 0.3345169", - "Scale": "1, 1, 1" + "Position": "-0.12698652, -1549.9912, -0.048026033", + "Rotation": "-0.5537624, 0.68516785, -0.33742976, 0.3317112", + "Scale": "0.99999994, 1, 0.99999976" }, "j_sk_f_a_l": { - "Position": "0.13096236, -4002.1072, 0.08797482", - "Rotation": "0.3351359, -0.32228327, -0.5743385, 0.6737596", - "Scale": "1.0000186, 1.0000005, 1" + "Position": "0.13833165, -1550.0026, 0.06456172", + "Rotation": "0.33005103, -0.33258447, -0.5772973, 0.6687159", + "Scale": "1.0000187, 1.0000006, 0.99999994" }, "j_sk_f_a_r": { - "Position": "-0.0015622545, -4002.1072, 0.1770888", - "Rotation": "0.28027627, -0.3823577, -0.60315263, 0.6414467", - "Scale": "1.0000186, 1.0000004, 0.9999999" + "Position": "0.0049637696, -1549.993, 0.15243722", + "Rotation": "0.2827615, -0.38588545, -0.6014122, 0.6398757", + "Scale": "1.0000185, 1.0000004, 0.99999994" }, "j_sk_s_a_l": { - "Position": "0.13506046, -4002.1062, -0.05823067", - "Rotation": "-0.16472897, 0.23559363, -0.56604123, 0.7726295", - "Scale": "0.99999976, 0.99999976, 1.0000002" + "Position": "0.14372332, -1550.0067, -0.08157129", + "Rotation": "-0.16891973, 0.22833894, -0.5773499, 0.76550215", + "Scale": "0.9999998, 0.9999998, 1.0000002" }, "j_sk_s_a_r": { - "Position": "-0.13827144, -4002.1062, 0.12556683", - "Rotation": "-0.5630944, 0.772182, 0.17421642, -0.23729216", - "Scale": "0.99999976, 0.9999999, 1" + "Position": "-0.13134804, -1549.987, 0.09967198", + "Rotation": "-0.5611085, 0.7755347, 0.17113805, -0.23326777", + "Scale": "0.9999997, 1, 1" }, "j_asi_b_l": { - "Position": "0.14439404, -5003.0396, -0.05761999", - "Rotation": "-0.6521306, 0.6216692, -0.21323963, 0.37786436", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "5.6169927E-05, -1549.9998, 9.640306E-05", + "Rotation": "-0.65020496, 0.623459, -0.21209328, 0.37887818", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_asi_b_r": { - "Position": "-0.14507443, -5003.0503, 0.13032341", - "Rotation": "-0.5366476, 0.63697475, -0.43766674, 0.33870322", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "1.1868775E-05, -1550, 4.3332577E-05", + "Rotation": "-0.5362474, 0.6372661, -0.43742427, 0.3391021", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_mune_l": { - "Position": "0.010528348, -5003.2935, -0.050711155", - "Rotation": "-0.051751826, -0.4307561, 0.093344845, 0.8961346", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "0.028916012, -1549.9325, -0.019067427", + "Rotation": "-0.050301015, -0.43256554, 0.09502134, 0.895169", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_mune_r": { - "Position": "-0.054920405, -5003.2935, -0.019094933", - "Rotation": "0.03708769, 0.6218643, -0.09891304, -0.7759671", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "-0.036884036, -1549.935, 0.012097795", + "Rotation": "0.035289157, 0.62342477, -0.100205235, -0.7746321", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_sebo_c": { - "Position": "-0.031043364, -5003.2935, -0.04849479", - "Rotation": "0.6308896, 0.54109174, 0.43638426, 0.34462464", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "-0.013189546, -1549.8586, -0.01705854", + "Rotation": "0.63416773, 0.53706974, 0.44053006, 0.3395883", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "j_sk_b_b_l": { - "Position": "-0.018861352, -5003.1577, -0.142127", - "Rotation": "-0.5642601, 0.6739301, -0.29874197, 0.3717276", - "Scale": "0.9999998, 0.9999999, 0.99999994" + "Position": "-0.010413541, -1550.1835, -0.1637278", + "Rotation": "-0.55998623, 0.6751805, -0.30277422, 0.37265727", + "Scale": "0.99999994, 1, 1" }, "j_sk_b_b_r": { - "Position": "-0.16524883, -5003.1675, -0.039734423", - "Rotation": "-0.5588805, 0.6824754, -0.3220435, 0.3437545", - "Scale": "0.9999998, 0.9999999, 0.99999994" + "Position": "-0.15798232, -1550.1736, -0.063022956", + "Rotation": "-0.5570665, 0.6813473, -0.32717854, 0.34408718", + "Scale": "0.99999976, 0.9999998, 1" }, "j_sk_f_b_l": { - "Position": "0.18596163, -5003.1567, 0.108443126", - "Rotation": "0.32548788, -0.33342552, -0.5933872, 0.6563352", - "Scale": "1.0000181, 1, 0.99999994" + "Position": "0.18484639, -1550.414, 0.09104288", + "Rotation": "0.31582257, -0.3487651, -0.610142, 0.6374519", + "Scale": "1.0000184, 1.0000002, 1.0000001" }, "j_sk_f_b_r": { - "Position": "-0.0098494915, -5003.167, 0.24034059", - "Rotation": "0.31776682, -0.345367, -0.60959816, 0.63885444", - "Scale": "1.0000182, 1.0000002, 0.9999999" + "Position": "-0.0038222694, -1550.4033, 0.21617894", + "Rotation": "0.32112527, -0.34876493, -0.61273974, 0.63229036", + "Scale": "1.0000185, 1.0000002, 1" }, "j_sk_s_b_l": { - "Position": "0.18926382, -5003.1514, -0.097011045", - "Rotation": "-0.15901174, 0.24619634, -0.5876485, 0.75416887", - "Scale": "0.99999976, 0.99999976, 1.0000001" + "Position": "0.19379926, -1550.2167, -0.11532001", + "Rotation": "-0.1543993, 0.24926008, -0.60230076, 0.742471", + "Scale": "1, 0.99999994, 1.0000002" }, "j_sk_s_b_r": { - "Position": "-0.19357792, -5003.172, 0.16275272", - "Rotation": "-0.58860135, 0.75471526, 0.19869736, -0.21088287", - "Scale": "0.99999976, 0.9999999, 0.99999994" + "Position": "-0.18839462, -1550.1947, 0.13670714", + "Rotation": "-0.5890532, 0.7564149, 0.19818808, -0.2038943", + "Scale": "1, 0.99999994, 0.99999994" }, "j_asi_c_l": { - "Position": "0.15293077, -6003.602, -0.06964271", - "Rotation": "-0.60154897, 0.67073524, -0.18305518, 0.3933744", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "1.0164455E-05, -1549.9998, 9.7319484E-05", + "Rotation": "-0.6032115, 0.6690318, -0.18401846, 0.39328042", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_asi_c_r": { - "Position": "-0.15727815, -6003.621, 0.13272269", - "Rotation": "-0.50110763, 0.6652959, -0.41854212, 0.36206985", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "0.00014463719, -1550, 3.7282705E-05", + "Rotation": "-0.5007506, 0.66552114, -0.41831014, 0.36241812", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_buki_sebo_l": { - "Position": "-0.014791651, -6004.6226, -0.17807767", - "Rotation": "0.106127754, -0.14934702, 0.7671702, -0.6147206", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "0.0027689906, -1549.7462, -0.14640656", + "Rotation": "0.10599867, -0.15048137, 0.76576823, -0.6162127", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_buki_sebo_r": { - "Position": "-0.1312134, -6004.6226, -0.122136176", - "Rotation": "0.7951773, -0.5935681, -0.12092464, 0.027324285", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "-0.113582805, -1549.7732, -0.090748325", + "Rotation": "0.79668236, -0.591596, -0.12097509, 0.026003046", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_kubi": { - "Position": "-0.026250904, -6004.622, -0.023134302", - "Rotation": "0.68163884, 0.31070763, 0.6020987, 0.276235", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "-0.008230539, -1549.7188, 0.010553032", + "Rotation": "0.6817398, 0.30240533, 0.6111193, 0.2651688", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_sako_l": { - "Position": "-0.010672195, -6004.6226, -0.07006729", - "Rotation": "0.058887884, 0.19174619, -0.03255321, 0.979135", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "0.007221536, -1549.8271, -0.038141347", + "Rotation": "0.06643601, 0.18361011, -0.034819227, 0.9801331", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_sako_r": { - "Position": "-0.06278045, -6004.623, -0.048536874", - "Rotation": "0.01366654, 0.9677451, 0.062956065, -0.24355377", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "-0.04478112, -1549.8296, -0.016642097", + "Rotation": "0.010184468, 0.9651802, 0.07152222, -0.2514115", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_sk_b_c_l": { - "Position": "-0.045419354, -6004.028, -0.19224131", - "Rotation": "-0.571048, 0.6683342, -0.30347708, 0.36760685", - "Scale": "0.9999997, 1, 0.9999999" + "Position": "-0.039226864, -1550.4838, -0.2138476", + "Rotation": "-0.5646642, 0.67235094, -0.31316656, 0.3619734", + "Scale": "0.99999994, 1, 0.99999994" }, "j_sk_b_c_r": { - "Position": "-0.20774081, -6004.047, -0.073135965", - "Rotation": "-0.5698641, 0.6721737, -0.31652945, 0.35106373", - "Scale": "0.9999998, 0.99999976, 0.9999999" + "Position": "-0.2014684, -1550.4745, -0.094888896", + "Rotation": "-0.56342393, 0.6766094, -0.33662093, 0.33382452", + "Scale": "0.9999998, 0.99999976, 0.9999998" }, "j_sk_f_c_l": { - "Position": "0.19478382, -6003.7954, 0.11461754", - "Rotation": "0.3172269, -0.34258014, -0.6038199, 0.64606994", - "Scale": "1.0000182, 1.0000001, 0.9999998" + "Position": "0.18632868, -1550.5338, 0.09807663", + "Rotation": "0.3119191, -0.35222554, -0.59967315, 0.6473291", + "Scale": "1.0000186, 1.0000001, 1" }, "j_sk_f_c_r": { - "Position": "-0.007659439, -6003.817, 0.24681069", - "Rotation": "0.311344, -0.35163602, -0.6040412, 0.64385563", - "Scale": "1.0000181, 0.99999994, 0.99999976" + "Position": "-0.003118665, -1550.5232, 0.22188714", + "Rotation": "0.30437085, -0.36553612, -0.6057997, 0.63776803", + "Scale": "1.0000184, 1.0000001, 0.9999998" }, "j_sk_s_c_l": { - "Position": "0.24061805, -6003.988, -0.14736894", - "Rotation": "-0.15734194, 0.25207874, -0.61213976, 0.7327914", - "Scale": "0.99999976, 0.9999999, 1" + "Position": "0.23479776, -1550.4819, -0.16562666", + "Rotation": "-0.16203552, 0.24316208, -0.61581415, 0.7317026", + "Scale": "1.0000002, 1, 1.0000002" }, "j_sk_s_c_r": { - "Position": "-0.25313395, -6004.03, 0.18579558", - "Rotation": "-0.6005564, 0.7450891, 0.19997643, -0.21019624", - "Scale": "0.99999976, 0.99999976, 0.9999999" + "Position": "-0.24941044, -1550.4602, 0.15721004", + "Rotation": "-0.5873596, 0.7570961, 0.19070503, -0.21317677", + "Scale": "0.9999998, 1, 1" }, "n_hizasoubi_l": { - "Position": "0.14788988, -6003.602, -0.06391221", - "Rotation": "-0.6521306, 0.6216692, -0.21323963, 0.37786436", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "0.0036396126, -1550.0287, -0.006209341", + "Rotation": "-0.6502049, 0.62345904, -0.21209328, 0.37887818", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "n_hizasoubi_r": { - "Position": "-0.15095288, -6003.621, 0.13135871", - "Rotation": "-0.5366476, 0.63697475, -0.43766674, 0.33870322", - "Scale": "0.9999996, 0.9999996, 0.9999996" + "Position": "-0.005897176, -1550.0293, 0.0008983463", + "Rotation": "-0.5362474, 0.6372661, -0.43742427, 0.3391021", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_asi_d_l": { - "Position": "0.16726032, -7004.1025, -0.20231257", - "Rotation": "-0.93459296, 0.28174102, -0.20790872, 0.06270033", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "2.6013702E-05, -1549.9996, 0.00016380847", + "Rotation": "-0.9346543, 0.28152576, -0.20796983, 0.0625558", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_asi_d_r": { - "Position": "-0.25893492, -7004.13, 0.10584161", - "Rotation": "-0.72355926, 0.19198954, -0.64082456, 0.17013314", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "9.834766E-06, -1549.9999, -6.055832E-05", + "Rotation": "-0.72352797, 0.1920517, -0.64082533, 0.17019445", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_kao": { - "Position": "-0.016504874, -7006.0894, 0.054140497", - "Rotation": "0.70270085, -0.13145581, 0.6933918, -0.09021197", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "0.00012351386, -1549.6311, 0.090661116", + "Rotation": "0.6980561, -0.13482586, 0.6954317, -0.10446971", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_ude_a_l": { - "Position": "0.115434036, -7005.983, -0.103327535", - "Rotation": "-0.55067515, 0.55875856, -0.24172719, 0.5710632", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "-9.611249E-06, -1549.9999, -6.605685E-05", + "Rotation": "-0.5517502, 0.56356955, -0.23925002, 0.5663219", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_ude_a_r": { - "Position": "-0.16739282, -7005.98, 0.02708634", - "Rotation": "-0.3724639, 0.6751429, -0.46739674, 0.43242604", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "8.7827444E-05, -1550, -7.7251345E-05", + "Rotation": "-0.37386733, 0.67421985, -0.4614232, 0.4390206", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "n_kataarmor_l": { - "Position": "0.09400613, -7005.983, -0.09429261", - "Rotation": "0.026755188, 0.22700678, -0.13747494, 0.9637697", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "0.11282254, -1549.7201, -0.059858695", + "Rotation": "0.027943624, 0.22721498, -0.13966241, 0.9633726", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "n_kataarmor_r": { - "Position": "-0.14898911, -7005.9805, 0.030015208", - "Rotation": "-0.16089796, 0.9683705, 0.13075665, -0.13882534", - "Scale": "0.9999995, 0.9999995, 0.9999995" + "Position": "-0.13069992, -1549.7155, 0.06430428", + "Rotation": "-0.16798402, 0.9669279, 0.13334289, -0.13802595", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "j_ago": { - "Position": "-0.016832938, -8007.6465, 0.04476397", - "Rotation": "0.6795306, -0.22205189, 0.6756847, -0.17994584", - "Scale": "0.99999964, 0.99999964, 0.9999995" + "Position": "2.9232382E-05, -1549.631, 0.08145625", + "Rotation": "0.6744854, -0.22478673, 0.67584574, -0.19434777", + "Scale": "0.99999976, 0.99999976, 0.99999964" }, "j_asi_e_l": { - "Position": "0.2790786, -8004.1934, -0.14997458", - "Rotation": "-0.9750971, -0.04502815, -0.21692738, -0.009993844", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-8.702278E-06, -1549.9996, 0.00014699623", + "Rotation": "-0.97508335, -0.045251552, -0.21693689, -0.010150459", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_asi_e_r": { - "Position": "-0.24338467, -8004.22, 0.2335455", - "Rotation": "-0.7485973, 0.000101178885, -0.6630244, 0.00018285215", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-2.3422763E-05, -1549.9999, -9.717047E-05", + "Rotation": "-0.7485829, 0.00016928876, -0.6630409, 0.0002419007", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_kami_a": { - "Position": "-0.01623262, -8007.6494, -0.057229068", - "Rotation": "-0.36855054, 0.7316656, -0.31196448, 0.48115855", - "Scale": "1.0000002, 1, 1" + "Position": "0.0010890076, -1549.579, -0.019404143", + "Rotation": "-0.3639462, 0.7347835, -0.30508626, 0.48431197", + "Scale": "1.0000004, 1.0000001, 1" }, "j_kami_f_l": { - "Position": "0.058001697, -8007.648, 0.024204131", - "Rotation": "0.610545, -0.57621175, 0.39733958, -0.37058792", - "Scale": "1.0000006, 1, 1.0000004" + "Position": "0.074743345, -1549.6105, 0.06219533", + "Rotation": "0.6029934, -0.58119214, 0.43095258, -0.33599627", + "Scale": "1.0000008, 1.0000002, 1.0000005" }, "j_kami_f_r": { - "Position": "-0.08970663, -8007.646, 0.027480243", - "Rotation": "0.64808667, -0.43947288, 0.45827928, -0.42050764", - "Scale": "1.0000002, 1, 1.0000002" + "Position": "-0.07309183, -1549.6042, 0.06376959", + "Rotation": "0.6365749, -0.4458399, 0.47720012, -0.41021726", + "Scale": "1.0000004, 1.0000001, 1.0000004" }, "j_mimi_l": { - "Position": "0.05982385, -8007.6475, 0.045121606", - "Rotation": "-0.15729739, 0.25183314, 0.36979827, 0.8803898", - "Scale": "0.9999995, 0.99999946, 0.99999946" + "Position": "0.07499072, -1549.5148, 0.08551439", + "Rotation": "-0.15026279, 0.24064039, 0.3778436, 0.8813324", + "Scale": "0.99999964, 0.9999996, 0.9999996" }, "j_mimi_r": { - "Position": "-0.079925686, -8007.6455, 0.048221223", - "Rotation": "0.41452926, 0.86386114, -0.17918433, 0.22316326", - "Scale": "0.9999995, 0.99999976, 0.99999976" + "Position": "-0.06488071, -1549.5089, 0.08698485", + "Rotation": "0.41257772, 0.8673963, -0.16427827, 0.22453395", + "Scale": "0.99999964, 0.9999999, 0.9999999" }, "j_ude_b_l": { - "Position": "0.18968448, -8007.3774, -0.2100761", - "Rotation": "-0.71055454, 0.33251548, -0.4251464, 0.4514375", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-8.909404E-05, -1549.9998, -1.1086464E-05", + "Rotation": "-0.7080499, 0.34742498, -0.41433892, 0.45418537", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_ude_b_r": { - "Position": "-0.26742852, -8007.3755, -0.04056578", - "Rotation": "-0.6026235, 0.48103243, -0.59736735, 0.22046363", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-2.2888184E-05, -1549.9999, -8.010864E-05", + "Rotation": "-0.6042117, 0.4788293, -0.5946823, 0.22804278", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_hkata_l": { - "Position": "0.115434036, -8007.3774, -0.103327535", - "Rotation": "-0.5538274, 0.5600879, -0.23863092, 0.5680067", - "Scale": "0.99999946, 1.0012813, 1.0012813" + "Position": "-9.611249E-06, -1549.9999, -6.605685E-05", + "Rotation": "-0.5548762, 0.56488514, -0.23612717, 0.5632595", + "Scale": "0.9999996, 1.0012814, 1.0012814" }, "n_hkata_r": { - "Position": "-0.16739282, -8007.376, 0.02708634", - "Rotation": "-0.3724639, 0.6751429, -0.46739674, 0.43242604", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "8.7827444E-05, -1550, -7.7251345E-05", + "Rotation": "-0.37386733, 0.67421985, -0.4614232, 0.4390206", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_kami_b": { - "Position": "-0.04224673, -9009.26, -0.103719324", - "Rotation": "-0.47939694, 0.70153296, -0.3175505, 0.4209411", - "Scale": "1.0000005, 0.9999999, 0.99999994" + "Position": "-0.025019974, -1549.6603, -0.067349225", + "Rotation": "-0.48271182, 0.7057228, -0.31808537, 0.40959248", + "Scale": "1.0000006, 1, 1" }, "j_te_l": { - "Position": "0.29786605, -9008.513, -0.13128978", - "Rotation": "-0.5244576, 0.3483562, -0.5680112, 0.530052", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "-4.2043626E-05, -1549.9996, 6.86571E-05", + "Rotation": "-0.5046287, 0.38450256, -0.56131977, 0.53143907", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_te_r": { - "Position": "-0.31317246, -9008.51, 0.0910754", - "Rotation": "-0.62851113, 0.6615983, -0.37269032, 0.16841196", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "-8.985028E-05, -1549.9999, -9.800494E-05", + "Rotation": "-0.6354979, 0.6581574, -0.35876778, 0.18508525", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_buki_tate_l": { - "Position": "0.28482294, -9008.515, -0.20319004", - "Rotation": "-0.33251548, -0.71055454, -0.4514375, -0.4251464", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "0.09484034, -1550.0406, 0.003560437", + "Rotation": "-0.34742498, -0.7080499, -0.45418537, -0.41433892", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_buki_tate_r": { - "Position": "-0.34621456, -9008.51, 0.011269011", - "Rotation": "0.22046365, -0.59736735, -0.48103243, 0.6026235", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "-0.07824499, -1550.0438, 0.051244102", + "Rotation": "0.22804281, -0.59468234, -0.47882926, 0.6042117", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_ear_a_l": { - "Position": "0.09841968, -9009.322, -0.008129615", - "Rotation": "0.1567435, 0.0065806955, -0.029164225, 0.98718643", - "Scale": "0.99999946, 0.9999994, 0.99999946" + "Position": "0.11385624, -1549.4823, 0.033614237", + "Rotation": "0.16920824, 0.0018538308, -0.02146554, 0.98534447", + "Scale": "0.9999995, 0.9999996, 0.99999964" }, "n_ear_a_r": { - "Position": "-0.11719443, -9009.325, -0.0033477433", - "Rotation": "0.156742, 0.006581366, -0.029164523, 0.9871866", - "Scale": "0.99999964, 1, 0.99999976" + "Position": "-0.101793304, -1549.4729, 0.035764184", + "Rotation": "0.16920678, 0.0018544572, -0.021465922, 0.98534477", + "Scale": "0.99999976, 1.0000001, 0.9999999" }, "n_hhiji_l": { - "Position": "0.18968448, -9008.516, -0.2100761", - "Rotation": "-0.6407242, 0.4526884, -0.3388091, 0.5193781", - "Scale": "0.9999994, 1.1566534, 1.0705037" + "Position": "-8.909404E-05, -1549.9998, -1.1086464E-05", + "Rotation": "-0.63879853, 0.46257457, -0.3312275, 0.517928", + "Scale": "0.99999946, 1.1466762, 1.0660139" }, "n_hhiji_r": { - "Position": "-0.26742852, -9008.511, -0.04056578", - "Rotation": "-0.49715942, 0.5893893, -0.54285616, 0.33280498", - "Scale": "0.9999994, 1.1805027, 1.0811754" + "Position": "-2.2888184E-05, -1549.9999, -8.010864E-05", + "Rotation": "-0.49878934, 0.5878422, -0.53853667, 0.34004223", + "Scale": "0.99999946, 1.1812356, 1.0811756" }, "n_hijisoubi_l": { - "Position": "0.19403283, -9008.516, -0.1972442", - "Rotation": "-0.6407242, 0.4526884, -0.3388091, 0.5193781", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "0.0042126044, -1550.0027, 0.012023442", + "Rotation": "-0.6387985, 0.46257457, -0.33122757, 0.51792806", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_hijisoubi_r": { - "Position": "-0.26495066, -9008.511, -0.024925433", - "Rotation": "-0.49715942, 0.5893893, -0.54285616, 0.33280498", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "0.0024601643, -1550.0021, 0.015525928", + "Rotation": "-0.49878925, 0.58784217, -0.5385368, 0.34004226", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_hte_l": { - "Position": "0.29786605, -9008.513, -0.13128978", - "Rotation": "-0.64325464, 0.33453107, -0.4311719, 0.5370314", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "0.107587494, -1550.2247, 0.070351854", + "Rotation": "-0.63864905, 0.34911183, -0.4225426, 0.54009795", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "n_hte_r": { - "Position": "-0.31317246, -9008.51, 0.0910754", - "Rotation": "-0.60240346, 0.5875583, -0.51053655, 0.1767397", - "Scale": "0.9999994, 0.9999994, 0.9999994" + "Position": "-0.043078225, -1550.2202, 0.12956436", + "Rotation": "-0.60531163, 0.5853419, -0.5073336, 0.18326214", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "j_hito_a_l": { - "Position": "0.30234143, -10009.422, -0.08125143", - "Rotation": "-0.09564388, -0.29197416, -0.44918087, 0.83895135", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.0017143376, -1550.0875, 0.044072293", + "Rotation": "-0.078457825, -0.26456165, -0.4772296, 0.83432794", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_hito_a_r": { - "Position": "-0.30710977, -10009.424, 0.13600962", - "Rotation": "-0.45572984, 0.7696581, 0.10608104, -0.43437636", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.008663366, -1550.0885, 0.041756593", + "Rotation": "-0.475779, 0.76292527, 0.11691982, -0.42179275", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_ko_a_l": { - "Position": "0.31489426, -10009.426, -0.14771059", - "Rotation": "-0.090752184, 0.0885957, -0.6996815, 0.7031075", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.012491252, -1550.0951, -0.02316185", + "Rotation": "-0.07129193, 0.121132255, -0.7171111, 0.682639", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_ko_a_r": { - "Position": "-0.35265395, -10009.424, 0.084803075", - "Rotation": "-0.7280302, 0.6497304, 0.1731658, -0.13354982", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "-0.03674356, -1550.0914, -0.009487184", + "Rotation": "-0.74221504, 0.63301176, 0.1829044, -0.12230553", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_kusu_a_l": { - "Position": "0.31420183, -10009.425, -0.12500773", - "Rotation": "-0.057004094, 0.0025590062, -0.72515374, 0.6862185", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.01236503, -1550.094, -0.00036187842", + "Rotation": "-0.040420946, 0.035684843, -0.74484754, 0.66505235", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_kusu_a_r": { - "Position": "-0.34035847, -10009.424, 0.1040961", - "Rotation": "-0.6121836, 0.74967146, 0.16998523, -0.18527879", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "-0.024560442, -1550.0911, 0.009704504", + "Rotation": "-0.6303464, 0.73408264, 0.18098597, -0.17615266", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_naka_a_l": { - "Position": "0.30979967, -10009.423, -0.102676675", - "Rotation": "-0.041086227, -0.19264165, -0.54811966, 0.812875", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.008601076, -1550.0907, 0.02231988", + "Rotation": "-0.021013955, -0.16322345, -0.5957613, 0.78612", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_naka_a_r": { - "Position": "-0.32479033, -10009.424, 0.12121355", - "Rotation": "-0.579488, 0.7129074, 0.18994087, -0.34623468", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "-0.009005875, -1550.0897, 0.026961733", + "Rotation": "-0.59772533, 0.70127696, 0.20497245, -0.33003178", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_oya_a_l": { - "Position": "0.27375102, -10009.425, -0.10195996", - "Rotation": "0.23324403, -0.71086884, -0.30532867, 0.5890983", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "-0.023995737, -1550.0131, 0.029085401", + "Rotation": "0.23448874, -0.6984235, -0.3445339, 0.581821", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_oya_a_r": { - "Position": "-0.28033978, -10009.426, 0.10421512", - "Rotation": "-0.20577407, 0.39539334, 0.44172674, -0.77858716", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0.03326793, -1550.018, 0.012402649", + "Rotation": "-0.22567149, 0.38309577, 0.43916243, -0.78067034", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "n_buki_l": { - "Position": "0.27830753, -9.425781, -0.117516935", - "Rotation": "0.3483562, 0.5244576, 0.530052, 0.5680112", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "0, 0, 0", + "Rotation": "8.940697E-08, 2.0861626E-07, 2.9802322E-07, 0.9999999", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "n_buki_r": { - "Position": "-0.3056404, -9.425781, 0.09253702", - "Rotation": "-0.6615983, -0.62851113, -0.16841196, -0.37269032", - "Scale": "0.99999934, 0.99999934, 0.99999934" + "Position": "-7.517543E-05, -1000, -0.00015269034", + "Rotation": "3.725472E-08, 2.8309287E-07, 2.905608E-07, 0.9999999", + "Scale": "1.0000001, 0.9997645, 0.9997707" }, "n_ear_b_l": { - "Position": "0.09793762, -10011.028, -0.010626901", - "Rotation": "7.4505806E-08, 0.00666601, -5.811453E-07, 0.99997735", - "Scale": "0.99999994, 0.9999995, 0.9999997" + "Position": "0.11352091, -1549.4897, 0.030953234", + "Rotation": "-0.020612683, 0.0031736502, -0.005133116, 0.99976873", + "Scale": "1, 0.9999998, 1" }, "n_ear_b_r": { - "Position": "-0.11767629, -10011.04, -0.005845384", - "Rotation": "-1.4901161E-08, 0.0066666966, -6.221235E-07, 0.99997735", - "Scale": "1.0000001, 1.0000001, 1.0000001" + "Position": "-0.102138676, -1549.4806, 0.033021245", + "Rotation": "-0.040729467, 0.0030978038, -0.0027415825, 0.99916124", + "Scale": "1.0000005, 1.0000005, 1.0000002" }, "j_hito_b_l": { - "Position": "0.32278818, -11010.243, -0.05361174", - "Rotation": "0.15506199, -0.26524037, -0.9257761, 0.22032103", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "0.021057693, -1550.1238, 0.06880612", + "Rotation": "0.14941688, -0.23199804, -0.9437378, 0.18223602", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_hito_b_r": { - "Position": "-0.317058, -11010.249, 0.16346335", - "Rotation": "-0.8684182, 0.2142734, 0.38420856, -0.2287352", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.00045373198, -1550.1283, 0.067352735", + "Rotation": "-0.8852322, 0.15743163, 0.39157563, -0.19557065", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_ko_b_l": { - "Position": "0.31508636, -11010.243, -0.1476214", - "Rotation": "-0.12529506, -0.01965465, -0.9820621, -0.1395292", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "0.010362869, -1550.132, -0.025484394", + "Rotation": "-0.13996232, 0.012888529, -0.97295237, -0.18332572", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_ko_b_r": { - "Position": "-0.34911206, -11010.248, 0.081894994", - "Rotation": "-0.9624121, -0.16106129, 0.21254396, 0.051449254", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.031775735, -1550.1279, -0.013818254", + "Rotation": "-0.95511985, -0.1983253, 0.20875557, 0.06952542", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_kusu_b_l": { - "Position": "0.31166807, -11010.244, -0.121128835", - "Rotation": "-0.043879323, -0.03647767, -0.99818254, 0.019376308", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "0.006872809, -1550.1427, 0.00025616493", + "Rotation": "-0.053876728, -0.0021351592, -0.99796826, -0.033939447", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_kusu_b_r": { - "Position": "-0.34926695, -11010.247, 0.10751003", - "Rotation": "-0.96708477, -0.03902799, 0.25023755, 0.024583906", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.031754375, -1550.1393, 0.011276164", + "Rotation": "-0.9643577, -0.0789185, 0.24887173, 0.04299449", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_naka_b_l": { - "Position": "0.32636994, -11010.242, -0.08440709", - "Rotation": "0.10714955, -0.16528113, -0.96235, 0.18730521", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "0.020668088, -1550.1381, 0.036647324", + "Rotation": "0.10251248, -0.12874268, -0.97905827, 0.11983772", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_naka_b_r": { - "Position": "-0.32931048, -11010.248, 0.13516353", - "Rotation": "-0.9106597, 0.121417165, 0.37568706, -0.121717736", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.01235467, -1550.1394, 0.037986137", + "Rotation": "-0.9195018, 0.059845, 0.3795522, -0.08291468", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_oya_b_l": { - "Position": "0.25896695, -11010.321, -0.049826667", - "Rotation": "0.5022719, -0.554491, -0.5185816, 0.41392693", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.040037997, -1550.0676, 0.078140385", + "Rotation": "0.49967113, -0.54139555, -0.5523904, 0.38997975", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "j_oya_b_r": { - "Position": "-0.25805867, -11010.322, 0.13675791", - "Rotation": "-0.3669274, 0.25306752, 0.7548117, -0.48122743", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "0.057420187, -1550.0826, 0.042394042", + "Rotation": "-0.38148198, 0.2283888, 0.75919753, -0.47531986", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "n_sippo_a": { - "Position": "-0.06675451, -4002.1052, -0.05506751", - "Rotation": "-0.21427661, 0.71957505, -0.14159927, 0.6451716", - "Scale": "0.9999997, 0.9999997, 0.9999997" + "Position": "2.6077032E-08, -1550, 1.4901161E-08", + "Rotation": "-0.21644351, 0.7052213, -0.14145027, 0.6601565", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "n_sippo_b": { - "Position": "-0.07810624, -5003.0596, -0.18523967", - "Rotation": "-0.36219904, 0.88390356, -0.08660388, 0.28288746", - "Scale": "0.9999998, 0.9999998, 0.9999998" + "Position": "-1.1483207E-05, -1549.9999, 1.5258789E-05", + "Rotation": "-0.42774802, 0.8420323, -0.12339146, 0.30460966", + "Scale": "0.9999999, 0.99999994, 1.0000001" }, "n_sippo_c": { - "Position": "-0.16474222, -6003.923, -0.25084287", - "Rotation": "-0.2554871, 0.9502097, -0.121238574, 0.13087483", - "Scale": "0.9999998, 0.99999994, 0.9999998" + "Position": "0.0018242225, -1549.9991, -0.0038166158", + "Rotation": "-0.53520435, 0.7931897, -0.2719582, 0.10219679", + "Scale": "1, 1, 0.9999999" }, "n_sippo_d": { - "Position": "-0.29002166, -7004.6455, -0.27885792", - "Rotation": "-0.04424259, 0.8275071, 0.03845892, 0.55838585", - "Scale": "0.9999998, 0.99999994, 0.9999997" + "Position": "0.03917456, -1550.0217, 0.0126848295", + "Rotation": "-0.32186863, 0.8306823, -0.025257021, 0.4535736", + "Scale": "0.9999999, 1.0000002, 0.99999994" }, "n_sippo_e": { - "Position": "-0.34589615, -8005.2573, -0.41798902", - "Rotation": "-0.024777405, 0.8063859, 0.051253803, 0.5886428", - "Scale": "0.9999998, 0.9999999, 0.9999996" + "Position": "0.07125033, -1550.0803, 0.020018786", + "Rotation": "-0.28953594, 0.8472249, -0.011976872, 0.4452362", + "Scale": "0.99999976, 1, 0.9999999" }, "iv_ko_c_l": { - "Position": "0.2978875, -12011.025, -0.14317009", - "Rotation": "-0.12529504, -0.019654648, -0.98206204, -0.13952918", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.0060725957, -1550.1252, -0.020365683", + "Rotation": "-0.13996229, 0.012888525, -0.9729523, -0.18332571", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "iv_kusu_c_l": { - "Position": "0.28728062, -12011.017, -0.11894797", - "Rotation": "-0.04387932, -0.036477666, -0.9981825, 0.019376306", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.017422758, -1550.141, 0.0028924355", + "Rotation": "-0.053876724, -0.0021351585, -0.9979682, -0.03393944", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "iv_naka_c_l": { - "Position": "0.30324456, -12011.02, -0.088087134", - "Rotation": "0.10714954, -0.16528112, -0.96234995, 0.1873052", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.0035615917, -1550.1449, 0.03237185", + "Rotation": "0.102512464, -0.12874267, -0.9790582, 0.119837716", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "iv_hito_c_l": { - "Position": "0.3022721, -12011.033, -0.05769728", - "Rotation": "0.15506198, -0.26524034, -0.92577606, 0.22032101", - "Scale": "0.9999993, 0.9999992, 0.9999993" + "Position": "-0.0003410019, -1550.1337, 0.064048804", + "Rotation": "0.14941686, -0.23199801, -0.94373775, 0.18223599", + "Scale": "0.99999946, 0.9999994, 0.99999946" }, "iv_ko_c_r": { - "Position": "-0.33324346, -12011.037, 0.07463311", - "Rotation": "-0.96241206, -0.16106127, 0.21254395, 0.05144925", - "Scale": "0.9999993, 0.9999993, 0.9999993" + "Position": "-0.01630053, -1550.1204, -0.020665107", + "Rotation": "-0.9551198, -0.19832529, 0.20875555, 0.06952541", + "Scale": "0.99999946, 0.99999946, 0.99999946" }, "iv_kusu_c_r": { - "Position": "-0.32790998, -12011.024, 0.095699", - "Rotation": "-0.9670847, -0.039027985, 0.25023752, 0.024583904", - "Scale": "0.9999992, 0.9999992, 0.9999993" + "Position": "-0.010535799, -1550.135, -0.00033129565", + "Rotation": "-0.9643576, -0.07891849, 0.24887171, 0.04299449", + "Scale": "0.9999994, 0.9999994, 0.99999946" }, "iv_naka_c_r": { - "Position": "-0.31176046, -12011.027, 0.11846887", - "Rotation": "-0.9106596, 0.12141716, 0.37568703, -0.12171773", - "Scale": "0.9999994, 0.9999994, 0.9999993" + "Position": "0.0056975745, -1550.1439, 0.020439385", + "Rotation": "-0.9195017, 0.059845, 0.37955216, -0.082914665", + "Scale": "0.9999996, 0.9999996, 0.99999946" }, "iv_hito_c_r": { - "Position": "-0.30234748, -12011.039, 0.1498006", - "Rotation": "-0.86841816, 0.21427338, 0.38420853, -0.22873518", - "Scale": "0.9999993, 0.9999992, 0.9999993" + "Position": "0.015119288, -1550.1387, 0.0521719", + "Rotation": "-0.88523215, 0.15743159, 0.39157557, -0.19557062", + "Scale": "0.99999946, 0.9999994, 0.99999946" }, "iv_asi_oya_a_l": { - "Position": "0.27315217, -9004.202, -0.11476794", - "Rotation": "-0.97509706, -0.045028146, -0.21692736, -0.009993843", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.0059123714, -1549.9817, 0.03535283", + "Rotation": "-0.9750833, -0.045251545, -0.21693689, -0.010150455", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_oya_b_l": { - "Position": "0.2951424, -10004.2295, -0.104474194", - "Rotation": "-0.975097, -0.045028143, -0.21692735, -0.009993842", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.016105145, -1549.9794, 0.045656875", + "Rotation": "-0.97508323, -0.04525154, -0.21693687, -0.010150453", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_hito_a_l": { - "Position": "0.2893434, -9004.202, -0.13424459", - "Rotation": "-0.97509706, -0.045028146, -0.21692736, -0.009993843", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.0102551505, -1549.9841, 0.015867744", + "Rotation": "-0.9750833, -0.045251545, -0.21693689, -0.010150455", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_hito_b_l": { - "Position": "0.30158532, -10004.227, -0.1285141", - "Rotation": "-0.975097, -0.045028143, -0.21692735, -0.009993842", - "Scale": "0.99999946, 0.9999994, 0.99999946" + "Position": "0.022498127, -1549.9828, 0.02159429", + "Rotation": "-0.97508323, -0.04525154, -0.21693687, -0.010150453", + "Scale": "0.9999997, 0.99999964, 0.9999997" }, "iv_asi_naka_a_l": { - "Position": "0.2920006, -9004.202, -0.15146388", - "Rotation": "-0.97509706, -0.045028146, -0.21692736, -0.009993843", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.012910435, -1549.9846, -0.0013483582", + "Rotation": "-0.9750833, -0.045251545, -0.21693689, -0.010150455", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_naka_b_l": { - "Position": "0.30424252, -10004.227, -0.14573336", - "Rotation": "-0.975097, -0.045028143, -0.21692735, -0.009993842", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.025138853, -1549.9833, 0.0043735113", + "Rotation": "-0.97508323, -0.04525154, -0.21693687, -0.010150453", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_kusu_a_l": { - "Position": "0.28972054, -9004.202, -0.17109092", - "Rotation": "-0.97509706, -0.045028146, -0.21692736, -0.009993843", - "Scale": "0.99999946, 0.9999994, 0.99999946" + "Position": "0.010639533, -1549.9856, -0.020977281", + "Rotation": "-0.9750833, -0.045251545, -0.21693689, -0.010150455", + "Scale": "0.99999964, 0.9999996, 0.99999964" }, "iv_asi_kusu_b_l": { - "Position": "0.30196247, -10004.226, -0.1653604", - "Rotation": "-0.975097, -0.045028143, -0.21692735, -0.009993842", - "Scale": "0.99999946, 0.9999994, 0.99999946" + "Position": "0.022897104, -1549.9843, -0.015246012", + "Rotation": "-0.97508323, -0.04525154, -0.21693687, -0.010150453", + "Scale": "0.9999997, 0.9999996, 0.9999997" }, "iv_asi_ko_a_l": { - "Position": "0.2892616, -9004.202, -0.18740322", - "Rotation": "-0.97509706, -0.045028146, -0.21692736, -0.009993843", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.010191208, -1549.9862, -0.037284087", + "Rotation": "-0.9750833, -0.045251545, -0.21693689, -0.010150455", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_ko_b_l": { - "Position": "0.29885674, -10004.225, -0.18291166", - "Rotation": "-0.975097, -0.045028143, -0.21692735, -0.009993842", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.019778114, -1549.9852, -0.032798626", + "Rotation": "-0.97508323, -0.04525154, -0.21693687, -0.010150453", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_oya_a_r": { - "Position": "-0.2078917, -9004.237, 0.2404908", - "Rotation": "-0.74859726, 0.00010117888, -0.66302437, 0.00018285213", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.035475187, -1549.9829, 0.006857594", + "Rotation": "-0.7485829, 0.00016928873, -0.66304076, 0.00024190069", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_oya_b_r": { - "Position": "-0.2049462, -10004.271, 0.2646963", - "Rotation": "-0.7485972, 0.00010117887, -0.6630243, 0.00018285212", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.038429312, -1549.9829, 0.031071868", + "Rotation": "-0.74858284, 0.00016928872, -0.6630407, 0.0002419007", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_hito_a_r": { - "Position": "-0.23147349, -9004.237, 0.24954993", - "Rotation": "-0.74859726, 0.00010117888, -0.66302437, 0.00018285213", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "0.011890877, -1549.986, 0.015913244", + "Rotation": "-0.7485829, 0.00016928873, -0.66304076, 0.00024190069", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_hito_b_r": { - "Position": "-0.22983375, -10004.269, 0.26302508", - "Rotation": "-0.7485972, 0.00010117887, -0.6630243, 0.00018285212", - "Scale": "0.99999946, 0.99999934, 0.99999946" + "Position": "0.013535421, -1549.986, 0.029393304", + "Rotation": "-0.74858284, 0.00016928872, -0.6630407, 0.0002419007", + "Scale": "0.9999997, 0.9999996, 0.9999997" }, "iv_asi_naka_a_r": { - "Position": "-0.24866645, -9004.237, 0.24669139", - "Rotation": "-0.74859726, 0.00010117888, -0.66302437, 0.00018285213", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.0053045307, -1549.986, 0.013051715", + "Rotation": "-0.7485829, 0.00016928873, -0.66304076, 0.00024190069", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_naka_b_r": { - "Position": "-0.24702668, -10004.269, 0.26016656", - "Rotation": "-0.7485972, 0.00010117887, -0.6630243, 0.00018285212", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.003659937, -1549.986, 0.02653173", + "Rotation": "-0.74858284, 0.00016928872, -0.6630407, 0.0002419007", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_kusu_a_r": { - "Position": "-0.26661253, -9004.237, 0.23836799", - "Rotation": "-0.74859726, 0.00010117888, -0.66302437, 0.00018285213", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.02325368, -1549.986, 0.00472451", + "Rotation": "-0.7485829, 0.00016928873, -0.66304076, 0.00024190069", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_kusu_b_r": { - "Position": "-0.26497278, -10004.269, 0.25184315", - "Rotation": "-0.7485972, 0.00010117887, -0.6630243, 0.00018285212", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.02160912, -1549.986, 0.018204553", + "Rotation": "-0.74858284, 0.00016928872, -0.6630407, 0.0002419007", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_asi_ko_a_r": { - "Position": "-0.28197435, -9004.237, 0.2328205", - "Rotation": "-0.74859726, 0.00010117888, -0.66302437, 0.00018285213", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.038617913, -1549.986, -0.00082603766", + "Rotation": "-0.7485829, 0.00016928873, -0.66304076, 0.00024190069", + "Scale": "0.99999964, 0.99999964, 0.99999964" }, "iv_asi_ko_b_r": { - "Position": "-0.2806891, -10004.269, 0.24338222", - "Rotation": "-0.7485972, 0.00010117887, -0.6630243, 0.00018285212", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.037328847, -1549.986, 0.009739512", + "Rotation": "-0.74858284, 0.00016928872, -0.6630407, 0.0002419007", + "Scale": "0.9999997, 0.9999997, 0.9999997" }, "iv_nitoukin_l": { - "Position": "0.15255928, -8007.3774, -0.15670191", - "Rotation": "-0.1126838, -0.5548879, -0.19184722, 0.8016207", - "Scale": "0.9999995, 0.99999946, 0.9999995" + "Position": "0.035940256, -1550.128, -0.053801946", + "Rotation": "-0.115558885, -0.54917485, -0.19210199, 0.80507755", + "Scale": "0.99999964, 0.9999996, 0.99999964" }, "iv_nitoukin_r": { - "Position": "-0.21741068, -8007.376, -0.0067397915", - "Rotation": "-0.34075296, -0.51880705, -0.40453207, 0.67162466", - "Scale": "0.99999946, 0.99999946, 0.99999946" + "Position": "-0.048021134, -1550.1304, -0.035521924", + "Rotation": "-0.3326717, -0.52027476, -0.40334263, 0.6752466", + "Scale": "0.9999996, 0.9999996, 0.9999996" }, "iv_c_mune_l": { - "Position": "0.0105283735, -6004.5483, -0.050711107", - "Rotation": "-0.051751822, -0.43075606, 0.09334484, 0.89613456", - "Scale": "0.99999964, 0.99999976, 0.99999964" + "Position": "0.028916039, -1549.9325, -0.019067379", + "Rotation": "-0.05030101, -0.4325655, 0.09502133, 0.89516896", + "Scale": "0.99999976, 0.9999999, 0.99999976" }, "iv_c_mune_r": { - "Position": "-0.05492037, -6004.5464, -0.01909484", - "Rotation": "0.037087686, 0.62186426, -0.09891303, -0.77596706", - "Scale": "0.99999964, 0.99999964, 0.99999964" + "Position": "-0.036884002, -1549.935, 0.012097887", + "Rotation": "0.035289153, 0.6234247, -0.10020523, -0.77463204", + "Scale": "0.99999976, 0.99999976, 0.99999976" }, "iv_kougan_l": { - "Position": "0.045663305, -4002.107, 0.0951607", - "Rotation": "-0.27661005, 0.38079628, 0.56974274, -0.6737015", - "Scale": "0.9999995, 0.99999964, 0.99999964" + "Position": "0.054206684, -1550.1583, 0.072416574", + "Rotation": "-0.27754757, 0.3851705, 0.56412613, -0.6755532", + "Scale": "0.9999996, 0.9999997, 0.9999997" }, "iv_kougan_r": { - "Position": "0.021077033, -4002.107, 0.11169332", - "Rotation": "-0.6737016, 0.56974274, -0.3807963, 0.27661002", - "Scale": "0.99999976, 0.99999976, 0.99999976" + "Position": "0.029463952, -1550.1565, 0.08871944", + "Rotation": "-0.6755533, 0.56412613, -0.38517052, 0.27754754", + "Scale": "0.9999998, 0.9999998, 0.9999998" }, "iv_ochinko_a": { - "Position": "0.03384135, -4002.107, 0.103291705", - "Rotation": "-0.8789784, -0.076664835, -0.4645891, -0.07533853", - "Scale": "0.99999964, 0.99999964, 0.99999976" + "Position": "0.042247307, -1550.1498, 0.08036791", + "Rotation": "-0.8762973, -0.08193612, -0.46833634, -0.07778207", + "Scale": "0.9999997, 0.9999997, 0.9999998" }, "iv_ochinko_b": { - "Position": "0.05092551, -5003.01, 0.12800747", - "Rotation": "-0.8789783, -0.07666483, -0.46458906, -0.07533852", - "Scale": "0.99999964, 0.99999964, 0.99999976" + "Position": "0.05904167, -1550.1431, 0.10515079", + "Rotation": "-0.87629724, -0.08193611, -0.46833625, -0.07778207", + "Scale": "0.9999997, 0.9999997, 0.9999998" }, "iv_ochinko_c": { - "Position": "0.06800966, -6003.9194, 0.15272324", - "Rotation": "-0.8723592, -0.13217318, -0.45888567, -0.104607895", - "Scale": "0.99999964, 0.9999996, 0.99999976" + "Position": "0.07585743, -1550.1365, 0.12995133", + "Rotation": "-0.86934966, -0.13726412, -0.46247065, -0.107283846", + "Scale": "0.99999976, 0.9999997, 0.9999998" }, "iv_ochinko_d": { - "Position": "0.08542428, -7004.836, 0.17747203", - "Rotation": "-0.87235916, -0.13217317, -0.45888564, -0.10460789", - "Scale": "0.99999964, 0.9999996, 0.99999976" + "Position": "0.09297902, -1550.1256, 0.15478942", + "Rotation": "-0.8693496, -0.1372641, -0.46247062, -0.10728384", + "Scale": "0.9999998, 0.9999997, 0.9999998" }, "iv_ochinko_e": { - "Position": "0.10283887, -8005.763, 0.20222077", - "Rotation": "-0.8688182, -0.15373713, -0.4561542, -0.115940385", - "Scale": "0.99999964, 0.9999996, 0.99999976" + "Position": "0.1101363, -1550.1149, 0.1795851", + "Rotation": "-0.8656835, -0.15875196, -0.4596718, -0.11870428", + "Scale": "0.9999998, 0.9999997, 0.9999998" }, "iv_ochinko_f": { - "Position": "0.11626909, -9006.701, 0.22116767", - "Rotation": "-0.86881816, -0.15373711, -0.45615417, -0.11594038", - "Scale": "0.99999964, 0.9999996, 0.99999976" + "Position": "0.12335145, -1550.1053, 0.19860941", + "Rotation": "-0.86568344, -0.15875195, -0.45967177, -0.11870428", + "Scale": "0.9999998, 0.9999997, 0.9999998" }, "iv_kuritto": { - "Position": "0.023580315, -4002.107, 0.08918862", - "Rotation": "0.1813549, -0.42857713, -0.39623138, 0.79147464", - "Scale": "1, 0.9999999, 1.0000001" + "Position": "0.032087855, -1550.1473, 0.06615259", + "Rotation": "0.17498218, -0.4725485, -0.39261138, 0.7693727", + "Scale": "0.99999994, 1, 1.0000002" }, "iv_inshin_l": { - "Position": "0.0066398717, -4002.1064, 0.05276805", - "Rotation": "-0.24977274, 0.3989142, 0.52207226, -0.71128136", - "Scale": "0.9999983, 0.9999997, 0.99999976" + "Position": "0.015588272, -1550.1632, 0.029729253", + "Rotation": "-0.2504073, 0.4033425, 0.5163416, -0.71274257", + "Scale": "0.99999833, 0.99999976, 0.9999998" }, "iv_inshin_r": { - "Position": "-0.003947027, -4002.1064, 0.05988703", - "Rotation": "-0.7112815, 0.5220721, -0.39891425, 0.24977265", - "Scale": "0.99999964, 0.99999964, 0.99999976" + "Position": "0.004934003, -1550.1625, 0.036749303", + "Rotation": "-0.7127427, 0.51634145, -0.40334255, 0.25040722", + "Scale": "0.9999997, 0.9999997, 0.9999998" }, "iv_omanko": { - "Position": "-0.0009933924, -4002.1064, 0.05207765", - "Rotation": "-0.24276346, 0.4032181, 0.50956255, -0.7202961", - "Scale": "1.0000055, 0.9999999, 0.99999976" + "Position": "0.007923538, -1550.1586, 0.028929686", + "Rotation": "-0.24332051, 0.40765682, 0.50380737, -0.72165686", + "Scale": "1.0000055, 0.99999994, 0.9999998" }, "iv_koumon": { - "Position": "-0.017593112, -4002.1062, 0.024335703", - "Rotation": "-0.43451837, 0.18086661, 0.8373387, -0.27810866", - "Scale": "0.9999997, 0.9999997, 0.99999976" + "Position": "-0.008526446, -1550.1472, 0.00094103627", + "Rotation": "-0.43759796, 0.18411142, 0.83351, -0.28261584", + "Scale": "0.99999976, 0.99999976, 0.9999998" }, "iv_koumon_l": { - "Position": "-0.017593112, -4002.1062, 0.024335703", - "Rotation": "-0.5693141, 0.67555785, -0.19232807, 0.42721477", - "Scale": "0.99999976, 0.9999999, 0.99999976" + "Position": "-0.008526446, -1550.1472, 0.00094103627", + "Rotation": "-0.57308584, 0.67055273, -0.19613254, 0.42832604", + "Scale": "0.9999998, 0.99999994, 0.9999998" }, "iv_koumon_r": { - "Position": "-0.017593112, -4002.1062, 0.024335703", - "Rotation": "-0.44881943, 0.7552422, -0.4035962, 0.25549898", - "Scale": "0.99999976, 0.99999976, 0.99999976" + "Position": "-0.008526446, -1550.1472, 0.00094103627", + "Rotation": "-0.45122275, 0.75050545, -0.4079172, 0.25834566", + "Scale": "0.9999998, 0.9999998, 0.9999998" }, "iv_shiri_l": { - "Position": "0.019906597, -4002.106, -0.04065509", - "Rotation": "-0.46988147, 0.027023368, 0.8821979, 0.014393648", - "Scale": "1, 1, 1.0000001" + "Position": "0.029254502, -1550.112, -0.06404251", + "Rotation": "-0.4732864, 0.03726659, 0.88009644, -0.006362951", + "Scale": "1, 1.0000001, 1.0000001" }, "iv_shiri_r": { - "Position": "-0.08981418, -4002.1057, 0.033124723", - "Rotation": "0.014393687, 0.8821979, -0.02702339, 0.46988165", - "Scale": "0.9999997, 0.9999997, 0.9999999" + "Position": "-0.081164524, -1550.1041, 0.008711992", + "Rotation": "0.0051279846, 0.8801041, -0.031084264, 0.4737329", + "Scale": "0.99999976, 0.99999964, 0.99999994" }, "iv_kyokin_phys_l": { - "Position": "0.03732989, -5003.294, -0.011139292", - "Rotation": "0.022727668, -0.1651301, -0.040835336, 0.9851635", - "Scale": "0.9999997, 0.99999994, 0.99999994" + "Position": "0.05506066, -1549.863, 0.02065643", + "Rotation": "0.02198437, -0.19178449, -0.034160722, 0.9805957", + "Scale": "1, 1.0000001, 1.0000001" }, "iv_kyokin_phys_r": { - "Position": "-0.044486634, -5003.2935, 0.028319228", - "Rotation": "0.057132974, -0.8139575, -0.028884888, 0.5773853", - "Scale": "1.0000004, 1, 1.0000004" + "Position": "-0.026900712, -1549.8661, 0.059743192", + "Rotation": "0.050581504, -0.8211075, -0.021341609, 0.5681266", + "Scale": "1.0000007, 1.0000004, 1.0000006" }, "iv_fukubu_phys": { - "Position": "0.019399585, -4002.1067, 0.06470646", - "Rotation": "0.122168794, 0.5101604, -0.08830422, -0.8467661", - "Scale": "0.9999997, 0.9999999, 0.99999976" + "Position": "2.4214387E-08, -1550, 1.4901161E-08", + "Rotation": "0.123459205, 0.5123246, -0.09444663, -0.8446069", + "Scale": "0.99999976, 0.99999994, 0.9999998" }, "iv_fukubu_phys_l": { - "Position": "0.06331239, -4002.1067, 0.023368584", - "Rotation": "-0.1507331, 0.09288211, -0.0015783459, 0.9841998", - "Scale": "0.99999976, 0.99999976, 0.99999976" + "Position": "2.2351742E-08, -1550, 1.3038516E-08", + "Rotation": "-0.15542102, 0.08985841, 0.0025950065, 0.9837492", + "Scale": "0.9999998, 0.9999998, 0.9999998" }, "iv_fukubu_phys_r": { - "Position": "-0.04158414, -4002.1062, 0.076627865", - "Rotation": "0.045783073, 0.91350424, -0.1436204, -0.37787077", - "Scale": "0.9999997, 0.9999995, 0.99999964" + "Position": "2.6077032E-08, -1550, 1.4901161E-08", + "Rotation": "0.04317076, 0.91396165, -0.14932735, -0.374848", + "Scale": "0.99999976, 0.9999996, 0.9999997" }, "iv_daitai_phys_l": { - "Position": "0.07598785, -5003.039, -0.0043630437", - "Rotation": "-0.6782463, 0.5930673, -0.22928251, 0.36835054", - "Scale": "0.99999964, 0.9999997, 0.9999997" + "Position": "2.6490213E-08, -1550, 5.051693E-08", + "Rotation": "-0.67491174, 0.5966252, -0.2272577, 0.36998126", + "Scale": "0.9999997, 0.99999976, 0.99999976" }, "iv_daitai_phys_r": { - "Position": "-0.07807202, -5003.0503, 0.09923181", - "Rotation": "-0.5572142, 0.6190636, -0.4485211, 0.32419258", - "Scale": "0.99999964, 0.99999964, 0.9999997" + "Position": "8.750614E-09, -1550, 5.0410502E-09", + "Rotation": "-0.5567528, 0.6194317, -0.44825456, 0.3246505", + "Scale": "0.9999997, 0.9999997, 0.99999976" }, "iv_kintama_phys_l": { - "Position": "0.037439413, -4002.107, 0.09908948", - "Rotation": "0.43388408, -0.28551334, -0.55834025, 0.64690185", - "Scale": "1.0000015, 0.99999976, 1.0000002" + "Position": "0.04600889, -1550.1659, 0.07634227", + "Rotation": "0.38450405, -0.3411598, -0.5709994, 0.6400978", + "Scale": "1.0000015, 0.9999998, 1.0000004" }, "iv_kintama_phys_r": { - "Position": "0.026999446, -4002.107, 0.10610961", - "Rotation": "0.24945214, -0.4024771, -0.6616439, 0.58138835", - "Scale": "1.0000006, 1, 1" + "Position": "0.035502512, -1550.165, 0.08326476", + "Rotation": "0.20006883, -0.45372564, -0.6660099, 0.5572568", + "Scale": "1.0000006, 0.99999994, 1.0000001" }, "iv_funyachin_phy_a": { - "Position": "0.035471253, -4002.107, 0.10282367", - "Rotation": "0.80822897, -0.36263147, 0.43366927, -0.16490728", - "Scale": "0.99999976, 0.99999964, 1" + "Position": "0.04367249, -1550.1235, 0.079675585", + "Rotation": "0.7698084, -0.35854185, 0.5105821, -0.13471328", + "Scale": "0.99999976, 0.9999997, 1" }, "iv_funyachin_phy_b": { - "Position": "0.045843575, -5003.036, 0.119535275", - "Rotation": "0.753353, -0.46691352, 0.40648025, -0.22186399", - "Scale": "0.9999999, 0.99999976, 0.99999994" + "Position": "0.05005979, -1550.1433, 0.09952769", + "Rotation": "0.7389419, -0.45682496, 0.44001997, -0.22728229", + "Scale": "0.99999976, 0.9999998, 0.99999994" }, "iv_funyachin_phy_c": { - "Position": "0.05268035, -6003.9443, 0.13139962", - "Rotation": "0.6861913, -0.5626615, 0.36817488, -0.2774876", - "Scale": "0.9999998, 0.99999976, 0.99999976" + "Position": "0.05574978, -1550.169, 0.11249464", + "Rotation": "0.6769576, -0.5496874, 0.39188272, -0.2932557", + "Scale": "0.99999994, 0.9999998, 0.99999976" }, "iv_funyachin_phy_d": { - "Position": "0.05517282, -7004.8267, 0.13642578", - "Rotation": "0.63816595, -0.6167785, 0.34283787, -0.3078788", - "Scale": "0.99999976, 0.9999997, 0.99999964" + "Position": "0.05805873, -1550.1943, 0.117815845", + "Rotation": "0.6284518, -0.60431516, 0.3676745, -0.32352105", + "Scale": "0.99999994, 0.9999996, 0.9999998" }, "j_f_face": { - "Position": "-0.016642204, -8007.6465, 0.054010797", - "Rotation": "0.090211965, -0.6933917, -0.13145578, 0.70270073", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.00012351386, -1549.6311, 0.090661116", + "Rotation": "0.10446964, -0.69543135, -0.13482578, 0.69805574", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_ago": { - "Position": "-0.016413322, -9009.201, 0.053903986", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.00046264986, -1549.6233, 0.09062846", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_dhoho_l": { - "Position": "0.020749459, -9009.202, 0.06675188", - "Rotation": "0.17771694, -0.19673175, -0.10057825, 0.9589559", - "Scale": "0.9999995, 0.99999976, 0.99999964" + "Position": "0.037851788, -1549.6595, 0.103204735", + "Rotation": "0.1916374, -0.20022395, -0.09547286, 0.956069", + "Scale": "0.99999964, 0.9999999, 0.99999976" }, "j_f_dhoho_r": { - "Position": "-0.05676519, -9009.201, 0.068476126", - "Rotation": "-0.04322592, 0.95846987, 0.19054778, -0.20774367", - "Scale": "0.9999994, 0.99999976, 0.99999946" + "Position": "-0.03962651, -1549.6565, 0.104010805", + "Rotation": "-0.053449083, 0.9569733, 0.20084608, -0.20249322", + "Scale": "0.9999995, 0.9999999, 0.9999996" }, "j_f_dmemoto_l": { - "Position": "0.0007299278, -9009.2, 0.114603445", - "Rotation": "0.06871045, -0.68905365, -0.1525696, 0.7051278", - "Scale": "0.9999995, 0.9999997, 0.9999995" + "Position": "0.017127985, -1549.6406, 0.15120071", + "Rotation": "0.08310327, -0.6909892, -0.15600023, 0.70092005", + "Scale": "0.99999964, 0.9999998, 0.99999964" }, "j_f_dmemoto_r": { - "Position": "-0.03257238, -9009.199, 0.1153969", - "Rotation": "0.11162929, -0.69708264, -0.1102193, 0.69961786", - "Scale": "0.9999995, 0.9999997, 0.9999995" + "Position": "-0.016287956, -1549.6392, 0.1515084", + "Rotation": "0.12573841, -0.69922394, -0.11352539, 0.6945394", + "Scale": "0.99999964, 0.9999998, 0.99999964" }, "j_f_dmiken_l": { - "Position": "-0.0024133828, -9009.2, 0.11931841", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.013657463, -1549.6238, 0.15631828", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_dmiken_r": { - "Position": "-0.027361503, -9009.199, 0.1199898", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.011292707, -1549.6226, 0.15663171", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_dslip_l": { - "Position": "0.006055245, -9009.2, 0.092554495", - "Rotation": "0.12560904, -0.44960976, -0.09818953, 0.8788806", - "Scale": "0.99999964, 0.99999976, 0.99999964" + "Position": "0.023142265, -1549.6716, 0.12837991", + "Rotation": "0.14021966, -0.45295322, -0.097109765, 0.8750649", + "Scale": "0.99999976, 0.9999999, 0.99999976" }, "j_f_dslip_r": { - "Position": "-0.042368524, -9009.2, 0.09362261", - "Rotation": "-0.046440598, 0.87280667, 0.1525191, -0.46128973", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.025416551, -1549.6694, 0.12899216", + "Rotation": "-0.05902171, 0.87335277, 0.16002592, -0.45624596", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eye_l": { - "Position": "0.011502633, -9009.2, 0.10007708", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.027724808, -1549.6129, 0.13753432", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eye_r": { - "Position": "-0.040941827, -9009.2, 0.1013283", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.024848578, -1549.6106, 0.1381497", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eyeprm_01_l": { - "Position": "-0.016909232, -9009.202, 0.04453509", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eyeprm_01_r": { - "Position": "-0.016909232, -9009.202, 0.04453509", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eyeprmroll_l": { - "Position": "0.003133187, -9009.201, 0.053553034", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.02006345, -1549.632, 0.09044318", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_eyeprmroll_r": { - "Position": "-0.03676855, -9009.201, 0.05449908", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.019887405, -1549.6301, 0.09092058", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_hagukiup": { - "Position": "-0.017931571, -9009.2, 0.09667437", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.0010080952, -1549.6696, 0.13229503", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_hana_l": { - "Position": "-0.0105158, -9009.199, 0.122049734", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.0059118504, -1549.6532, 0.15816568", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_hana_r": { - "Position": "-0.022440543, -9009.199, 0.12238543", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.0060706255, -1549.6527, 0.1583542", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_hoho_l": { - "Position": "0.0261587, -9009.201, 0.09937517", - "Rotation": "0.17638609, -0.41778976, -0.08964831, 0.88673663", - "Scale": "0.99999964, 0.9999997, 0.99999964" + "Position": "0.042619728, -1549.633, 0.13648736", + "Rotation": "0.19082174, -0.42095137, -0.08780277, 0.8824258", + "Scale": "0.99999976, 0.9999998, 0.99999976" }, "j_f_hoho_r": { - "Position": "-0.057711236, -9009.199, 0.1013283", - "Rotation": "-0.036354363, 0.880879, 0.20124975, -0.42688155", - "Scale": "0.99999946, 0.9999997, 0.9999995" + "Position": "-0.041301787, -1549.6295, 0.1374046", + "Rotation": "-0.04886396, 0.8806682, 0.20914578, -0.4222454", + "Scale": "0.9999996, 0.9999998, 0.99999964" }, "j_f_mab_l": { - "Position": "0.011502633, -9009.2, 0.10007708", - "Rotation": "0.10274973, -0.5661009, -0.12410246, 0.8084365", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.027724808, -1549.6129, 0.13753432", + "Rotation": "0.11742663, -0.5688215, -0.1250924, 0.80436444", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mab_r": { - "Position": "-0.040941827, -9009.2, 0.1013283", - "Rotation": "0.07672411, -0.8013482, -0.13674155, 0.5772822", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.024848578, -1549.6106, 0.1381497", + "Rotation": "0.09017357, -0.80261856, -0.14238824, 0.57218444", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mayu_l": { - "Position": "0.03408564, -9009.201, 0.109934255", - "Rotation": "0.13574854, -0.29265887, -0.07679784, 0.9434109", - "Scale": "0.9999995, 0.9999997, 0.99999964" + "Position": "0.04994545, -1549.6055, 0.1479116", + "Rotation": "0.1499766, -0.29662248, -0.07326079, 0.9402938", + "Scale": "0.99999964, 0.9999998, 0.99999976" }, "j_f_mayu_r": { - "Position": "-0.06193792, -9009.199, 0.11211626", - "Rotation": "-0.021280173, 0.93950886, 0.15345353, -0.30548525", - "Scale": "0.99999934, 0.9999997, 0.99999946" + "Position": "-0.046126015, -1549.6014, 0.14896163", + "Rotation": "-0.032370012, 0.9392345, 0.16299859, -0.300366", + "Scale": "0.99999946, 0.9999998, 0.9999996" }, "j_f_miken_01_l": { - "Position": "-0.0010782387, -9009.199, 0.13305132", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.01467967, -1549.6149, 0.17012051", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_miken_01_r": { - "Position": "-0.027033439, -9009.199, 0.1335396", - "Rotation": "0.09021195, -0.69339156, -0.13145575, 0.7027006", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.011282103, -1549.6139, 0.1704618", + "Rotation": "0.10446958, -0.695431, -0.1348257, 0.6980554", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mmayu_l": { - "Position": "0.020322213, -9009.2, 0.124247", - "Rotation": "0.1211613, -0.48789257, -0.10362795, 0.8582196", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.036078498, -1549.6086, 0.1618529", + "Rotation": "0.13580532, -0.49106473, -0.103192896, 0.85426044", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mmayu_r": { - "Position": "-0.04796087, -9009.199, 0.12589495", - "Rotation": "-0.053114787, 0.8516371, 0.15032509, -0.49929368", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.03226781, -1549.6056, 0.1626814", + "Rotation": "-0.066014394, 0.8524048, 0.15727034, -0.4942788", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_shoho_l": { - "Position": "0.013440499, -9009.201, 0.081324026", - "Rotation": "0.25495198, -0.26838663, -0.22262636, 0.90188944", - "Scale": "0.9999995, 0.9999997, 0.9999995" + "Position": "0.030556997, -1549.6704, 0.1173237", + "Rotation": "0.26939082, -0.2694694, -0.21830533, 0.89841807", + "Scale": "0.99999964, 0.9999998, 0.99999964" }, "j_f_shoho_r": { - "Position": "-0.049440973, -9009.2, 0.08236162", - "Rotation": "-0.16651401, 0.90669477, 0.27432474, -0.2737192", - "Scale": "0.99999934, 0.99999976, 0.99999934" + "Position": "-0.03245762, -1549.6676, 0.11770796", + "Rotation": "-0.17772079, 0.9037385, 0.2827544, -0.26780453", + "Scale": "0.99999946, 0.9999999, 0.99999946" }, "j_f_uhana": { - "Position": "-0.015215507, -9009.199, 0.13401262", - "Rotation": "-0.031564787, -0.6985225, -0.00743597, 0.71485204", - "Scale": "0.9999995, 0.9999997, 0.9999995" + "Position": "0.0007683388, -1549.6362, 0.17056075", + "Rotation": "-0.017877884, -0.7030068, -0.011561379, 0.7108625", + "Scale": "0.99999964, 0.9999998, 0.99999964" }, "j_f_ulip_01_l": { - "Position": "-0.012957206, -9009.2, 0.109186575", - "Rotation": "0.07809685, -0.6948604, -0.119171925, 0.70488775", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.0037481987, -1549.6625, 0.1450424", + "Rotation": "0.09231671, -0.69714826, -0.12262243, 0.700302", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_ulip_01_r": { - "Position": "-0.02160894, -9009.2, 0.109430715", - "Rotation": "0.07809685, -0.6948604, -0.119171925, 0.70488775", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.0048902486, -1549.662, 0.14517757", + "Rotation": "0.09231671, -0.69714826, -0.12262243, 0.700302", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_umlip_01_l": { - "Position": "-0.0031992104, -9009.2, 0.10233538", - "Rotation": "0.08721272, -0.4482214, -0.1019401, 0.88379776", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.013599656, -1549.6632, 0.1383252", + "Rotation": "0.10190352, -0.45180702, -0.10104846, 0.88049567", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_umlip_01_r": { - "Position": "-0.03171026, -9009.2, 0.10303728", - "Rotation": "-0.050761532, 0.8779541, 0.1141974, -0.4621445", - "Scale": "0.99999934, 0.99999976, 0.99999934" + "Position": "-0.014943477, -1549.6621, 0.13859642", + "Rotation": "-0.06314888, 0.87895507, 0.12174062, -0.4567569", + "Scale": "0.99999946, 0.9999999, 0.99999946" }, "j_f_uslip_l": { - "Position": "0.0061925743, -9009.201, 0.09313433", - "Rotation": "0.12560904, -0.44960976, -0.09818953, 0.8788806", - "Scale": "0.99999964, 0.99999976, 0.99999964" + "Position": "0.02326184, -1549.6697, 0.1290714", + "Rotation": "0.14021966, -0.45295322, -0.097109765, 0.8750649", + "Scale": "0.99999976, 0.9999999, 0.99999976" }, "j_f_uslip_r": { - "Position": "-0.042261712, -9009.2, 0.094202444", - "Rotation": "-0.046440598, 0.87280667, 0.1525191, -0.46128973", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "-0.025332704, -1549.6676, 0.12964328", + "Rotation": "-0.05902171, 0.87335277, 0.16002592, -0.45624596", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_bero_01": { - "Position": "-0.018732658, -10010.764, 0.049860407", - "Rotation": "0.011137888, -0.6991465, -0.051062755, 0.7130646", - "Scale": "0.9999995, 0.9999999, 0.99999946" + "Position": "-0.0010654898, -1549.658, 0.08575296", + "Rotation": "0.02507297, -0.70278656, -0.05493688, 0.70883036", + "Scale": "0.99999964, 1, 0.9999996" }, "j_f_dago": { - "Position": "-0.017298331, -10010.764, 0.050867487", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-2.3109606E-06, -1549.6324, 0.087373346", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_dlip_01_l": { - "Position": "-0.01529943, -10010.763, 0.09478228", - "Rotation": "0.19757158, -0.67074245, -0.23976384, 0.67348486", - "Scale": "0.99999946, 0.99999976, 0.9999995" + "Position": "0.0022106306, -1549.6862, 0.12996352", + "Rotation": "0.21197264, -0.6705261, -0.24236555, 0.66836923", + "Scale": "0.9999996, 0.9999999, 0.99999964" }, "j_f_dlip_01_r": { - "Position": "-0.02324926, -10010.763, 0.094934866", - "Rotation": "0.19757158, -0.67074245, -0.23976384, 0.67348486", - "Scale": "0.99999946, 0.99999976, 0.9999995" + "Position": "-0.0057110945, -1549.6857, 0.1300333", + "Rotation": "0.21197264, -0.6705261, -0.24236555, 0.66836923", + "Scale": "0.9999996, 0.9999999, 0.99999964" }, "j_f_dmlip_01_l": { - "Position": "-0.005335441, -10010.763, 0.092661306", - "Rotation": "0.2825301, -0.44145834, -0.15775397, 0.83690107", - "Scale": "0.99999964, 0.9999999, 0.9999995" + "Position": "0.012096474, -1549.6815, 0.12807652", + "Rotation": "0.29691258, -0.44274148, -0.15587051, 0.83157897", + "Scale": "0.99999976, 1, 0.99999964" }, "j_f_dmlip_01_r": { - "Position": "-0.032686822, -10010.763, 0.093302175", - "Rotation": "-0.10475508, 0.8343897, 0.3100258, -0.44351184", - "Scale": "0.99999946, 0.9999999, 0.99999946" + "Position": "-0.015242526, -1549.6805, 0.12839209", + "Rotation": "-0.117828846, 0.8324674, 0.31678957, -0.4390389", + "Scale": "0.9999996, 1, 0.9999996" }, "j_f_eyeprm_02_l": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.090211935, -0.6933914, -0.13145572, 0.70270044", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.104469515, -0.6954305, -0.13482562, 0.6980549", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_eyeprm_02_r": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.090211935, -0.6933914, -0.13145572, 0.70270044", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.104469515, -0.6954305, -0.13482562, 0.6980549", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_eyepuru_l": { - "Position": "0.011235604, -10010.772, 0.100229666", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.027724808, -1549.6129, 0.13753432", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_eyepuru_r": { - "Position": "-0.041208856, -10010.775, 0.101374075", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-0.024848578, -1549.6106, 0.1381497", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_hagukidn": { - "Position": "-0.018923393, -10010.763, 0.09018938", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-0.0014225915, -1549.6787, 0.12563986", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_irisprm_l": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_irisprm_r": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_mabdn_01_l": { - "Position": "0.011212716, -10010.772, 0.09878008", - "Rotation": "0.19949135, -0.5396582, -0.2626003, 0.7746041", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.027855407, -1549.6128, 0.13642968", + "Rotation": "0.2144177, -0.53978866, -0.262868, 0.7704217", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_mabdn_01_r": { - "Position": "-0.041470163, -10010.774, 0.10021441", - "Rotation": "0.2147109, -0.77585065, -0.23490834, 0.54476696", - "Scale": "0.9999994, 0.9999999, 0.99999946" + "Position": "-0.025019396, -1549.6104, 0.13707925", + "Rotation": "0.22817649, -0.7747659, -0.23958406, 0.53876597", + "Scale": "0.9999995, 1, 0.9999996" }, "j_f_mabup_01_l": { - "Position": "0.011716256, -10010.772, 0.1002907", - "Rotation": "0.05301977, -0.57290184, -0.053170294, 0.81617624", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.028380072, -1549.6129, 0.13783845", + "Rotation": "0.06740369, -0.576891, -0.054511383, 0.8122057", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mabup_01_r": { - "Position": "-0.0419985, -10010.774, 0.10178606", - "Rotation": "0.0065900683, -0.8049855, -0.08590775, 0.5870031", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-0.025527699, -1549.6102, 0.13851649", + "Rotation": "0.019877613, -0.807423, -0.0919772, 0.5824167", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_miken_02_l": { - "Position": "-0.0066095497, -10010.7705, 0.13158648", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.009494862, -1549.6194, 0.16856386", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_miken_02_r": { - "Position": "-0.02260839, -10010.771, 0.1318001", - "Rotation": "0.090211935, -0.69339144, -0.13145572, 0.7027005", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-0.0065572355, -1549.6184, 0.16886157", + "Rotation": "0.10446952, -0.69543064, -0.13482563, 0.698055", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_ulip_02_l": { - "Position": "-0.013834586, -10010.724, 0.10660784", - "Rotation": "0.07809684, -0.6948603, -0.1191719, 0.7048875", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.0033695048, -1549.6711, 0.14229317", + "Rotation": "0.09231664, -0.69714785, -0.12262234, 0.70030147", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_ulip_02_r": { - "Position": "-0.022394767, -10010.724, 0.1068825", - "Rotation": "0.07809684, -0.6948603, -0.1191719, 0.7048875", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "-0.0052538267, -1549.6708, 0.1424864", + "Rotation": "0.09231664, -0.69714785, -0.12262234, 0.70030147", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_umlip_02_l": { - "Position": "-0.004023185, -10010.723, 0.10045092", - "Rotation": "0.087212704, -0.44822124, -0.10194007, 0.8837975", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.013009687, -1549.6699, 0.13640018", + "Rotation": "0.10190347, -0.45180672, -0.101048395, 0.88049513", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_umlip_02_r": { - "Position": "-0.031988733, -10010.724, 0.101496145", - "Rotation": "-0.050761513, 0.8779539, 0.11419738, -0.46214435", - "Scale": "0.99999934, 0.9999999, 0.99999934" + "Position": "-0.01494493, -1549.6691, 0.13663962", + "Rotation": "-0.06314883, 0.87895447, 0.12174054, -0.45675656", + "Scale": "0.99999946, 1, 0.99999946" }, "j_f_bero_02": { - "Position": "-0.018530479, -11012.29, 0.065836355", - "Rotation": "0.09625937, -0.69257754, -0.13758284, 0.7015264", - "Scale": "0.99999964, 0.9999998, 0.99999946" + "Position": "-0.00095961645, -1549.6598, 0.10165623", + "Rotation": "0.110534154, -0.6944919, -0.14091198, 0.6968513", + "Scale": "0.99999976, 0.99999994, 0.9999996" }, "j_f_dlip_02_l": { - "Position": "-0.0153452065, -11012.263, 0.100733206", - "Rotation": "0.19757152, -0.6707423, -0.23976381, 0.6734847", - "Scale": "0.9999994, 0.99999976, 0.9999995" + "Position": "0.0026396567, -1549.6782, 0.13600446", + "Rotation": "0.21197246, -0.67052555, -0.24236536, 0.6683687", + "Scale": "0.9999995, 0.9999999, 0.99999964" }, "j_f_dlip_02_r": { - "Position": "-0.02361547, -11012.262, 0.10067217", - "Rotation": "0.19757152, -0.6707423, -0.23976381, 0.6734847", - "Scale": "0.9999994, 0.99999976, 0.9999995" + "Position": "-0.0053686877, -1549.6776, 0.13614951", + "Rotation": "0.21197246, -0.67052555, -0.24236536, 0.6683687", + "Scale": "0.9999995, 0.9999999, 0.99999964" }, "j_f_dmlip_02_l": { - "Position": "-0.0059457924, -11012.266, 0.09647171", - "Rotation": "0.28253007, -0.4414583, -0.15775397, 0.83690095", - "Scale": "0.9999995, 0.9999998, 0.9999995" + "Position": "0.012121504, -1549.6761, 0.13244648", + "Rotation": "0.29691243, -0.4427413, -0.15587044, 0.83157855", + "Scale": "0.99999964, 0.99999994, 0.99999964" }, "j_f_dmlip_02_r": { - "Position": "-0.0328623, -11012.267, 0.09818499", - "Rotation": "-0.10475506, 0.8343895, 0.31002575, -0.44351178", - "Scale": "0.9999994, 0.9999998, 0.9999994" + "Position": "-0.014662041, -1549.675, 0.13285889", + "Rotation": "-0.117828794, 0.83246696, 0.3167894, -0.4390387", + "Scale": "0.9999995, 0.99999994, 0.9999995" }, "j_f_mabdn_02out_l": { - "Position": "0.009320626, -11012.345, 0.0993294", - "Rotation": "0.17584506, -0.6051156, -0.27898777, 0.72462195", - "Scale": "0.99999964, 0.9999998, 0.99999964" + "Position": "0.026950117, -1549.6129, 0.13679124", + "Rotation": "0.19069126, -0.6048809, -0.28055528, 0.72044396", + "Scale": "0.99999976, 0.99999994, 0.99999976" }, "j_f_mabdn_02out_r": { - "Position": "-0.041782968, -11012.348, 0.101007864", - "Rotation": "0.23436743, -0.7254184, -0.21530107, 0.61031365", - "Scale": "0.99999964, 0.9999998, 0.99999946" + "Position": "-0.024137815, -1549.6104, 0.13744281", + "Rotation": "0.24818921, -0.7248606, -0.2187853, 0.6042408", + "Scale": "0.99999976, 0.99999994, 0.9999996" }, "j_f_mabdn_03in_l": { - "Position": "0.008313546, -11012.344, 0.099481985", - "Rotation": "0.17584506, -0.6051156, -0.27898777, 0.72462195", - "Scale": "0.99999964, 0.9999998, 0.99999964" + "Position": "0.025962515, -1549.6128, 0.13721366", + "Rotation": "0.19069126, -0.6048809, -0.28055528, 0.72044396", + "Scale": "0.99999976, 0.99999994, 0.99999976" }, "j_f_mabdn_03in_r": { - "Position": "-0.040753, -11012.348, 0.101496145", - "Rotation": "0.23436743, -0.7254184, -0.21530107, 0.61031365", - "Scale": "0.99999964, 0.9999998, 0.99999946" + "Position": "-0.023129333, -1549.6105, 0.13776822", + "Rotation": "0.24818921, -0.7248606, -0.2187853, 0.6042408", + "Scale": "0.99999976, 0.99999994, 0.9999996" }, "j_f_mabup_02out_l": { - "Position": "0.010609994, -11012.345, 0.10057299", - "Rotation": "0.048183896, -0.64185625, -0.05758894, 0.76313865", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.02742304, -1549.6128, 0.13818958", + "Rotation": "0.062396176, -0.6454838, -0.06017854, 0.75883514", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mabup_02out_r": { - "Position": "-0.041138284, -11012.348, 0.10229723", - "Rotation": "0.01405232, -0.75076145, -0.08500646, 0.6549284", - "Scale": "0.9999995, 0.9999998, 0.99999964" + "Position": "-0.024601392, -1549.6102, 0.13884926", + "Rotation": "0.02781828, -0.75358903, -0.089894705, 0.6505717", + "Scale": "0.99999964, 0.99999994, 0.99999976" }, "j_f_mabup_03in_l": { - "Position": "0.009694466, -11012.344, 0.100927755", - "Rotation": "0.048183896, -0.64185625, -0.05758894, 0.76313865", - "Scale": "0.9999995, 0.99999976, 0.9999995" + "Position": "0.026492195, -1549.613, 0.1384887", + "Rotation": "0.062396176, -0.6454838, -0.06017854, 0.75883514", + "Scale": "0.99999964, 0.9999999, 0.99999964" }, "j_f_mabup_03in_r": { - "Position": "-0.040268533, -11012.348, 0.10258715", - "Rotation": "0.01405232, -0.75076145, -0.08500646, 0.6549284", - "Scale": "0.9999995, 0.9999998, 0.99999964" + "Position": "-0.023650538, -1549.6104, 0.13915607", + "Rotation": "0.02781828, -0.75358903, -0.089894705, 0.6505717", + "Scale": "0.99999964, 0.99999994, 0.99999976" }, "j_f_bero_03": { - "Position": "-0.019308677, -12013.8125, 0.08010332", - "Rotation": "0.13237414, -0.6865903, -0.17410927, 0.69336426", - "Scale": "0.99999976, 0.99999994, 0.99999946" + "Position": "-0.0010098492, -1549.665, 0.11572124", + "Rotation": "0.14672945, -0.6877547, -0.1771891, 0.688521", + "Scale": "0.9999999, 1, 0.9999996" }, "j_f_noanim_ago": { - "Position": "-0.017275443, -9009.203, 0.04451983", - "Rotation": "0.6795304, -0.22205183, 0.67568445, -0.17994581", - "Scale": "0.99999934, 0.99999946, 0.9999995" + "Position": "2.9232382E-05, -1549.631, 0.08145625", + "Rotation": "0.67448485, -0.22478656, 0.6758452, -0.19434765", + "Scale": "0.99999946, 0.9999996, 0.99999964" }, "j_f_noanim_eyesize_l": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.09814422, -0.69410264, -0.12846038, 0.7014882", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.11237182, -0.69611835, -0.13179831, 0.69671905", + "Scale": "0.99999964, 1, 0.99999964" }, "j_f_noanim_eyesize_r": { - "Position": "-0.017222038, -10010.76, 0.044596124", - "Rotation": "0.09814422, -0.69410264, -0.12846038, 0.7014882", - "Scale": "0.9999995, 0.9999999, 0.9999995" + "Position": "0.00015941416, -1549.6278, 0.081282154", + "Rotation": "0.11237182, -0.69611835, -0.13179831, 0.69671905", + "Scale": "0.99999964, 1, 0.99999964" }, "j_ex_h0179_back_01_c": { - "Position": "-0.013201347, -8007.6494, -0.06081922", - "Rotation": "-0.35935616, 0.63876235, -0.41061872, 0.54243636", - "Scale": "0.99999946, 0.99999946, 0.9999999" + "Position": "0.0035234615, -1549.521, -0.021342844", + "Rotation": "-0.35085863, 0.6453699, -0.40462506, 0.54467654", + "Scale": "0.9999995, 0.99999976, 0.9999999" }, "j_ex_h0179_side_a01_l": { - "Position": "0.031987555, -8007.645, 0.13872759", - "Rotation": "0.40393114, -0.58983773, 0.42651248, -0.5540915", - "Scale": "0.9999995, 0.99999964, 0.9999995" + "Position": "0.04698825, -1549.5819, 0.17733745", + "Rotation": "-0.46014994, 0.54102194, -0.47360337, 0.5208219", + "Scale": "0.99999976, 1.0000001, 0.99999976" }, "j_ex_h0179_side_a01_r": { - "Position": "-0.05516302, -8007.6436, 0.14026873", - "Rotation": "0.40393114, -0.58983773, 0.42651248, -0.5540915", - "Scale": "0.9999995, 0.99999964, 0.9999995" + "Position": "-0.040179394, -1549.5785, 0.17776534", + "Rotation": "-0.46012953, 0.54098886, -0.47340003, 0.5210591", + "Scale": "0.99999976, 1.0000001, 0.99999976" }, "j_ex_h0179_side_b01_l": { - "Position": "0.05664576, -8007.646, 0.11364977", - "Rotation": "-0.09848597, 0.5915007, -0.1031325, 0.7935934", - "Scale": "0.9999995, 0.99999964, 0.9999995" + "Position": "0.07175188, -1549.5658, 0.15294404", + "Rotation": "-0.091884024, 0.5871175, -0.09099975, 0.7991044", + "Scale": "0.99999964, 0.99999976, 0.99999964" }, "j_ex_h0179_side_b01_r": { - "Position": "-0.07898199, -8007.644, 0.116632864", - "Rotation": "-0.06107174, 0.81099534, -0.12886639, 0.56740576", - "Scale": "0.99999964, 0.99999976, 0.99999976" + "Position": "-0.06396433, -1549.5596, 0.15436053", + "Rotation": "-0.058618665, 0.8085669, -0.11527331, 0.57401544", + "Scale": "0.99999976, 0.9999999, 0.9999999" } }, "MainHand": { "n_root": { - "Position": "0, -1000, 0", + "Position": "0, 0, 0", "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", "Scale": "1, 1, 1" }, "n_hara": { - "Position": "0, -2000, 0", + "Position": "0, 0, 0", "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", "Scale": "0.99999994, 0.99999994, 0.99999994" } }, "OffHand": { "n_root": { - "Position": "9.124032, 2.019264, 1.2696509", - "Rotation": "-6.250944E-09, 1.0430816E-07, 3.7062628E-10, 0.99999994", - "Scale": "1.0001576, 0.99997276, 1.0000038" + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "1, 1, 1" }, "n_hara": { - "Position": "9.113761, 2.0131454, 1.263746", - "Rotation": "1.2491924E-08, 9.02219E-08, 3.5295212E-08, 0.99999994", - "Scale": "1.0000908, 0.99999, 1" + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" } }, + "Position": "-78.538475, 1.060323, 36.018433", + "Rotation": "0, 0.3695864, 0, 0.92919636", + "Scale": "1, 1, 1", "Author": null, "Description": null, "Version": null, diff --git a/Brio/Resources/Embedded/Data/BrioTPose.pose b/Brio/Resources/Embedded/Data/BrioTPose.pose new file mode 100644 index 00000000..5e7eca8f --- /dev/null +++ b/Brio/Resources/Embedded/Data/BrioTPose.pose @@ -0,0 +1,1297 @@ +{ + "TypeName": "Brio Pose", + "ModelDifference": { + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 1", + "Scale": "0, 0, 0" + }, + "ModelAbsoluteValues": { + "Position": "-0.0070150536, 41.386536, -138.16553", + "Rotation": "0, 0.010434319, 0, 0.9999456", + "Scale": "1, 1, 1" + }, + "Bones": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "-5.9604536E-14, 1.0767692, 4.7067012E-14", + "Rotation": "0, 0, 0, 0.9999998", + "Scale": "0.9999999, 0.9999999, 0.9999999" + }, + "n_throw": { + "Position": "-5.9604584E-14, 3.105873E-28, -7.1054185E-21", + "Rotation": "0, 0, 0, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + }, + "j_kosi": { + "Position": "-6.053587E-14, 1.0767692, 4.706694E-14", + "Rotation": "-0.55081683, 0.44351804, -0.55081683, 0.44327536", + "Scale": "0.9999997, 0.9999996, 0.9999997" + }, + "j_sebo_a": { + "Position": "-6.053587E-14, 1.0767692, 4.706694E-14", + "Rotation": "0.47380355, 0.52476853, 0.47380355, 0.5250124", + "Scale": "0.9999997, 0.9999998, 0.9999998" + }, + "j_asi_a_l": { + "Position": "0.09297474, 0.9623664, 0.02498788", + "Rotation": "-0.50759006, 0.4924021, -0.5076124, 0.49216047", + "Scale": "0.9999995, 0.9999993, 0.99999964" + }, + "j_asi_a_r": { + "Position": "-0.09302521, 0.9624161, 0.025028016", + "Rotation": "-0.50759006, 0.4924021, -0.5076124, 0.49216047", + "Scale": "0.9999995, 0.9999993, 0.99999964" + }, + "j_buki2_kosi_l": { + "Position": "0.16842723, 1.0478883, 0.023239058", + "Rotation": "-0.00024428964, 9.697676E-05, -0.7072113, 0.70700186", + "Scale": "0.9999995, 1.0000002, 0.9999988" + }, + "j_buki2_kosi_r": { + "Position": "-0.16843262, 1.0479783, 0.023311779", + "Rotation": "-0.7070223, 0.7071909, -9.214878E-05, -5.5253506E-05", + "Scale": "0.99999964, 1.0000002, 0.9999989" + }, + "j_buki_kosi_l": { + "Position": "0.16842723, 1.0478883, 0.023239058", + "Rotation": "9.453297E-05, 0.7071828, -9.4503164E-05, 0.70703065", + "Scale": "0.9999995, 0.9999997, 0.99999964" + }, + "j_buki_kosi_r": { + "Position": "-0.16843262, 1.0479783, 0.023311779", + "Rotation": "9.453297E-05, 0.7071828, -9.4503164E-05, 0.70703065", + "Scale": "0.9999995, 0.9999997, 0.99999964" + }, + "j_sebo_b": { + "Position": "3.752533E-05, 1.2228317, -0.014982477", + "Rotation": "0.4947296, 0.50508845, 0.4947395, 0.5053321", + "Scale": "0.99999964, 0.99999964, 0.99999976" + }, + "j_sk_b_a_l": { + "Position": "0.07997715, 1.0799724, -0.11001764", + "Rotation": "-0.47005785, 0.5283505, -0.4701081, 0.5281001", + "Scale": "0.9999999, 0.9999999, 1" + }, + "j_sk_b_a_r": { + "Position": "-0.080022804, 1.0800152, -0.10998311", + "Rotation": "-0.4700569, 0.5283516, -0.47010866, 0.5280995", + "Scale": "0.9999999, 1, 1" + }, + "j_sk_f_a_l": { + "Position": "0.08002887, 1.0799842, 0.12998258", + "Rotation": "0.47007418, -0.52700984, -0.4619476, 0.5365589", + "Scale": "1.0000186, 1.0000005, 1" + }, + "j_sk_f_a_r": { + "Position": "-0.07997112, 1.080027, 0.13001712", + "Rotation": "0.4616941, -0.5365708, -0.47032967, 0.5269917", + "Scale": "1.0000185, 1.0000004, 1.0000001" + }, + "j_sk_s_a_l": { + "Position": "0.16500302, 1.0791545, 0.011075876", + "Rotation": "-0.007604639, -0.008700259, -0.6519151, 0.7582039", + "Scale": "0.9999998, 0.99999994, 1.0000002" + }, + "j_sk_s_a_r": { + "Position": "-0.16499692, 1.0792428, 0.011147104", + "Rotation": "-0.6517101, 0.75837976, -0.0074534463, -0.008855582", + "Scale": "0.9999998, 0.9999999, 1" + }, + "j_asi_b_l": { + "Position": "0.092875496, 0.5820191, 0.03664579", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.9999991, 0.9999996" + }, + "j_asi_b_r": { + "Position": "-0.093124464, 0.5820699, 0.036685895", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.9999991, 0.9999996" + }, + "j_mune_l": { + "Position": "0.03640786, 1.2890183, -0.011461224", + "Rotation": "-0.03110633, -0.62148196, 0.030779313, 0.782205", + "Scale": "0.9999991, 0.99999934, 0.99999946" + }, + "j_mune_r": { + "Position": "-0.036304086, 1.2890351, -0.011479795", + "Rotation": "0.030968033, 0.7823568, -0.03095483, -0.6212889", + "Scale": "0.9999996, 0.99999946, 0.9999996" + }, + "j_sebo_c": { + "Position": "7.1252245E-05, 1.3658082, -0.017978534", + "Rotation": "0.51190376, 0.4876743, 0.51192206, 0.4879175", + "Scale": "0.99999946, 0.99999946, 0.9999997" + }, + "j_sk_b_b_l": { + "Position": "0.0799192, 0.8955877, -0.13156839", + "Rotation": "-0.47062403, 0.5278701, -0.47087988, 0.5273883", + "Scale": "0.9999998, 0.9999999, 1" + }, + "j_sk_b_b_r": { + "Position": "-0.080081396, 0.8956303, -0.13153394", + "Rotation": "-0.4705796, 0.5279188, -0.47091863, 0.52734447", + "Scale": "0.99999994, 0.99999994, 1" + }, + "j_sk_f_b_l": { + "Position": "0.08738961, 0.66869736, 0.18444669", + "Rotation": "0.4692996, -0.52997786, -0.49653456, 0.50232947", + "Scale": "1.0000182, 1.0000002, 1" + }, + "j_sk_f_b_r": { + "Position": "-0.08753457, 0.66873574, 0.18447986", + "Rotation": "0.49584857, -0.5028485, -0.47002807, 0.5294822", + "Scale": "1.0000185, 1.0000002, 1" + }, + "j_sk_s_b_l": { + "Position": "0.19773285, 0.86327994, 0.01612278", + "Rotation": "0.0062599555, 0.005875917, -0.6757839, 0.73704976", + "Scale": "0.9999998, 0.9999998, 1.0000002" + }, + "j_sk_s_b_r": { + "Position": "-0.19784239, 0.8633859, 0.01620235", + "Rotation": "-0.6751139, 0.7376635, 0.0063910927, 0.0057361308", + "Scale": "0.9999998, 0.99999994, 1" + }, + "j_asi_c_l": { + "Position": "0.09285854, 0.51930535, 0.035845533", + "Rotation": "-0.47089425, 0.5276041, -0.47093394, 0.5273647", + "Scale": "0.99999946, 0.9999991, 0.9999995" + }, + "j_asi_c_r": { + "Position": "-0.093141414, 0.519356, 0.03588564", + "Rotation": "-0.47089425, 0.5276041, -0.47093394, 0.5273647", + "Scale": "0.99999934, 0.9999991, 0.9999995" + }, + "j_buki_sebo_l": { + "Position": "0.10011753, 1.4759586, -0.09983562", + "Rotation": "-0.017234165, -0.017045029, 0.70689195, -0.70690554", + "Scale": "0.99999917, 0.9999996, 0.9999993" + }, + "j_buki_sebo_r": { + "Position": "-0.09988232, 1.4760047, -0.09988671", + "Rotation": "0.70682347, -0.7069784, -0.017047137, -0.017059475", + "Scale": "0.9999993, 0.9999997, 0.9999993" + }, + "j_kubi": { + "Position": "0.00010235656, 1.5083792, -0.01109577", + "Rotation": "0.6044724, 0.3667217, 0.6045424, 0.36695534", + "Scale": "0.99999946, 0.9999994, 0.99999964" + }, + "j_sako_l": { + "Position": "0.028292827, 1.3940656, -0.03391999", + "Rotation": "7.31647E-05, -8.925796E-06, 9.402633E-06, 0.99999976", + "Scale": "0.9999996, 0.99999917, 0.99999917" + }, + "j_sako_r": { + "Position": "-0.028128132, 1.3940786, -0.0339344", + "Rotation": "0.00024054945, 0.99999964, 7.31796E-05, 0.00024709105", + "Scale": "0.9999996, 0.99999917, 0.99999917" + }, + "j_sk_b_c_l": { + "Position": "0.07969021, 0.5918058, -0.16629377", + "Rotation": "-0.4747495, 0.52412415, -0.47461128, 0.5240714", + "Scale": "0.9999998, 0.99999994, 1" + }, + "j_sk_b_c_r": { + "Position": "-0.08036446, 0.5918489, -0.16626266", + "Rotation": "-0.4706314, 0.5285442, -0.47764343, 0.52058035", + "Scale": "0.99999976, 0.9999998, 1" + }, + "j_sk_f_c_l": { + "Position": "0.08080304, 0.5490284, 0.19242394", + "Rotation": "0.47514385, -0.5220983, -0.47546235, 0.52496403", + "Scale": "1.0000185, 1.0000004, 1" + }, + "j_sk_f_c_r": { + "Position": "-0.08123521, 0.5490489, 0.19245374", + "Rotation": "0.47750562, -0.52242243, -0.47314206, 0.52459484", + "Scale": "1.0000184, 1.0000001, 1" + }, + "j_sk_s_c_l": { + "Position": "0.22136453, 0.59134483, 0.011448363", + "Rotation": "0.0007866422, -0.00019364248, -0.67282766, 0.7397988", + "Scale": "0.9999999, 0.99999994, 1.0000002" + }, + "j_sk_s_c_r": { + "Position": "-0.22196937, 0.5914942, 0.011536183", + "Rotation": "-0.66908956, 0.7431809, 0.0010968653, -0.00024870737", + "Scale": "0.9999998, 0.99999994, 1" + }, + "n_hizasoubi_l": { + "Position": "0.09286739, 0.55202156, 0.036262996", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.9999991, 0.9999995" + }, + "n_hizasoubi_r": { + "Position": "-0.09313257, 0.5520723, 0.036303103", + "Rotation": "-0.49678603, 0.50330025, -0.49681363, 0.50305915", + "Scale": "0.9999995, 0.9999991, 0.9999995" + }, + "j_asi_d_l": { + "Position": "0.092733294, 0.090574145, -0.012895644", + "Rotation": "-0.6834413, 0.18170166, -0.6833428, 0.18147981", + "Scale": "0.9999994, 0.9999992, 0.99999946" + }, + "j_asi_d_r": { + "Position": "-0.09326666, 0.09062475, -0.012855552", + "Rotation": "-0.6834413, 0.18170166, -0.6833428, 0.18147981", + "Scale": "0.99999917, 0.9999991, 0.99999946" + }, + "j_kao": { + "Position": "0.000112611, 1.6139672, 0.043865114", + "Rotation": "0.70701605, -1.4394522E-05, 0.7071971, 0.00014907122", + "Scale": "0.99999917, 0.9999992, 0.9999996" + }, + "j_ude_a_l": { + "Position": "0.15606773, 1.4353812, -0.021994675", + "Rotation": "-0.6802281, 0.032828417, 0.019438282, 0.73200667", + "Scale": "0.9999996, 1.0000011, 1.0000008" + }, + "j_ude_a_r": { + "Position": "-0.1558911, 1.4354533, -0.022074489", + "Rotation": "0.019783035, 0.7319942, -0.6802301, 0.032859832", + "Scale": "0.999999, 0.9999976, 0.9999964" + }, + "n_kataarmor_l": { + "Position": "0.12227181, 1.4961883, -0.033903375", + "Rotation": "7.31647E-05, -8.925796E-06, 9.402633E-06, 0.99999976", + "Scale": "0.9999995, 0.9999991, 0.9999991" + }, + "n_kataarmor_r": { + "Position": "-0.122058965, 1.4962447, -0.033965886", + "Rotation": "0.00024054945, 0.99999964, 7.31796E-05, 0.00024709105", + "Scale": "0.9999995, 0.9999991, 0.9999991" + }, + "j_ago": { + "Position": "0.0001141856, 1.6110313, 0.035112772", + "Rotation": "0.7009652, -0.09229821, 0.70116615, -0.09215978", + "Scale": "0.9999995, 0.99999946, 0.9999996" + }, + "j_asi_e_l": { + "Position": "0.092741266, 0.017036304, 0.11570898", + "Rotation": "-0.7071827, 0.00016985834, -0.70703065, -1.9267201E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "j_asi_e_r": { + "Position": "-0.09325869, 0.017086908, 0.11574904", + "Rotation": "-0.7071827, 0.00016985834, -0.70703065, -1.9267201E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "j_kami_a": { + "Position": "0.00014656092, 1.626336, -0.0773012", + "Rotation": "-0.41120014, 0.57719, -0.41301432, 0.5720013", + "Scale": "1.0000002, 1, 1" + }, + "j_kami_f_l": { + "Position": "0.07411033, 1.6270804, 0.009847552", + "Rotation": "0.5756847, -0.41698027, 0.598251, -0.36987895", + "Scale": "1.0000006, 1, 1.0000004" + }, + "j_kami_f_r": { + "Position": "-0.07386159, 1.6271147, 0.009809714", + "Rotation": "0.5928525, -0.3736787, 0.582453, -0.41187212", + "Scale": "1.0000002, 1, 1.0000002" + }, + "j_mimi_l": { + "Position": "0.07014951, 1.7249885, -9.4130635E-05", + "Rotation": "-0.30316788, 0.2962366, 0.35009825, 0.83532256", + "Scale": "0.999999, 0.9999992, 0.99999917" + }, + "j_mimi_r": { + "Position": "-0.069850385, 1.725021, -0.00012890622", + "Rotation": "0.35036892, 0.8351658, -0.30314666, 0.2963804", + "Scale": "0.9999994, 0.99999917, 0.9999994" + }, + "j_ude_b_l": { + "Position": "0.44223216, 1.4307308, -0.04337796", + "Rotation": "-0.67973125, -0.041874133, -0.060854994, 0.7297317", + "Scale": "0.99999887, 0.9999992, 0.99999845" + }, + "j_ude_b_r": { + "Position": "-0.44204664, 1.4309354, -0.04360536", + "Rotation": "-0.06051095, 0.729757, -0.6797366, -0.04184312", + "Scale": "0.99999946, 0.99999934, 0.99999857" + }, + "n_hkata_l": { + "Position": "0.1560678, 1.435381, -0.021994691", + "Rotation": "-0.6802281, 0.032828417, 0.019438282, 0.73200667", + "Scale": "0.999999, 0.9999991, 0.99999845" + }, + "n_hkata_r": { + "Position": "-0.15589103, 1.4354533, -0.022074481", + "Rotation": "0.019783035, 0.7319942, -0.6802301, 0.032859832", + "Scale": "0.99999946, 0.99999934, 0.99999857" + }, + "j_kami_b": { + "Position": "-0.0005847566, 1.5334657, -0.10874065", + "Rotation": "-0.47118038, 0.5316926, -0.47476473, 0.5195098", + "Scale": "1.0000005, 1, 0.9999999" + }, + "j_te_l": { + "Position": "0.6986034, 1.4224652, -0.0060936064", + "Rotation": "-0.6810147, -0.002634231, -0.018702216, 0.73202586", + "Scale": "0.9999987, 0.9999992, 0.99999857" + }, + "j_te_r": { + "Position": "-0.69844097, 1.4227884, -0.006453272", + "Rotation": "-0.01835728, 0.7320313, -0.6810183, -0.002602961", + "Scale": "0.9999993, 0.9999993, 0.9999984" + }, + "n_buki_tate_l": { + "Position": "0.5188636, 1.4982566, -0.02737352", + "Rotation": "0.041874133, -0.67973125, -0.7297317, -0.060854994", + "Scale": "0.9999987, 0.99999917, 0.99999857" + }, + "n_buki_tate_r": { + "Position": "-0.5186552, 1.4984963, -0.027640313", + "Rotation": "-0.04184312, -0.6797366, -0.729757, 0.06051095", + "Scale": "0.9999993, 0.9999993, 0.9999985" + }, + "n_ear_a_l": { + "Position": "0.10815677, 1.7399638, -0.06009558", + "Rotation": "-0.0001501143, -3.758073E-05, -8.788705E-05, 0.99999976", + "Scale": "0.9999989, 0.99999917, 0.99999917" + }, + "n_ear_a_r": { + "Position": "-0.1078199, 1.7400143, -0.060149852", + "Rotation": "-0.00014945865, -0.0002194941, -0.0001468733, 0.99999964", + "Scale": "0.9999995, 0.9999994, 0.9999994" + }, + "n_hhiji_l": { + "Position": "0.44223225, 1.430731, -0.04337793", + "Rotation": "-0.68100446, -0.0045761354, -0.020789515, 0.73196954", + "Scale": "0.9999987, 0.99999905, 0.99999857" + }, + "n_hhiji_r": { + "Position": "-0.4420467, 1.4309354, -0.043605354", + "Rotation": "-0.020444598, 0.73197603, -0.68100816, -0.0045448765", + "Scale": "0.9999994, 0.9999993, 0.99999857" + }, + "n_hijisoubi_l": { + "Position": "0.44223225, 1.430731, -0.04337793", + "Rotation": "-0.68100446, -0.0045761354, -0.020789515, 0.73196954", + "Scale": "0.9999987, 0.99999905, 0.99999845" + }, + "n_hijisoubi_r": { + "Position": "-0.4420467, 1.4309354, -0.043605354", + "Rotation": "-0.020444598, 0.73197603, -0.68100816, -0.0045448765", + "Scale": "0.9999994, 0.9999993, 0.9999985" + }, + "n_hte_l": { + "Position": "0.6986034, 1.4224652, -0.0060936064", + "Rotation": "-0.6810147, -0.002634231, -0.018702216, 0.73202586", + "Scale": "0.9999987, 0.9999992, 0.99999857" + }, + "n_hte_r": { + "Position": "-0.69844097, 1.4227884, -0.006453272", + "Rotation": "-0.01835728, 0.7320313, -0.6810183, -0.002602961", + "Scale": "0.9999993, 0.9999993, 0.9999984" + }, + "j_hito_a_l": { + "Position": "0.79136384, 1.4192009, 0.026670076", + "Rotation": "0.035948396, -0.0150857605, -0.011363624, 0.9991751", + "Scale": "0.9999986, 0.99999934, 0.9999983" + }, + "j_hito_a_r": { + "Position": "-0.7912189, 1.4195668, 0.026262514", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.9999994, 0.999998" + }, + "j_ko_a_l": { + "Position": "0.7908955, 1.4206846, -0.04191868", + "Rotation": "0.036192298, -0.015088534, -0.011359941, 0.99916625", + "Scale": "0.9999986, 0.99999934, 0.9999983" + }, + "j_ko_a_r": { + "Position": "-0.7907155, 1.4210504, -0.042325955", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.9999994, 0.999998" + }, + "j_kusu_a_l": { + "Position": "0.7926697, 1.4234966, -0.019277783", + "Rotation": "0.036192298, -0.015088534, -0.011359941, 0.99916625", + "Scale": "0.9999986, 0.99999934, 0.9999983" + }, + "j_kusu_a_r": { + "Position": "-0.792499, 1.4238622, -0.019686073", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.999999, 0.9999994, 0.999998" + }, + "j_naka_a_l": { + "Position": "0.7922047, 1.4229218, 0.0039084554", + "Rotation": "0.035948396, -0.0150857605, -0.011363624, 0.9991751", + "Scale": "0.9999986, 0.99999934, 0.9999983" + }, + "j_naka_a_r": { + "Position": "-0.7920472, 1.4232872, 0.0035004374", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.9999994, 0.999998" + }, + "j_oya_a_l": { + "Position": "0.71325034, 1.4007016, 0.024071954", + "Rotation": "0.63501173, -0.37456238, -0.004487886, 0.6756054", + "Scale": "0.9999985, 0.9999992, 0.99999857" + }, + "j_oya_a_r": { + "Position": "-0.7131134, 1.4010315, 0.023703665", + "Rotation": "-0.0044956543, 0.6757025, 0.6350976, -0.37424123", + "Scale": "0.99999887, 0.9999992, 0.9999982" + }, + "n_buki_l": { + "Position": "0.7866492, 1.3898705, -0.0057039885", + "Rotation": "-0.002634231, 0.6810147, 0.73202586, 0.018702216", + "Scale": "0.9999986, 0.9999992, 0.9999985" + }, + "n_buki_r": { + "Position": "-0.78650105, 1.3902345, -0.006109186", + "Rotation": "-0.7320313, -0.01835728, 0.002602961, -0.6810183", + "Scale": "0.9999991, 0.9999992, 0.9999982" + }, + "n_ear_b_l": { + "Position": "0.10815521, 1.731884, -0.060093183", + "Rotation": "5.2186802E-05, -3.7726004E-05, -0.00044971937, 0.99999994", + "Scale": "1, 0.99999976, 0.99999976" + }, + "n_ear_b_r": { + "Position": "-0.1078222, 1.7319342, -0.06014764", + "Rotation": "5.0246228E-05, -0.000219623, -0.00043214514, 0.99999994", + "Scale": "1.0000002, 1.0000002, 1.0000001" + }, + "j_hito_b_l": { + "Position": "0.8393296, 1.4180588, 0.02807789", + "Rotation": "0.035948396, -0.0150857605, -0.011363624, 0.9991751", + "Scale": "0.99999857, 0.9999993, 0.9999982" + }, + "j_hito_b_r": { + "Position": "-0.83918583, 1.4184469, 0.027645595", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.99999934, 0.999998" + }, + "j_ko_b_l": { + "Position": "0.8278692, 1.4198042, -0.040833484", + "Rotation": "0.036192298, -0.015088534, -0.011359941, 0.99916625", + "Scale": "0.9999986, 0.9999993, 0.9999982" + }, + "j_ko_b_r": { + "Position": "-0.8276902, 1.4201874, -0.04125982", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.99999934, 0.999998" + }, + "j_kusu_b_l": { + "Position": "0.84163475, 1.4223307, -0.017840637", + "Rotation": "0.036192298, -0.015088534, -0.011359941, 0.99916625", + "Scale": "0.9999986, 0.9999993, 0.9999982" + }, + "j_kusu_b_r": { + "Position": "-0.8414654, 1.422719, -0.01827417", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.999999, 0.99999934, 0.999998" + }, + "j_naka_b_l": { + "Position": "0.8431683, 1.4217082, 0.00540426", + "Rotation": "0.035948396, -0.0150857605, -0.011363624, 0.9991751", + "Scale": "0.99999857, 0.9999993, 0.9999982" + }, + "j_naka_b_r": { + "Position": "-0.8430123, 1.4220973, 0.0049699703", + "Rotation": "-0.011141797, 0.9991814, 0.035949677, -0.01481977", + "Scale": "0.9999991, 0.99999934, 0.999998" + }, + "j_oya_b_l": { + "Position": "0.76720285, 1.364569, 0.06160299", + "Rotation": "0.63501173, -0.37456238, -0.0044878875, 0.6756054", + "Scale": "0.99999833, 0.9999992, 0.99999857" + }, + "j_oya_b_r": { + "Position": "-0.7671019, 1.364924, 0.061206724", + "Rotation": "-0.0044956557, 0.6757025, 0.6350976, -0.37424123", + "Scale": "0.99999887, 0.99999934, 0.99999833" + }, + "n_sippo_a": { + "Position": "-4.0628016E-05, 1.0035336, -0.09755956", + "Rotation": "-0.18408701, 0.6828027, -0.18422988, 0.68260646", + "Scale": "0.9999994, 0.9999996, 0.99999964" + }, + "n_sippo_b": { + "Position": "-8.8742854E-05, 0.92809814, -0.22721097", + "Rotation": "-0.18408576, 0.6828031, -0.18422872, 0.6826069", + "Scale": "0.9999998, 0.99999994, 0.99999994" + }, + "n_sippo_c": { + "Position": "-0.00013687686, 0.852663, -0.35686272", + "Rotation": "-0.18408954, 0.6828022, -0.18423297, 0.68260556", + "Scale": "0.9999999, 0.99999994, 0.99999994" + }, + "n_sippo_d": { + "Position": "-0.00018514832, 0.7772264, -0.48651353", + "Rotation": "-0.18363339, 0.6842012, -0.1845198, 0.6812488", + "Scale": "0.99999994, 1.0000002, 0.9999998" + }, + "n_sippo_e": { + "Position": "-0.00083891227, 0.7018224, -0.6161819", + "Rotation": "-0.1845394, 0.6814013, -0.18393692, 0.6839624", + "Scale": "0.9999999, 1.0000002, 0.99999994" + }, + "iv_ko_c_l": { + "Position": "0.84635603, 1.419364, -0.040290892", + "Rotation": "0.036192294, -0.015088533, -0.01135994, 0.9991662", + "Scale": "0.9999986, 0.9999993, 0.9999982" + }, + "iv_kusu_c_l": { + "Position": "0.8661175, 1.4217478, -0.017122013", + "Rotation": "0.036192294, -0.015088533, -0.01135994, 0.9991662", + "Scale": "0.9999986, 0.9999993, 0.9999982" + }, + "iv_naka_c_l": { + "Position": "0.8686503, 1.4211016, 0.0061521665", + "Rotation": "0.035948392, -0.01508576, -0.011363623, 0.999175", + "Scale": "0.99999857, 0.9999993, 0.9999982" + }, + "iv_hito_c_l": { + "Position": "0.86331266, 1.4174877, 0.0287818", + "Rotation": "0.035948392, -0.01508576, -0.011363623, 0.999175", + "Scale": "0.99999857, 0.9999992, 0.9999982" + }, + "iv_ko_c_r": { + "Position": "-0.8461774, 1.4197556, -0.04072678", + "Rotation": "-0.011141796, 0.99918133, 0.035949674, -0.014819769", + "Scale": "0.9999991, 0.99999934, 0.999998" + }, + "iv_kusu_c_r": { + "Position": "-0.86594856, 1.4221475, -0.017568221", + "Rotation": "-0.011141796, 0.99918133, 0.035949674, -0.014819769", + "Scale": "0.9999989, 0.9999993, 0.999998" + }, + "iv_naka_c_r": { + "Position": "-0.86849487, 1.4215024, 0.0057047317", + "Rotation": "-0.011141796, 0.99918133, 0.035949674, -0.014819769", + "Scale": "0.9999992, 0.99999946, 0.999998" + }, + "iv_hito_c_r": { + "Position": "-0.86316925, 1.417887, 0.028337127", + "Rotation": "-0.011141796, 0.99918133, 0.035949674, -0.014819769", + "Scale": "0.9999991, 0.9999993, 0.999998" + }, + "iv_asi_oya_a_l": { + "Position": "0.058350407, 0.034072954, 0.12689525", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_oya_b_l": { + "Position": "0.058355644, 0.03406776, 0.15127932", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_hito_a_l": { + "Position": "0.08285475, 0.030941889, 0.13303468", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_hito_b_l": { + "Position": "0.08285766, 0.030939, 0.14660923", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.999999, 0.9999994" + }, + "iv_asi_naka_a_l": { + "Position": "0.09957546, 0.03093845, 0.12811661", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_naka_b_l": { + "Position": "0.099578366, 0.030935561, 0.14169118", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_kusu_a_l": { + "Position": "0.11638246, 0.030936172, 0.11768271", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.999999, 0.9999994" + }, + "iv_asi_kusu_b_l": { + "Position": "0.11638538, 0.030933289, 0.13125728", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.999999, 0.9999994" + }, + "iv_asi_ko_a_l": { + "Position": "0.13096008, 0.030933835, 0.11031699", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_ko_b_l": { + "Position": "0.13096234, 0.030931571, 0.120956644", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.9999991, 0.99999905, 0.9999994" + }, + "iv_asi_oya_a_r": { + "Position": "-0.05885524, 0.034105003, 0.12692045", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_oya_b_r": { + "Position": "-0.058850005, 0.034099802, 0.15130453", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_hito_a_r": { + "Position": "-0.083358616, 0.030987076, 0.13307047", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_hito_b_r": { + "Position": "-0.08335572, 0.030984174, 0.14664502", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.999999, 0.9999988, 0.9999994" + }, + "iv_asi_naka_a_r": { + "Position": "-0.10008144, 0.030992605, 0.12815961", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_naka_b_r": { + "Position": "-0.10007851, 0.03098971, 0.14173418", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_kusu_a_r": { + "Position": "-0.11689292, 0.030999335, 0.11773293", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_kusu_b_r": { + "Position": "-0.11689, 0.03099644, 0.1313075", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_ko_a_r": { + "Position": "-0.1314737, 0.031004813, 0.11037353", + "Rotation": "-0.70718265, 0.00016985832, -0.7070306, -1.92672E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_asi_ko_b_r": { + "Position": "-0.1314714, 0.031002542, 0.12101317", + "Rotation": "-0.7071826, 0.00016985831, -0.70703053, -1.9267198E-05", + "Scale": "0.999999, 0.9999989, 0.9999994" + }, + "iv_nitoukin_l": { + "Position": "0.29915008, 1.4330559, -0.03268631", + "Rotation": "0.28244606, -0.6754016, 0.24345769, 0.63622695", + "Scale": "0.99999905, 0.9999992, 0.9999986" + }, + "iv_nitoukin_r": { + "Position": "-0.29896894, 1.4331943, -0.03283995", + "Rotation": "-0.6496218, -0.25008848, -0.6498387, 0.3052152", + "Scale": "0.99999946, 0.99999934, 0.99999857" + }, + "iv_c_mune_l": { + "Position": "0.036407854, 1.289018, -0.011461202", + "Rotation": "-0.031106329, -0.6214819, 0.030779311, 0.7822049", + "Scale": "0.9999991, 0.99999946, 0.99999946" + }, + "iv_c_mune_r": { + "Position": "-0.036304105, 1.2890348, -0.011479724", + "Rotation": "0.03096803, 0.78235674, -0.030954828, -0.62128884", + "Scale": "0.9999996, 0.99999946, 0.9999996" + }, + "iv_kougan_l": { + "Position": "0.014819197, 0.9197874, 0.09152882", + "Rotation": "-0.4421702, 0.55170435, 0.4424129, -0.5517048", + "Scale": "0.99999946, 0.99999946, 0.9999996" + }, + "iv_kougan_r": { + "Position": "-0.0148643665, 0.91979533, 0.09153518", + "Rotation": "-0.5517049, 0.44241288, -0.5517044, 0.4421702", + "Scale": "0.9999997, 0.9999996, 0.9999997" + }, + "iv_ochinko_a": { + "Position": "-2.0354986E-05, 0.9274112, 0.09153165", + "Rotation": "-0.7026655, -0.07980323, -0.70249295, -0.07997388", + "Scale": "0.9999996, 0.99999946, 0.9999997" + }, + "iv_ochinko_b": { + "Position": "-1.208307E-05, 0.9343029, 0.121444106", + "Rotation": "-0.70266545, -0.07980322, -0.7024929, -0.07997387", + "Scale": "0.9999996, 0.99999946, 0.9999997" + }, + "iv_ochinko_c": { + "Position": "-3.817204E-06, 0.9411946, 0.15135656", + "Rotation": "-0.69620144, -0.124140084, -0.69601846, -0.12429947", + "Scale": "0.9999996, 0.9999994, 0.9999997" + }, + "iv_ochinko_d": { + "Position": "5.587276E-06, 0.9522689, 0.18139799", + "Rotation": "-0.6962014, -0.12414008, -0.6960184, -0.12429946", + "Scale": "0.9999996, 0.9999994, 0.9999997" + }, + "iv_ochinko_e": { + "Position": "1.49867265E-05, 0.96334326, 0.21143934", + "Rotation": "-0.6929134, -0.14134385, -0.69272655, -0.14149866", + "Scale": "0.9999996, 0.9999994, 0.9999997" + }, + "iv_ochinko_f": { + "Position": "2.2541364E-05, 0.9731528, 0.23446651", + "Rotation": "-0.69291335, -0.14134383, -0.6927265, -0.14149864", + "Scale": "0.9999996, 0.9999994, 0.9999997" + }, + "iv_kuritto": { + "Position": "-0.00083508156, 0.9297578, 0.074052915", + "Rotation": "0.3021347, -0.63880306, -0.30220228, 0.6397805", + "Scale": "1, 1, 1.0000001" + }, + "iv_inshin_l": { + "Position": "0.0063545364, 0.91388166, 0.034682155", + "Rotation": "-0.4031899, 0.58080137, 0.40343195, -0.58081853", + "Scale": "0.9999982, 0.9999995, 0.9999997" + }, + "iv_inshin_r": { + "Position": "-0.006427265, 0.9138851, 0.03468491", + "Rotation": "-0.58081865, 0.4034318, -0.5808015, 0.40318975", + "Scale": "0.9999996, 0.99999946, 0.9999997" + }, + "iv_omanko": { + "Position": "0.00012332597, 0.9182067, 0.029764555", + "Rotation": "-0.39297858, 0.5877584, 0.39322034, -0.5877798", + "Scale": "1.0000054, 0.9999997, 0.9999997" + }, + "iv_koumon": { + "Position": "0.001106808, 0.92932034, -0.0027462766", + "Rotation": "-0.66488343, 0.24046259, 0.6650908, -0.24033654", + "Scale": "0.99999964, 0.9999995, 0.9999997" + }, + "iv_koumon_l": { + "Position": "0.001106808, 0.92932034, -0.0027462766", + "Rotation": "-0.51024485, 0.5031933, -0.33634496, 0.6109979", + "Scale": "0.9999997, 0.9999997, 0.9999997" + }, + "iv_koumon_r": { + "Position": "0.001106808, 0.92932034, -0.0027462766", + "Rotation": "-0.33597973, 0.6331165, -0.50881463, 0.47685254", + "Scale": "0.9999997, 0.9999996, 0.9999997" + }, + "iv_shiri_l": { + "Position": "0.06619707, 0.96816134, -0.036543373", + "Rotation": "-0.7070306, 9.466899E-05, 0.707183, 9.437999E-05", + "Scale": "1, 1, 1.0000001" + }, + "iv_shiri_r": { + "Position": "-0.06627128, 0.96819675, -0.036514886", + "Rotation": "9.4446325E-05, 0.70718277, -9.4603885E-05, 0.7070308", + "Scale": "0.9999997, 0.9999997, 1" + }, + "iv_kyokin_phys_l": { + "Position": "0.04522211, 1.351867, 0.044153605", + "Rotation": "0.08391271, -0.37790453, -0.07120927, 0.9192802", + "Scale": "0.99999994, 1, 1" + }, + "iv_kyokin_phys_r": { + "Position": "-0.045646947, 1.3518671, 0.044069238", + "Rotation": "-0.07327869, 0.9197509, 0.07852894, -0.37752017", + "Scale": "1.0000006, 1.0000001, 1.0000006" + }, + "iv_fukubu_phys": { + "Position": "-6.8582594E-06, 1.1145278, 0.06086532", + "Rotation": "0.0001090765, 0.70719707, 5.4329634E-05, -0.7070161", + "Scale": "0.99999964, 0.99999994, 0.9999998" + }, + "iv_fukubu_phys_l": { + "Position": "0.059006903, 1.1131427, 0.042821597", + "Rotation": "-5.567074E-05, -0.14863701, -0.00010892749, 0.98889154", + "Scale": "0.9999997, 0.9999998, 0.9999998" + }, + "iv_fukubu_phys_r": { + "Position": "-0.059446655, 1.1131704, 0.04279129", + "Rotation": "0.00012047589, 0.9889297, -2.1025538E-05, -0.14838323", + "Scale": "0.99999964, 0.9999996, 0.9999997" + }, + "iv_daitai_phys_l": { + "Position": "0.09297473, 0.96236646, 0.02498791", + "Rotation": "-0.5120628, 0.4877491, -0.51208293, 0.48750725", + "Scale": "0.99999946, 0.9999993, 0.99999964" + }, + "iv_daitai_phys_r": { + "Position": "-0.093025215, 0.9624161, 0.025028002", + "Rotation": "-0.5120626, 0.48774925, -0.51208276, 0.4875074", + "Scale": "0.99999946, 0.9999992, 0.99999964" + }, + "iv_kintama_phys_l": { + "Position": "0.0062771905, 0.91170835, 0.09036183", + "Rotation": "0.577733, -0.46160096, -0.40770617, 0.5356536", + "Scale": "1.0000015, 0.9999998, 1.0000002" + }, + "iv_kintama_phys_r": { + "Position": "-0.00632718, 0.91171175, 0.090364546", + "Rotation": "-0.43167, 0.55461395, 0.5600549, -0.4386374", + "Scale": "1.0000006, 0.99999994, 1.0000001" + }, + "iv_funyachin_phy_a": { + "Position": "-1.3286248E-05, 0.9537829, 0.09153037", + "Rotation": "0.6508869, -0.276562, 0.65076226, -0.27634788", + "Scale": "0.99999976, 0.99999964, 1" + }, + "iv_funyachin_phy_b": { + "Position": "-1.2025739E-05, 0.93309647, 0.111486584", + "Rotation": "0.6078271, -0.3615117, 0.6077232, -0.36128667", + "Scale": "0.99999994, 0.9999998, 1" + }, + "iv_funyachin_phy_c": { + "Position": "-1.3082341E-05, 0.90737504, 0.12546751", + "Rotation": "0.55317783, -0.4406229, 0.55307186, -0.44040564", + "Scale": "0.99999994, 0.9999997, 0.99999994" + }, + "iv_funyachin_phy_d": { + "Position": "-1.5012316E-05, 0.88199484, 0.13129511", + "Rotation": "0.5151943, -0.4844898, 0.5150979, -0.48427138", + "Scale": "0.9999997, 0.9999995, 0.99999976" + }, + "j_f_face": { + "Position": "0.000112607246, 1.6139671, 0.043865107", + "Rotation": "-0.00014907238, -0.7071968, -1.4395755E-05, 0.7070157", + "Scale": "0.99999917, 0.9999998, 0.9999996" + }, + "j_f_ago": { + "Position": "0.000114985545, 1.6213628, 0.041264974", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_dhoho_l": { + "Position": "0.038902134, 1.5927389, 0.06507908", + "Rotation": "0.031417534, -0.21123749, -0.039405283, 0.97613347", + "Scale": "0.99999917, 0.9999996, 0.99999994" + }, + "j_f_dhoho_r": { + "Position": "-0.038697653, 1.5927567, 0.065059096", + "Rotation": "-0.03918769, 0.9761965, 0.03145625, -0.2109802", + "Scale": "0.9999986, 0.9999996, 0.9999993" + }, + "j_f_dmemoto_l": { + "Position": "0.01719988, 1.6265608, 0.10486888", + "Rotation": "0.0007044769, -0.70595753, -0.02158063, 0.7079232", + "Scale": "0.99999917, 1.0121772, 0.9999996" + }, + "j_f_dmemoto_r": { + "Position": "-0.017000267, 1.6265687, 0.10486007", + "Rotation": "0.021417165, -0.70810884, -0.0008621334, 0.70577604", + "Scale": "0.99999917, 1.0121772, 0.9999996" + }, + "j_f_dmiken_l": { + "Position": "0.012912092, 1.641157, 0.10368254", + "Rotation": "0.0335657, -0.69154125, -0.023953069, 0.7211573", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_dmiken_r": { + "Position": "-0.012705118, 1.6411632, 0.10367596", + "Rotation": "0.023794971, -0.7213399, -0.033719417, 0.6913487", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_dslip_l": { + "Position": "0.024521125, 1.5889056, 0.09225019", + "Rotation": "-0.04831263, -0.4445836, 0.011357896, 0.89436", + "Scale": "0.9999995, 0.9999996, 0.99999994" + }, + "j_f_dslip_r": { + "Position": "-0.024332406, 1.5889169, 0.09223759", + "Rotation": "0.011576998, 0.8944712, -0.04820695, -0.44436568", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eye_l": { + "Position": "0.026410615, 1.647968, 0.08186531", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eye_r": { + "Position": "-0.026189249, 1.6479801, 0.08185175", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eyeprm_01_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eyeprm_01_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eyeprmroll_l": { + "Position": "0.020108366, 1.613955, 0.04386906", + "Rotation": "0.010839883, -0.70708984, 0.013420034, 0.70691144", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_eyeprmroll_r": { + "Position": "-0.01988261, 1.6139642, 0.043858767", + "Rotation": "-0.013580662, -0.7070894, -0.011006768, 0.70690626", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_hagukiup": { + "Position": "0.000105752304, 1.591605, 0.095923424", + "Rotation": "-0.00014907231, -0.7071964, -1.4395748E-05, 0.70701534", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_hana_l": { + "Position": "0.0062143677, 1.6163039, 0.11473243", + "Rotation": "0.0008271346, -0.7020261, 0.0078014047, 0.7121062", + "Scale": "1.0048703, 1.0106558, 1.0048707" + }, + "j_f_hana_r": { + "Position": "-0.006024571, 1.6163068, 0.11472926", + "Rotation": "-0.007965798, -0.71228415, -0.0009914093, 0.70184356", + "Scale": "1.0048703, 1.0106558, 1.0048708" + }, + "j_f_hoho_l": { + "Position": "0.042155366, 1.629632, 0.0877333", + "Rotation": "0.040782902, -0.4229029, 0.0066511766, 0.90523094", + "Scale": "0.9999995, 0.9999994, 0.99999994" + }, + "j_f_hoho_r": { + "Position": "-0.041945506, 1.6296514, 0.08771165", + "Rotation": "0.0068499786, 0.9053377, 0.040882368, -0.42266142", + "Scale": "0.9999988, 0.9999994, 0.99999946" + }, + "j_f_mab_l": { + "Position": "0.026411895, 1.6479573, 0.08183228", + "Rotation": "0.0036503072, -0.5807935, 0.00072641036, 0.8140409", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_mab_r": { + "Position": "-0.026190516, 1.6479695, 0.08181872", + "Rotation": "-0.0009136455, -0.81418943, -0.003784749, 0.5805841", + "Scale": "0.99999917, 0.9999996, 0.99999946" + }, + "j_f_mayu_l": { + "Position": "0.048579052, 1.6582426, 0.088389665", + "Rotation": "0.033031374, -0.30136967, -0.014410832, 0.95282483", + "Scale": "0.99999917, 0.9999994, 0.99999994" + }, + "j_f_mayu_r": { + "Position": "-0.048356295, 1.658265, 0.08836469", + "Rotation": "-0.014199032, 0.9529053, 0.03309734, -0.30111784", + "Scale": "0.99999845, 0.9999994, 0.9999993" + }, + "j_f_miken_01_l": { + "Position": "0.013166276, 1.6536878, 0.11349205", + "Rotation": "0.0020516089, -0.7205807, -0.021260263, 0.69304013", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_miken_01_r": { + "Position": "-0.012958565, 1.6536939, 0.11348534", + "Rotation": "0.02110059, -0.69322956, -0.0022127284, 0.72040266", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_mmayu_l": { + "Position": "0.035007473, 1.6572086, 0.10392463", + "Rotation": "0.015731214, -0.4992463, -0.045106318, 0.86514074", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_mmayu_r": { + "Position": "-0.034793194, 1.6572245, 0.103906676", + "Rotation": "-0.044910368, 0.8652791, 0.01583507, -0.499021", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_shoho_l": { + "Position": "0.03204558, 1.5863262, 0.082305625", + "Rotation": "0.10643038, -0.30995685, -0.14611596, 0.9334061", + "Scale": "0.99999917, 1.0361824, 1.0240045" + }, + "j_f_shoho_r": { + "Position": "-0.031375196, 1.5865569, 0.08196854", + "Rotation": "-0.14592743, 0.93351924, 0.10646456, -0.30969307", + "Scale": "0.99999845, 1.0361824, 1.0240041" + }, + "j_f_uhana": { + "Position": "9.783661E-05, 1.6360886, 0.12106626", + "Rotation": "-0.11958073, -0.69701314, 0.11938902, 0.69686216", + "Scale": "0.99999917, 0.9999994, 0.9999996" + }, + "j_f_ulip_01_l": { + "Position": "0.004325908, 1.6035151, 0.105870545", + "Rotation": "-0.015177502, -0.7070355, 0.010614744, 0.70693374", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_ulip_01_r": { + "Position": "-0.0041374685, 1.6035173, 0.10586837", + "Rotation": "-0.010782042, -0.7071123, 0.015011349, 0.7068579", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_umlip_01_l": { + "Position": "0.014791088, 1.600932, 0.0995685", + "Rotation": "-0.047341153, -0.46318358, 0.00340644, 0.884989", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_umlip_01_r": { + "Position": "-0.0146006085, 1.600939, 0.09956093", + "Rotation": "0.0036231333, 0.8851069, -0.04723321, -0.46296784", + "Scale": "0.99999845, 0.9999996, 0.9999989" + }, + "j_f_uslip_l": { + "Position": "0.024279285, 1.5906982, 0.09263888", + "Rotation": "-0.025707869, -0.4441135, -0.03427092, 0.89494437", + "Scale": "0.9999995, 0.9999996, 0.99999994" + }, + "j_f_uslip_r": { + "Position": "-0.024089951, 1.5907096, 0.09262639", + "Rotation": "-0.03405747, 0.8950661, -0.025613979, -0.44389004", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_bero_01": { + "Position": "0.00010529465, 1.5871644, 0.04817146", + "Rotation": "-0.080205, -0.70263326, 0.08002205, 0.7024717", + "Scale": "0.999999, 0.99999994, 0.9999993" + }, + "j_f_dago": { + "Position": "0.00011273738, 1.6116389, 0.041266825", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_dlip_01_l": { + "Position": "0.0040838923, 1.576418, 0.099785626", + "Rotation": "0.0983288, -0.69986254, -0.10247822, 0.7000133", + "Scale": "0.9999988, 0.9999996, 0.9999996" + }, + "j_f_dlip_01_r": { + "Position": "-0.0039049855, 1.5764198, 0.099783555", + "Rotation": "0.10234161, -0.7002163, -0.09846431, 0.69966036", + "Scale": "0.9999988, 0.9999996, 0.9999996" + }, + "j_f_dmlip_01_l": { + "Position": "0.0145608345, 1.5804873, 0.0968233", + "Rotation": "0.15507792, -0.4600188, -0.04749111, 0.8729688", + "Scale": "0.9999995, 0.99999994, 0.9999996" + }, + "j_f_dmlip_01_r": { + "Position": "-0.014378482, 1.5804942, 0.09681579", + "Rotation": "-0.047329072, 0.87309754, 0.15517211, -0.45975924", + "Scale": "0.9999988, 0.99999994, 0.9999993" + }, + "j_f_eyeprm_02_l": { + "Position": "-0.00022141234, 1.6132183, 0.035054144", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_eyeprm_02_r": { + "Position": "0.0004508185, 1.6132182, 0.035054304", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_eyepuru_l": { + "Position": "0.02641062, 1.6479682, 0.081865326", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_eyepuru_r": { + "Position": "-0.026189256, 1.6479802, 0.081851766", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_hagukidn": { + "Position": "0.00016645683, 1.5806464, 0.092767544", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_irisprm_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_irisprm_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "-0.00014907224, -0.70719606, -1.439574E-05, 0.707015", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_mabdn_01_l": { + "Position": "0.026554272, 1.6477264, 0.08072915", + "Rotation": "0.0867323, -0.57400405, -0.14078897, 0.80197996", + "Scale": "0.999999, 0.99999994, 0.99999946" + }, + "j_f_mabdn_01_r": { + "Position": "-0.026332423, 1.6477381, 0.08071551", + "Rotation": "0.14062496, -0.80215925, -0.0868302, 0.573779", + "Scale": "0.9999986, 0.99999994, 0.9999993" + }, + "j_f_mabup_01_l": { + "Position": "0.027048962, 1.6481377, 0.082151175", + "Rotation": "-0.03478829, -0.5797013, 0.05558556, 0.81218415", + "Scale": "0.99999917, 0.9999996, 0.9999996" + }, + "j_f_mabup_01_r": { + "Position": "-0.026827667, 1.6481502, 0.08213729", + "Rotation": "-0.055782247, -0.81231964, 0.034640074, 0.5795012", + "Scale": "0.99999917, 0.99999994, 0.99999946" + }, + "j_f_miken_02_l": { + "Position": "0.007249107, 1.6505802, 0.11339834", + "Rotation": "-0.099926114, -0.72576153, -0.1617233, 0.6611557", + "Scale": "0.99999917, 0.99999994, 0.93676156" + }, + "j_f_miken_02_r": { + "Position": "-0.007042804, 1.6505837, 0.11339468", + "Rotation": "0.16154484, -0.66137886, 0.09979977, 0.7256152", + "Scale": "0.99999917, 0.99999994, 0.93676144" + }, + "j_f_ulip_02_l": { + "Position": "0.0042815693, 1.5947366, 0.10614734", + "Rotation": "-0.01300136, -0.70559555, 0.009362291, 0.70843124", + "Scale": "0.9920272, 0.99999994, 0.9999996" + }, + "j_f_ulip_02_r": { + "Position": "-0.0040973253, 1.594739, 0.106145196", + "Rotation": "-0.009529378, -0.7086098, 0.012835858, 0.7054171", + "Scale": "0.9920272, 0.99999994, 0.9999996" + }, + "j_f_umlip_02_l": { + "Position": "0.01452633, 1.593964, 0.10017712", + "Rotation": "-0.047341116, -0.46318325, 0.003406437, 0.88498837", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_umlip_02_r": { + "Position": "-0.014339351, 1.5939709, 0.10016974", + "Rotation": "0.003623134, 0.88510644, -0.04723318, -0.46296757", + "Scale": "0.99999845, 0.99999994, 0.9999989" + }, + "j_f_bero_02": { + "Position": "0.000102072554, 1.5907667, 0.063760616", + "Rotation": "0.006022282, -0.70717007, -0.0061841905, 0.70698744", + "Scale": "0.9999992, 0.9999997, 0.9999995" + }, + "j_f_dlip_02_l": { + "Position": "0.004142296, 1.5860144, 0.10259663", + "Rotation": "0.098328725, -0.69986206, -0.10247816, 0.7000128", + "Scale": "0.9919811, 0.99198174, 0.9999996" + }, + "j_f_dlip_02_r": { + "Position": "-0.0039604404, 1.5860167, 0.10259461", + "Rotation": "0.102341525, -0.7002158, -0.09846424, 0.6996599", + "Scale": "0.9919811, 0.9919817, 0.9999996" + }, + "j_f_dmlip_02_l": { + "Position": "0.01414252, 1.5871191, 0.0990245", + "Rotation": "0.15507784, -0.46001858, -0.047491092, 0.87296826", + "Scale": "0.9919814, 0.9919819, 0.9999996" + }, + "j_f_dmlip_02_r": { + "Position": "-0.013958249, 1.5871264, 0.09901732", + "Rotation": "-0.047329046, 0.873097, 0.15517202, -0.459759", + "Scale": "0.9919809, 0.9919819, 0.9999992" + }, + "j_f_mabdn_02out_l": { + "Position": "0.025609171, 1.6477493, 0.08105526", + "Rotation": "0.07413167, -0.64171666, -0.14781237, 0.7489001", + "Scale": "0.9999992, 0.9999997, 0.9999998" + }, + "j_f_mabdn_02out_r": { + "Position": "-0.02538749, 1.6477606, 0.08104199", + "Rotation": "0.14765757, -0.74909836, -0.074243486, 0.6415082", + "Scale": "0.99999934, 0.9999997, 0.9999995" + }, + "j_f_mabdn_03in_l": { + "Position": "0.02466408, 1.6477716, 0.08138116", + "Rotation": "0.07413167, -0.64171666, -0.14781237, 0.7489001", + "Scale": "0.9999992, 0.9999997, 0.9999998" + }, + "j_f_mabdn_03in_r": { + "Position": "-0.024442574, 1.6477829, 0.08136841", + "Rotation": "0.14765757, -0.74909836, -0.074243486, 0.6415082", + "Scale": "0.99999934, 0.9999997, 0.9999995" + }, + "j_f_mabup_02out_l": { + "Position": "0.026103443, 1.6481296, 0.08247666", + "Rotation": "-0.029811295, -0.64828175, 0.05840602, 0.75856894", + "Scale": "0.999999, 0.9999996, 0.9999996" + }, + "j_f_mabup_02out_r": { + "Position": "-0.02588232, 1.6481422, 0.08246326", + "Rotation": "-0.05858906, -0.75872135, 0.029646507, 0.648094", + "Scale": "0.99999917, 0.9999997, 0.9999998" + }, + "j_f_mabup_03in_l": { + "Position": "0.02515792, 1.648122, 0.082802154", + "Rotation": "-0.029811295, -0.64828175, 0.05840602, 0.75856894", + "Scale": "0.999999, 0.9999996, 0.9999996" + }, + "j_f_mabup_03in_r": { + "Position": "-0.024936998, 1.6481339, 0.082789235", + "Rotation": "-0.05858906, -0.75872135, 0.029646507, 0.648094", + "Scale": "0.99999917, 0.9999997, 0.9999998" + }, + "j_f_bero_03": { + "Position": "9.808998E-05, 1.5905075, 0.07875828", + "Rotation": "0.04302443, -0.70588523, -0.043176543, 0.7056944", + "Scale": "0.9999996, 0.99999994, 0.9999995" + }, + "j_f_noanim_ago": { + "Position": "0.00011411109, 1.6110312, 0.035112683", + "Rotation": "0.70096475, -0.09229817, 0.7011657, -0.09215975", + "Scale": "0.9999988, 0.99999917, 0.99999946" + }, + "j_f_noanim_eyesize_l": { + "Position": "-0.00026046712, 1.6131796, 0.035054132", + "Rotation": "0.007872224, -0.70719, 0.0030719552, 0.70697063", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_f_noanim_eyesize_r": { + "Position": "0.0004898554, 1.6131791, 0.035054322", + "Rotation": "0.007872224, -0.70719, 0.0030719552, 0.70697063", + "Scale": "0.99999917, 0.99999994, 0.9999996" + }, + "j_ex_h0179_back_01_c": { + "Position": "0.0001646834, 1.6804804, -0.09852052", + "Rotation": "-0.40574524, 0.58078367, -0.4110869, 0.5736442", + "Scale": "0.9999994, 0.99999946, 0.9999998" + }, + "j_ex_h0179_side_a01_l": { + "Position": "0.043938704, 1.6911907, 0.10895225", + "Rotation": "-0.4984195, 0.50144833, -0.50130117, 0.49882215", + "Scale": "0.9999995, 0.99999994, 0.9999997" + }, + "j_ex_h0179_side_a01_r": { + "Position": "-0.043316215, 1.6909308, 0.10854824", + "Rotation": "-0.49841943, 0.50144845, -0.5013011, 0.49882215", + "Scale": "0.9999995, 0.99999994, 0.9999997" + }, + "j_ex_h0179_side_b01_l": { + "Position": "0.06829355, 1.6992975, 0.08048706", + "Rotation": "-0.23848057, 0.55964977, -0.17277083, 0.7746406", + "Scale": "0.9999999, 0.99999994, 0.9999997" + }, + "j_ex_h0179_side_b01_r": { + "Position": "-0.06758577, 1.6996939, 0.0803228", + "Rotation": "-0.17246126, 0.7747005, -0.23870587, 0.55956674", + "Scale": "0.99999964, 0.99999994, 0.99999994" + } + }, + "MainHand": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + } + }, + "OffHand": { + "n_root": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "1, 1, 1" + }, + "n_hara": { + "Position": "0, 0, 0", + "Rotation": "-2.5000001E-14, 2.5000001E-14, -2.5000001E-14, 0.99999994", + "Scale": "0.99999994, 0.99999994, 0.99999994" + } + }, + "Position": "-0.0070150536, 41.386536, -138.16553", + "Rotation": "0, 0.010434319, 0, 0.9999456", + "Scale": "1, 1, 1", + "Author": null, + "Description": null, + "Version": null, + "Base64Image": null, + "Tags": null +} \ No newline at end of file diff --git a/Brio/Resources/Embedded/Data/Changelog.txt b/Brio/Resources/Embedded/Data/Changelog.txt index 051f565a..9696bcb2 100644 --- a/Brio/Resources/Embedded/Data/Changelog.txt +++ b/Brio/Resources/Embedded/Data/Changelog.txt @@ -1,183 +1,103 @@ To open this window again click `Information` on the Scene Manager then -> `View the Changelog` --------------------------------------------------------------------------------- - ---> Brio, Version 0.4.4 <--- --------------------------------------------------------------------------------- - ----------- 0.4.4.1 ---------- - -- Fixed an issue with Ears when importing as Body or Expression - ----------- 0.4.4.0 ---------- - -- Added a Hide Actor button to the `Entity Hierarchy` - -- Added `Import as Body`, to Import Pose button -- Added a new setting in the Import Pose popup, - - You can now Freeze an Actor after import - -- Updated Brio's IPC API (Thanks to Darkarchon for the collaborative efforts!) - - For more info on Brio's updated IPC look at `BrioAPI_V2.cs` in the root of Brio's GitHub repo - -- Loading a pose will now be more consistent & predictable - -- You can now double-click items in Library to apply them -- You can now make the Library Window smaller -- You can now make the Library item icon size smaller - -- Status Effects in the effects selector that have no VFX are now filtered out (Thank you MKhayle!) -- Added better localization for Status Effects selector (Thank you MKhayle!) - -- Fixed an issue with Anamnesis and editing Brio actors -- Fixed the Library's Search Suggest Box closing when it shouldn't -- Fixed multiple possible crashes! - --------------------------------------------------------------------------------- - --- Brio, Version 0.4.3 --- --------------------------------------------------------------------------------- - ----------- 0.4.3.1 ---------- - -- Fix an issue where not all of the actions would appear in the animation select list -- Fixed an isues with Penumbra and 100+ actors +-------------------------------------------------------------------------------------------------------------------------------------------------------- + ---> Brio, Version 0.5.0 <--- Props, Free Cameras & Projects! +--------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- 0.4.3.0 ---------- +- Brio has a new Icon! + - Over time it will update in Dalamud -- Support for FFXIV 7.1! +- Added "Legacy" bone filter. + - Use this import filter when loading on to pre-dawntrail faces -- Brio can now spawn up to 239 Actors +- Added Brio Style + - Fixes a bug under certain circumstances. + - More styles will be added in the future. + - You can disabled the Color Style in the Settings. --------------------------------------------------------------------------------- - --- Brio, Version 0.4.1 --- --------------------------------------------------------------------------------- - ----------- 0.4.2.0 ---------- - -- Provide better compatibility for .chara files - ----------- 0.4.1.0 ---------- +- Added Projects, save and load the entire Brio scene. + - Project System is in Beta. NOTE: Projects might not be compatible from version to version! + - Scene exporting will be available in a later update. + - (Thanks Ashadow700 for the initial implementation and inspiration) -- Added a `Universal Gizmo` mode to the `Brio Overlay` Gizmo! -- Added `Upper & Lower Teeth` bones to `Advanced Pose` window -- Added `IVCS Buttock` bones to `Advanced Pose` window +- Added AutoSaving, saves the entire Brio scene. + - Default interval is once a minute. -- Added a `Enable FOV` setting to the `Cutscene Control` -- Added a `Delimit Speed` setting to the `Advanced Animation` Window - - With this enabled you can make the animation speed go in reverse or very very fast! +- Added Customize+ suport. -- Fixed an issue that caused incorrect items to show up when you right-clicked an item in the `Entity Hierarchy` -- Fixed `Glamourer` desync issues -- Fixed FOV being high when playing a XAT Cutscene(`.xcp`) file +- Added a Change Customize+ Profile menu. +- Added a Change Glamourer Design menu. -- Made more micro-optimizations & more stability improvements +- Added Virtual Cameras, You can now spawn more then one Camera! - -- Known Issues -- +- Added Free Cameras! + - Keybinds will be changeable in the future. -- When importing a pose as Expression the head does not rotate properly, - - You can fix this by rotating the "Head" bone manually -- Not all of the new bones are named yet -- The Library does not have an option to `Import as Expression` - - --------------------------------------------------------------------------------- - --- Brio, Version 0.4.0 --- --------------------------------------------------------------------------------- +- Added Prop Spawning! (Thanks MKhayle for inspiration) + - If you have issues seeing the Prop be sure to click the "Refresh" button in the top left of the widget! ----------- 0.4.0.3 ---------- +- Added "Change weapon into a Prop" button to the Advanced Appearance window. (Thanks MKhayle!) + - If you have issues seeing the Prop be sure to press the Attach Weapon button. -- Fixed being unable to change an Actor's Appearance if you don't have Glamourer installed -- Fixed the Camera Window from moving endlessly to the right -- Fix a crash when leaving GPose with Freeze Physics Enabled +- Added a Reset model transform button to the posing widget. ----------- 0.4.0.0 ---------- +- You can now press Escape to clear the selected bone. + - Keybind will be changeable in the future. -- Updated the `Advanced Pose` Window - - Added a `Freeze Physics` & `Freeze Character` button - - Changed the Bone Page selector visual style - - Better layout of Bones on Body page +- Refresh the designs of the Appearance, Posing, & Animation Control widgets! + - Added multiple buttons to the posing widget. + - Change the icons to the import and export buttons. + - Added a scrub bar to the animation control widget. -- Refreshed the UI for the `Entity Hierarchy` +- Rewrote the Freeze Physics System for better reliability. (Thanks Winter & darkarchon for the tip!) -- Updated the `Animation Control` Editor - - Ported XAT's `Cutscene Control` to the `Advanced Animation Control` Window - - Added a new Cutscene setting, `Start All Actors Animations On Play` - - `With this enabled all actors will play the animation set in the `Base` slot` - - Added `Start Delay` & `Animation Delay` - - Note: `The time-scale for the delay functions are in milliseconds!` - - `1000 Milliseconds = 1 Second` - - - Refreshed user experience of the `Animation Control` Editor - - Added a `Freeze Physics` button - - Added new `Actors` dropdown list - - `With this menu you can Freeze/Un-Freeze all Actors or Stop/Play All Actors Animations` - - Pausing Actors should now be more reliable - - Added a new setting when searching for a animation, `Start Animation On Select` - -- Added 3 new Key-binds - - Stop Playing Cutscene (Shift + B) - - Start All Actors Animations (Shift + N) - - Stop All Actors Animations (Shift + M) - -- Added simple savable camera presets to the `Camera Editor` - - These presets **do not** persist and will be 'forgotten' after ending a Gpose session -- The open `Advanced Window` buttons will now toggle their respective Advanced Windows -- Updated the `Brio Welcome` Window -- Brio will now respond to `/xat` in FFXIV chat -- Made micro optimizations across the codebase - -- Fixed a crash with IMGUI -- Fixed an issue with MCDFs -- Fixed the margins on the `Rename Actor` Popup +- Fixed an issue when loading as 'Body' on pre-dawntrail actors +- Fixed an issue with Third-Party plugins not being Available after being updated or installed! +- Fixed an issue with font scaling, Brio's font scale will now always be '1'. +- Fixed an issue with the Reset Settings button being enabled when it shouldn't have been -------------------------------------------------------------------------------- - --- Brio, Version 0.3.3 --- --------------------------------------------------------------------------------- - -Support for FFXIV 7.05! --Updated the Advanced Pose Window. - - Added a new separate page for Face Bones - - You can now undock the Transform Control Pane - - You can now Hide the Transform Control Pane +And finally, a message: It's been over a year now that I've been the developer & maintainer for Brio. -Added more Bone Categories: Face, Eyes, Lips & Jaw +Thank you to everyone who uses Brio, supports it monetarily, contributes with code, requests features, +reports bugs, or simply engages with the community. +I'm truly grateful for all the wonderful people I have met over the past year. -Added a new setting "Use the Library when importing a file" -`With this disabled you use the Dalamud File Picker when importing files` +This last year has been the hardest of my life. Without all of you, and without Brio, +it would have been much worse, so again, Thank You! -Fixed an issue with the Undo Button upon resetting a pose +But there is one in particular whom I have met I wish to make a message for, -And finally, -- Added 'Import as Expression" +I started talking to you to simply ask you what the color of your sky was, +what I found was a sky full of beautiful colors, colors I couldn't stop looking at, +colors I fell in love with, colors I wish never to forget. +I told you I'll give you stars and the moon and a soul to guide you +and a promise I'll never go, I mean it now more then ever. - -- Known Issues -- +So, while it is not mine to give necessary, +I want to give you the only thing else I know to give you, +I dedicate Brio to you -When importing a pose as Expression the head does not rotate properly, -You can fix this by rotating the "Head" bone manually +I love you, forever unto eternity~ --------------------------------------------------------------------------------- - --- Brio, Version 0.3.2 --- --------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------------------------------------------------------------- + --- Brio, Version 0.4.4.5 --- +-------------------------------------------------------------------------------------------------------------------------------------------------------- -- Update Brio for Dawntrail 7.01 -- Add support for Facewear +- Fixed an issue with Brio's IPC not loading Expressions when loading a pose -- More facial bones added to advanced posing -- More facial bones named +- Fixed an issue with hair when Importing Pose -- Update Brio for Dawntrail (Thanks Asgard!) -- Added support for the second dye channel -- Added the Import Options button to the Library when importing a pose -- Renamed some of the bones for better consistency -- Made the default size of the Skeleton's LineThickness & Bone's CircleSize smaller +- Fixed an issue with Brio's IPC causing a crash -------------------------------------------------------------------------------- A Big Thank you to (Sufferhymn), (Night Song), (Alvar Valo), (Yasumi), (YikesXD), -(Selitha), (AquilaHK), (LotusEcho), & (Yume) for their support on Kofi! +(Selitha), (AquilaHK), (LotusEcho) & (Yume) for their support on Kofi! -Also, Thank you, to: (@MKhayle), (@ashna_ff14), (@Yuki-Codes), (@danma3x), (@snaeling), -(@WorstAquaPlayer), (@Caraxi), & (@gris-fuego), for their contributions to Brio! +Also, Thank you, to: (Ashadow700), (@MKhayle), (@ashna_ff14), (@Yuki-Codes), (@danma3x), (@snaeling), +(@WorstAquaPlayer), (@Caraxi), (@Enth) & (@gris-fuego), for their contributions to Brio! -------------------------------------------------------------------------------- diff --git a/Brio/Resources/Embedded/Language/en.json b/Brio/Resources/Embedded/Language/en.json index ccb5671b..2736b9fd 100644 --- a/Brio/Resources/Embedded/Language/en.json +++ b/Brio/Resources/Embedded/Language/en.json @@ -275,6 +275,8 @@ "hands": "Hands", "weapon": "Weapons", "ivcs": "IVCS", + "ex": "EX", + "legacy": "Legacy", "other": "Other" }, diff --git a/Brio/Resources/Extra/ModelDatabase.cs b/Brio/Resources/Extra/ModelDatabase.cs index 1627e56d..f79c5d21 100644 --- a/Brio/Resources/Extra/ModelDatabase.cs +++ b/Brio/Resources/Extra/ModelDatabase.cs @@ -7,7 +7,7 @@ namespace Brio.Resources.Extra; -internal class ModelDatabase +public class ModelDatabase { private readonly MultiValueDictionary _modelLookupTable; private readonly List _modelsList; @@ -38,19 +38,20 @@ public ModelDatabase(ResourceProvider _resourceProvider) // From JSON var knownEntries = _resourceProvider.GetResourceDocument>("Data.Props.json"); + knownEntries = knownEntries.GroupBy(x => x.Name).Select(g => g.First()).ToList(); foreach(var item in knownEntries) { ushort[] result = item.Id.Split(", ").Select(ushort.Parse).ToArray(); if(result.Length > 2) { WeaponModelId weaponItem = new() { Id = result[0], Type = result[1], Variant = (byte)result[2] }; - var modelInfo = new ModelInfo(weaponItem.Value, 0, $"{item.Name.ToString()}\n{item.Description?.ToString()}", 0, ActorEquipSlot.Prop, null); + var modelInfo = new ModelInfo(weaponItem.Value, 0, $"{item.Name}\n{item.Description?.ToString()}", 0, ActorEquipSlot.Prop, null); AddModel(modelInfo); } else { EquipmentModelId actualItem = new() { Id = result[0], Variant = (byte)result[1] }; - var modelInfo = new ModelInfo(actualItem.Value, 0, $"{item.Name.ToString()}\n{item.Description?.ToString()}", 0, ActorEquipSlot.Prop, null); + var modelInfo = new ModelInfo(actualItem.Value, 0, $"{item.Name}\n{item.Description?.ToString()}", 0, ActorEquipSlot.Prop, null); AddModel(modelInfo); } } diff --git a/Brio/Resources/GameDataProvider.cs b/Brio/Resources/GameDataProvider.cs index f9b1bb66..4eef1495 100644 --- a/Brio/Resources/GameDataProvider.cs +++ b/Brio/Resources/GameDataProvider.cs @@ -9,7 +9,7 @@ namespace Brio.Resources; -internal class GameDataProvider +public class GameDataProvider { public static GameDataProvider Instance { get; private set; } = null!; diff --git a/Brio/Resources/Localize.cs b/Brio/Resources/Localize.cs index bae42f51..bd3a9907 100644 --- a/Brio/Resources/Localize.cs +++ b/Brio/Resources/Localize.cs @@ -3,7 +3,7 @@ namespace Brio.Resources; -internal static class Localize +public static class Localize { private static readonly Dictionary _stringDb = []; diff --git a/Brio/Resources/ResourceProvider.cs b/Brio/Resources/ResourceProvider.cs index bb72f396..8b46c5ca 100644 --- a/Brio/Resources/ResourceProvider.cs +++ b/Brio/Resources/ResourceProvider.cs @@ -9,7 +9,7 @@ namespace Brio.Resources; -internal class ResourceProvider : IDisposable +public class ResourceProvider : IDisposable { public static ResourceProvider Instance { get; private set; } = null!; diff --git a/Brio/Resources/Sheets/BrioCharaMakeType.cs b/Brio/Resources/Sheets/BrioCharaMakeType.cs index f9a74b7c..d3be6fcb 100644 --- a/Brio/Resources/Sheets/BrioCharaMakeType.cs +++ b/Brio/Resources/Sheets/BrioCharaMakeType.cs @@ -14,7 +14,7 @@ namespace Brio.Resources.Sheets; [Sheet("CharaMakeType", 0x80D7DB6D)] -internal unsafe struct BrioCharaMakeType(ExcelPage page, uint offset, uint row) : IExcelRow +public unsafe struct BrioCharaMakeType(ExcelPage page, uint offset, uint row) : IExcelRow { public const int MenuCount = 28; public const int SubMenuParamCount = 100; diff --git a/Brio/Resources/Sheets/BrioHairMakeType.cs b/Brio/Resources/Sheets/BrioHairMakeType.cs index 7a109f18..76b368c2 100644 --- a/Brio/Resources/Sheets/BrioHairMakeType.cs +++ b/Brio/Resources/Sheets/BrioHairMakeType.cs @@ -7,7 +7,7 @@ namespace Brio.Resources.Sheets; [Sheet("HairMakeType")] -internal struct BrioHairMakeType : IExcelRow +public struct BrioHairMakeType : IExcelRow { public const int EntryCount = 100; diff --git a/Brio/UI/BrioStyle.cs b/Brio/UI/BrioStyle.cs index bca97721..d1394dab 100644 --- a/Brio/UI/BrioStyle.cs +++ b/Brio/UI/BrioStyle.cs @@ -2,9 +2,14 @@ using System.Numerics; namespace Brio.UI; -internal static class BrioStyle +public static class BrioStyle { public static bool EnableStyle { get; set; } + public static bool EnableColor => Config.ConfigurationService.Instance.Configuration.Appearance.EnableBrioColor; + + static bool _hasPushed = false; + static bool _hasPushedColor = false; + static float _lastGlobalScale; public static void PushStyle() { @@ -12,6 +17,86 @@ public static void PushStyle() { return; } + _hasPushed = true; + + var imIO = ImGui.GetIO(); + + _lastGlobalScale = imIO.FontGlobalScale; + imIO.FontGlobalScale = 1f; + + if(EnableColor) + { + _hasPushedColor = true; + + PushStyleColor(ImGuiCol.Text, new Vector4(255, 255, 255, 255)); + PushStyleColor(ImGuiCol.TextDisabled, new Vector4(128, 128, 128, 255)); + + PushStyleColor(ImGuiCol.WindowBg, new Vector4(25, 25, 25, 248)); + PushStyleColor(ImGuiCol.ChildBg, new Vector4(25, 25, 25, 228)); + PushStyleColor(ImGuiCol.PopupBg, new Vector4(25, 25, 25, 248)); + + PushStyleColor(ImGuiCol.Border, new Vector4(44, 44, 44, 255)); + PushStyleColor(ImGuiCol.BorderShadow, new Vector4(0, 0, 0, 128)); + + PushStyleColor(ImGuiCol.FrameBg, new Vector4(36, 36, 36, 255)); + PushStyleColor(ImGuiCol.FrameBgHovered, new Vector4(57, 57, 57, 255)); + PushStyleColor(ImGuiCol.FrameBgActive, new Vector4(33, 33, 3, 255)); + + PushStyleColor(ImGuiCol.TitleBg, new Vector4(27, 27, 27, 232)); + PushStyleColor(ImGuiCol.TitleBgActive, new Vector4(33, 33, 33, 255)); + PushStyleColor(ImGuiCol.TitleBgCollapsed, new Vector4(30, 30, 30, 255)); + + PushStyleColor(ImGuiCol.MenuBarBg, new Vector4(36, 36, 36, 255)); + PushStyleColor(ImGuiCol.ScrollbarBg, new Vector4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol.ScrollbarGrab, new Vector4(62, 62, 62, 255)); + PushStyleColor(ImGuiCol.ScrollbarGrabHovered, new Vector4(70, 70, 70, 255)); + PushStyleColor(ImGuiCol.ScrollbarGrabActive, new Vector4(70, 70, 70, 255)); + + PushStyleColor(ImGuiCol.CheckMark, new Vector4(98, 75, 224, 255)); + + PushStyleColor(ImGuiCol.SliderGrab, new Vector4(101, 101, 101, 255)); + PushStyleColor(ImGuiCol.SliderGrabActive, new Vector4(123, 123, 123, 255)); + + PushStyleColor(ImGuiCol.Button, new Vector4(255, 255, 255, 31)); + PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(74, 56, 170, 255)); + PushStyleColor(ImGuiCol.ButtonActive, new Vector4(54, 42, 122, 255)); + + PushStyleColor(ImGuiCol.Header, new Vector4(0, 0, 0, 60)); + PushStyleColor(ImGuiCol.HeaderHovered, new Vector4(0, 0, 0, 90)); + PushStyleColor(ImGuiCol.HeaderActive, new Vector4(0, 0, 0, 120)); + + PushStyleColor(ImGuiCol.Separator, new Vector4(75, 75, 75, 121)); + PushStyleColor(ImGuiCol.SeparatorHovered, new Vector4(37, 25, 98, 255)); + PushStyleColor(ImGuiCol.SeparatorActive, new Vector4(98, 75, 224, 255)); + + PushStyleColor(ImGuiCol.ResizeGrip, new Vector4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol.ResizeGripHovered, new Vector4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol.ResizeGripActive, new Vector4(98, 75, 224, 255)); + + PushStyleColor(ImGuiCol.Tab, new Vector4(41, 41, 41, 255)); + PushStyleColor(ImGuiCol.TabHovered, new Vector4(42, 29, 113, 255)); + PushStyleColor(ImGuiCol.TabActive, new Vector4(98, 75, 224, 255)); + PushStyleColor(ImGuiCol.TabUnfocused, new Vector4(41, 39, 41, 255)); + PushStyleColor(ImGuiCol.TabUnfocusedActive, new Vector4(73, 48, 205, 255)); + + PushStyleColor(ImGuiCol.DockingPreview, new Vector4(91, 70, 208, 105)); + PushStyleColor(ImGuiCol.DockingEmptyBg, new Vector4(51, 51, 51, 255)); + + PushStyleColor(ImGuiCol.PlotLines, new Vector4(156, 156, 156, 255)); + + PushStyleColor(ImGuiCol.TableHeaderBg, new Vector4(48, 48, 48, 255)); + PushStyleColor(ImGuiCol.TableBorderStrong, new Vector4(79, 79, 89, 255)); + PushStyleColor(ImGuiCol.TableBorderLight, new Vector4(59, 59, 64, 255)); + PushStyleColor(ImGuiCol.TableRowBg, new Vector4(0, 0, 0, 0)); + PushStyleColor(ImGuiCol.TableRowBgAlt, new Vector4(255, 255, 255, 15)); + + PushStyleColor(ImGuiCol.TextSelectedBg, new Vector4(98, 75, 224, 255)); + PushStyleColor(ImGuiCol.DragDropTarget, new Vector4(98, 75, 224, 255)); + + PushStyleColor(ImGuiCol.NavHighlight, new Vector4(98, 75, 224, 179)); + PushStyleColor(ImGuiCol.NavWindowingDimBg, new Vector4(204, 204, 204, 51)); + PushStyleColor(ImGuiCol.NavWindowingHighlight, new Vector4(204, 204, 204, 89)); + } ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(6, 6)); ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(4, 3)); @@ -37,13 +122,31 @@ public static void PushStyle() ImGui.PushStyleVar(ImGuiStyleVar.TabRounding, 4f); } + static void PushStyleColor(ImGuiCol imGuiCol, Vector4 colorVector) + { + uint r = (uint)(colorVector.X) & 0xFF; + uint g = (uint)(colorVector.Y) & 0xFF; + uint b = (uint)(colorVector.Z) & 0xFF; + uint a = (uint)(colorVector.W) & 0xFF; + + ImGui.PushStyleColor(imGuiCol, (a << 24) | (b << 16) | (g << 8) | r); + } + public static void PopStyle() { - if(EnableStyle == false) + if(_hasPushed) { - return; - } + _hasPushed = false; + + ImGui.PopStyleVar(19); - ImGui.PopStyleVar(19); + if(_hasPushedColor) + { + _hasPushedColor = false; + ImGui.PopStyleColor(51); + } + + ImGui.GetIO().FontGlobalScale = _lastGlobalScale; + } } } diff --git a/Brio/UI/Controls/Core/UIConstants.cs b/Brio/UI/Controls/Core/UIConstants.cs index a6143bfb..843e5c70 100644 --- a/Brio/UI/Controls/Core/UIConstants.cs +++ b/Brio/UI/Controls/Core/UIConstants.cs @@ -1,6 +1,7 @@  namespace Brio.UI.Controls.Core; -internal static class UIConstants + +public static class UIConstants { public const uint ToggleButtonInactive = 0xFFFFFFFF; public const uint ToggleButtonActive = 0xFF0050FF; @@ -11,4 +12,7 @@ internal static class UIConstants public const uint GizmoBlue = 0x88FF3333; public const uint GizmoGreen = 0x8833FF33; public const uint GizmoRed = 0x883333FF; + + public const uint GizmoMagenta = 0xFFB500FF; + } diff --git a/Brio/UI/Controls/Editors/ActionTimelineEditor.cs b/Brio/UI/Controls/Editors/ActionTimelineEditor.cs index d125676d..4018c668 100644 --- a/Brio/UI/Controls/Editors/ActionTimelineEditor.cs +++ b/Brio/UI/Controls/Editors/ActionTimelineEditor.cs @@ -20,7 +20,7 @@ namespace Brio.UI.Controls.Editors; -internal class ActionTimelineEditor(CutsceneManager cutsceneManager, GPoseService gPoseService, EntityManager entityManager, PhysicsService physicsService, ConfigurationService configService) +public class ActionTimelineEditor(CutsceneManager cutsceneManager, GPoseService gPoseService, EntityManager entityManager, PhysicsService physicsService, ConfigurationService configService) { private readonly CutsceneManager _cutsceneManager = cutsceneManager; private readonly GPoseService _gPoseService = gPoseService; @@ -31,7 +31,6 @@ internal class ActionTimelineEditor(CutsceneManager cutsceneManager, GPoseServic private static float MaxItemWidth => ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("XXXXXXXXXXXXXXXXXX").X; private static float LabelStart => MaxItemWidth + ImGui.GetCursorPosX() + (ImGui.GetStyle().FramePadding.X * 2f); - private static readonly float _hederButtonSize = ImGui.CalcTextSize("#########").X + 28; private static readonly ActionTimelineSelector _globalTimelineSelector = new("global_timeline_selector"); private static bool _startAnimationOnSelect = true; @@ -52,6 +51,13 @@ public void Draw(bool drawAdvanced, ActionTimelineCapability capability) DrawBlend(); DrawOverallSpeed(drawAdvanced); + if(drawAdvanced == false) + { + ImGui.Separator(); + + DrawFirstScrub(); + } + if(drawAdvanced) { DrawLips(); @@ -75,16 +81,16 @@ public void Draw(bool drawAdvanced, ActionTimelineCapability capability) private void DrawHeder() { - if(ImBrio.ToggelButton("Freeze Physics", new Vector2(95, 0), _physicsService.IsFreezeEnabled, hoverText: _physicsService.IsFreezeEnabled ? "Un-Freeze Physics" : "Freeze Physics")) + if(ImBrio.ToggelButton("Freeze Physics", new Vector2(95, 25), _physicsService.IsFreezeEnabled, hoverText: _physicsService.IsFreezeEnabled ? "Un-Freeze Physics" : "Freeze Physics")) { _physicsService.FreezeToggle(); } ImGui.SameLine(); - ImBrio.RightAlign(_hederButtonSize, 1); + ImBrio.RightAlign(97, 1); - if(ImGui.Button("Actors ")) + if(ImGui.Button("Actors ", new Vector2(70, 25))) { ImGui.OpenPopup("animation_control"); } @@ -94,7 +100,7 @@ private void DrawHeder() using(ImRaii.PushColor(ImGuiCol.Button, 0)) { var curPos = ImGui.GetCursorPos(); - ImGui.SetCursorPos(new Vector2(curPos.X - 28, curPos.Y)); + ImGui.SetCursorPos(new Vector2(curPos.X - 30, curPos.Y + 2)); ImGui.ArrowButton("###animation_control_drop", ImGuiDir.Down); } @@ -335,8 +341,6 @@ private void DrawLips() private unsafe void DrawScrub() { - bool drewAny = false; - float width = -ImGui.CalcTextSize("XXXX").X; var drawObj = _capability.Character.Native()->GameObject.DrawObject; @@ -374,24 +378,77 @@ private unsafe void DrawScrub() if(anim == null) continue; - if(control->PlaybackSpeed == 0) + var duration = anim->Duration; + var time = control->hkaAnimationControl.LocalTime; + ImGui.SetNextItemWidth(width); + if(ImGui.SliderFloat($"###scrub_{p}_{c}", ref time, 0f, duration, "%.2f", ImGuiSliderFlags.AlwaysClamp)) { - drewAny |= true; - var duration = anim->Duration; - var time = control->hkaAnimationControl.LocalTime; - ImGui.SetNextItemWidth(width); - if(ImGui.SliderFloat($"###scrub_{p}_{c}", ref time, 0f, duration, "%.2f", ImGuiSliderFlags.AlwaysClamp)) - { - control->hkaAnimationControl.LocalTime = time; - } - ImGui.SameLine(); - ImGui.Text($"{p}.{c}"); + control->hkaAnimationControl.LocalTime = time; + } + if(ImGui.IsItemClicked(ImGuiMouseButton.Left)) + { + _capability.SetOverallSpeedOverride(0f); } + ImGui.SameLine(); + ImGui.Text($"{p}.{c}"); } } + } - if(!drewAny) - ImGui.Text("Pause motion to enable."); + private unsafe void DrawFirstScrub() + { + + var drawObj = _capability.Character.Native()->GameObject.DrawObject; + if(drawObj == null) + return; + + if(drawObj->Object.GetObjectType() != ObjectType.CharacterBase) + return; + + var charaBase = (CharacterBase*)drawObj; + + if(charaBase->Skeleton == null) + return; + + var skeleton = charaBase->Skeleton; + + if(!(skeleton->PartialSkeletonCount > 0)) + return; + + var partial = &skeleton->PartialSkeletons[0]; + var animatedSkele = partial->GetHavokAnimatedSkeleton(0); + if(animatedSkele == null) + return; + + if(!(animatedSkele->AnimationControls.Length > 0)) + return; + + var control = animatedSkele->AnimationControls[0].Value; + if(control == null) + return; + + var binding = control->hkaAnimationControl.Binding; + if(binding.ptr == null) + return; + + var anim = binding.ptr->Animation.ptr; + if(anim == null) + return; + + var duration = anim->Duration; + var time = control->hkaAnimationControl.LocalTime; + + ImGui.SetNextItemWidth(-ImGui.CalcTextSize("ScrubX").X); + if(ImGui.SliderFloat($"###scrub_001", ref time, 0f, duration, "%.2f", ImGuiSliderFlags.AlwaysClamp)) + { + control->hkaAnimationControl.LocalTime = time; + } + if(ImGui.IsItemClicked(ImGuiMouseButton.Left)) + { + _capability.SetOverallSpeedOverride(0f); + } + ImGui.SameLine(); + ImGui.Text("Scrub"); } private void DrawSlots() diff --git a/Brio/UI/Controls/Editors/ActorEditor.cs b/Brio/UI/Controls/Editors/ActorEditor.cs new file mode 100644 index 00000000..366bd810 --- /dev/null +++ b/Brio/UI/Controls/Editors/ActorEditor.cs @@ -0,0 +1,47 @@ +using Brio.Capabilities.Actor; +using Brio.Entities.Actor; +using Brio.UI.Controls.Core; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace Brio.UI.Controls.Editors; + +public class ActorEditor +{ + public unsafe static void DrawSpawnMenu(ActorContainerEntity actorContainerEntity) + { + var hasCapability = actorContainerEntity.TryGetCapability(out var capability); + + using(ImRaii.Disabled(hasCapability == false)) + { + DrawSpawnMenu(capability!); + } + } + + private unsafe static void DrawSpawnMenu(ActorContainerCapability actorContainerCapability) + { + using var popup = ImRaii.Popup("ActorEditorDrawSpawnMenuPopup"); + if(popup.Success) + { + using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.Transparent)) + { + if(ImGui.Button("Spawn Actor")) + { + actorContainerCapability.CreateCharacter(false, true, forceSpawnActorWithoutCompanion: true); + } + + if(ImGui.Button("Spawn Actor with Slot")) + { + actorContainerCapability.CreateCharacter(true, true); + } + + ImGui.Separator(); + + if(ImGui.Button("Spawn Prop")) + { + actorContainerCapability.CreateProp(true); + } + } + } + } +} diff --git a/Brio/UI/Controls/Editors/AppearanceEditorCommon.cs b/Brio/UI/Controls/Editors/AppearanceEditorCommon.cs index 0017014f..75b4ca78 100644 --- a/Brio/UI/Controls/Editors/AppearanceEditorCommon.cs +++ b/Brio/UI/Controls/Editors/AppearanceEditorCommon.cs @@ -5,15 +5,20 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; +using System.Collections.Generic; using System.Linq; using System.Numerics; namespace Brio.UI.Controls.Editors; -internal static class AppearanceEditorCommon +public static class AppearanceEditorCommon { private const string _collectionLabel = "Collection"; - private static float _lableWidth { get; } = ImGui.CalcTextSize($"{_collectionLabel} XXXXXXXXXX").X; + private const string _collectionLabelDesign = "Design"; + private const string _collectionLabelProfile = "Profile"; + private static float _lableWidth { get; } = ImGui.CalcTextSize($"{_collectionLabel} IIXXXXXXXX").X; + private static float _lableWidthDesign { get; } = ImGui.CalcTextSize($"{_collectionLabelDesign} IIIXXXXXXXXXX").X; + private static float _lableWidthProfile { get; } = ImGui.CalcTextSize($"{_collectionLabelProfile} IIIIIXXXXXXXXX").X; private static readonly NpcSelector _globalNpcSelector = new("global_npc_selector"); @@ -22,7 +27,7 @@ public static void DrawPenumbraCollectionSwitcher(ActorAppearanceCapability capa if(!capability.HasPenumbraIntegration) return; - if(ImBrio.FontIconButton(FontAwesomeIcon.EarthOceania)) + if(ImBrio.FontIconButton(FontAwesomeIcon.EarthOceania, new Vector2(25))) { capability.PenumbraService.OpenPenumbra(); } @@ -52,9 +57,123 @@ public static void DrawPenumbraCollectionSwitcher(ActorAppearanceCapability capa ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("actorappearancewidget_reset", FontAwesomeIcon.Undo, 1, "Reset", capability.IsCollectionOverridden)) + if(ImBrio.FontIconButtonRight("actorappearancewidget_reset", FontAwesomeIcon.Undo, 1, "Reset Collection", capability.IsCollectionOverridden)) capability.ResetCollection(); } + public static void DrawGlamourerDesignSwitcher(ActorAppearanceCapability capability) + { + if(!capability.HasGlamourerIntegration) + return; + + if(ImBrio.FontIconButton(FontAwesomeIcon.TheaterMasks, new Vector2(25))) + { + + } + + if(ImGui.IsItemHovered()) + ImGui.SetTooltip("Glamourer Design"); + ImGui.SameLine(); + + var currentDesign = capability.CurrentDesign; + + ImGui.SetNextItemWidth(_lableWidthDesign); + + using(var combo = ImRaii.Combo(_collectionLabelDesign, "Apply Design")) + { + if(combo.Success) + { + var collections = capability.GlamourerService.GetDesignList(); + + if(collections is not null) + { + foreach(var collection in collections) + { + bool isSelected = collection.Value.Equals(currentDesign); + if(ImGui.Selectable(collection.Value, isSelected)) + { + capability.CurrentDesign = collection.Value; + capability.SetDesign(collection.Key); + } + } + } + } + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("actorappearancewidget_DesignReset", FontAwesomeIcon.Undo, 1, "Reset Design")) + capability.ResetDesign(); + + } + + private static bool _isProfileOpen = false; + private static IEnumerable _profiles = []; + public static void DrawCustomizePlusProfileSwitcher(ActorAppearanceCapability capability) + { + if(!capability.HasCustomizePlusIntegration) + return; + + if(ImGui.Button("C+", new Vector2(25))) + { + + } + + if(ImGui.IsItemHovered()) + ImGui.SetTooltip("Customize+ Profile"); + ImGui.SameLine(); + + ImGui.SetNextItemWidth(_lableWidthProfile); + + if(capability.SelectedDesign.name is null) + { + capability.SetSelectedProfile(); + } + + using(var combo = ImRaii.Combo(_collectionLabelProfile, capability.SelectedDesign.name!)) + { + if(combo.Success) + { + if(_isProfileOpen == false) + { + _isProfileOpen = true; + _profiles = capability.CustomizePlusService.GetProfiles(); + + if(capability.SelectedDesign.id is null) + capability.SetSelectedProfile(); + } + + if(_profiles is not null) + { + foreach(var collection in _profiles) + { + bool isSelected = collection.UniqueId.Equals(capability.CurrentProfile.id); + if(ImGui.Selectable(collection.Name, isSelected)) + { + capability.ResetProfile(); + var (_, data) = capability.CustomizePlusService.GetProfile(collection.UniqueId); + if(string.IsNullOrEmpty(data) == false) + { + capability.SelectedDesign = (collection.Name, collection.UniqueId); + capability.SetProfile(data); + } + } + } + } + } + else if(_isProfileOpen) + { + _isProfileOpen = false; + _profiles = []; + } + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("actorappearancewidget_ProfileReset", FontAwesomeIcon.Undo, 1, "Reset C+ Profile")) + { + capability.ResetProfile(); + } + } public static void ResetNPCSelector() { diff --git a/Brio/UI/Controls/Editors/BoneIKEditor.cs b/Brio/UI/Controls/Editors/BoneIKEditor.cs index 3de32da1..4568ca48 100644 --- a/Brio/UI/Controls/Editors/BoneIKEditor.cs +++ b/Brio/UI/Controls/Editors/BoneIKEditor.cs @@ -4,7 +4,7 @@ using ImGuiNET; namespace Brio.UI.Controls.Editors; -internal class BoneIKEditor +public class BoneIKEditor { public static void Draw(BonePoseInfo poseInfo, PosingCapability posing) { diff --git a/Brio/UI/Controls/Editors/BoneSearchControl.cs b/Brio/UI/Controls/Editors/BoneSearchControl.cs index 23723a17..2e43f736 100644 --- a/Brio/UI/Controls/Editors/BoneSearchControl.cs +++ b/Brio/UI/Controls/Editors/BoneSearchControl.cs @@ -9,7 +9,7 @@ namespace Brio.UI.Controls.Editors; -internal class BoneSearchControl +public class BoneSearchControl { private string _searchTerm = string.Empty; public void Draw(string id, PosingCapability posing) diff --git a/Brio/UI/Controls/Editors/CameraEditor.cs b/Brio/UI/Controls/Editors/CameraEditor.cs index 009e27f9..bf067bdd 100644 --- a/Brio/UI/Controls/Editors/CameraEditor.cs +++ b/Brio/UI/Controls/Editors/CameraEditor.cs @@ -1,142 +1,269 @@ using Brio.Capabilities.Camera; +using Brio.Entities.Camera; +using Brio.Game.Camera; +using Brio.UI.Controls.Core; using Brio.UI.Controls.Stateless; +using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; using System.Numerics; namespace Brio.UI.Controls.Editors; -internal static class CameraEditor +public static class CameraEditor { - struct CameraPresetProperties(Vector3 offset, float rotation, float zoom, float fov, Vector2 pan, Vector2 angle, bool disableCollision, bool delimitCamera) + public unsafe static void DrawSpawnMenu(VirtualCameraManager virtualCameraManager) { - public bool isSet = true; - public Vector3 offset = offset; - public float rotation = rotation; - public float zoom = zoom; - public float fov = fov; - public Vector2 pan = pan; - public Vector2 angle = angle; - public bool disableCollision = disableCollision; - public bool delimitCamera = delimitCamera; + using var popup = ImRaii.Popup("DrawSpawnMenuPopup"); + if(popup.Success) + { + using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.Transparent)) + { + if(ImGui.Button("New Brio Camera")) + { + virtualCameraManager.CreateCamera(CameraType.Brio); + } + + if(ImGui.Button("New Free-Cam")) + { + virtualCameraManager.CreateCamera(CameraType.Free); + } + + //ImGui.Separator(); + + //if(ImGui.Button("New Cutscene Camera")) + //{ + // virtualCameraManager.CreateCamera(CameraType.Cutscene); + //} + } + } } - private static readonly CameraPresetProperties[] presets = new CameraPresetProperties[3]; - public unsafe static void Draw(string id, CameraCapability capability) + public unsafe static void DrawFreeCam(string id, BrioCameraCapability capability) { - var camera = capability.Camera; + var camera = capability.VirtualCamera; using(ImRaii.PushId(id)) { using(ImRaii.Disabled(!capability.IsAllowed)) { - if(camera != null) + var width = -ImGui.CalcTextSize("XXXXXXXx").X; + + if(ImBrio.ToggelButton("Enable Movement", new Vector2(135, 25), camera.FreeCamValues.IsMovementEnabled, hoverText: camera.FreeCamValues.IsMovementEnabled ? + "Disable Free-Cam Movement" : "Enabled Free-Cam Movement")) { - var width = -ImGui.CalcTextSize("XXXXXXXXXx").X; + camera.FreeCamValues.IsMovementEnabled = !camera.FreeCamValues.IsMovementEnabled; + } + + ImGui.SameLine(); + + using(ImRaii.Disabled(camera.FreeCamValues.IsMovementEnabled == false)) + { + if(ImBrio.ToggelFontIconButton("LateralMovement", FontAwesomeIcon.SolarPanel, new Vector2(25, 0), camera.FreeCamValues.Move2D, hoverText: "Lateral Movement")) + { + camera.FreeCamValues.Move2D = !camera.FreeCamValues.Move2D; + } + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("reset", FontAwesomeIcon.Undo, 1f, "Reset", camera.IsOverridden)) + camera.ResetCamera(); + + // + ImGui.Separator(); + // + + { + ImBrio.Icon(FontAwesomeIcon.ArrowsToCircle); + + ImGui.SameLine(); - const string offsetText = "Offset"; - Vector3 pos = capability.PositionOffset; ImGui.SetNextItemWidth(width); - if(ImGui.DragFloat3(offsetText, ref pos, 0.001f)) - capability.PositionOffset = pos; + var position = camera.Position; + if(ImGui.DragFloat3("Position", ref position, 0.001f)) + camera.Position = position; + } + + { + ImBrio.Icon(FontAwesomeIcon.ArrowsSpin); ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("reset", Dalamud.Interface.FontAwesomeIcon.Undo, 1f, "Reset", capability.IsOveridden)) - capability.Reset(); + ImGui.SetNextItemWidth(width); + var rotation = camera.Rotation; + if(ImGui.DragFloat3("Rotation", ref rotation, 0.001f)) + camera.Rotation = rotation; + } + + { + ImBrio.Icon(FontAwesomeIcon.Panorama); + + ImGui.SameLine(); + + var fov = camera.FoV; + if(ImBrio.SliderAngle("##FoV", ref fov, -44, 120, "%.2f", ImGuiSliderFlags.AlwaysClamp)) + camera.FoV = fov; + } + + ImGui.Separator(); + + { + ImBrio.Icon(FontAwesomeIcon.Walking); + + ImGui.SameLine(); + + float moveSpeed = camera.FreeCamValues.MovementSpeed; + if(ImBrio.SliderFloat("##MovementSpeed", ref moveSpeed, 0.005f, 0.3f, "%.4f", ImGuiSliderFlags.None, step: 0.001f)) + camera.FreeCamValues.MovementSpeed = moveSpeed; + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("resetMovementSpeed", FontAwesomeIcon.Undo, 1f, "Reset Movement Speed", moveSpeed != VirtualCameraManager.DefaultMovementSpeed)) + camera.FreeCamValues.MovementSpeed = VirtualCameraManager.DefaultMovementSpeed; + } + + { + ImBrio.Icon(FontAwesomeIcon.Mouse); + + ImGui.SameLine(); + + float mouseSpeed = camera.FreeCamValues.MouseSensitivity; + if(ImBrio.SliderFloat("##MouseSensitivity", ref mouseSpeed, 0.001f, 0.2f, "%.4f", ImGuiSliderFlags.None, step: 0.001f)) + camera.FreeCamValues.MouseSensitivity = mouseSpeed; + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("resetMouseSensitivity", FontAwesomeIcon.Undo, 1f, "Reset MouseSensitivity", mouseSpeed != VirtualCameraManager.DefaultMouseSensitivity)) + camera.FreeCamValues.MouseSensitivity = VirtualCameraManager.DefaultMouseSensitivity; + } + + ImGui.Separator(); + + var delimit = camera.FreeCamValues.DelimitAngle; + if(ImGui.Checkbox("Delimit Camera Angle", ref delimit)) + camera.FreeCamValues.DelimitAngle = delimit; + } + } + } + + public unsafe static void DrawBrioCam(string id, BrioCameraCapability capability) + { + var camera = capability.VirtualCamera; + + using(ImRaii.PushId(id)) + { + using(ImRaii.Disabled(!capability.IsAllowed)) + { + if(camera is not null) + { + var width = -ImGui.CalcTextSize("XXXXXXXXXx").X; + + if(ImBrio.FontIconButtonRight("reset", FontAwesomeIcon.Undo, 1f, "Reset", camera.IsOverridden)) + camera.ResetCamera(); + + // + ImGui.Separator(); + // + + { + const string offsetText = "Position"; + + ImBrio.Icon(FontAwesomeIcon.ArrowsToCircle); + + ImGui.SameLine(); + + ImGui.SetNextItemWidth(width); + var position = camera.RealPosition; + using(ImRaii.Disabled(true)) + { + ImGui.DragFloat3(offsetText, ref position, 0.001f); + } + } + + { + const string offsetText = "Offset"; + + ImBrio.Icon(FontAwesomeIcon.ArrowsUpDownLeftRight); + + ImGui.SameLine(); + + Vector3 pos = camera.PositionOffset; + ImGui.SetNextItemWidth(width); + if(ImGui.DragFloat3(offsetText, ref pos, 0.001f)) + camera.PositionOffset = pos; + + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("resetPosition", FontAwesomeIcon.Undo, 1f, "Reset Position-Offset", camera.PositionOffset != Vector3.Zero)) + camera.PositionOffset = Vector3.Zero; + } + + ImGui.Separator(); const string rotationText = "Rotation"; - float rotation = camera->Rotation; + float rotation = camera.PivotRotation; ImGui.SetNextItemWidth(width); if(ImBrio.SliderAngle(rotationText, ref rotation, -180, 180, "%.2f")) - camera->Rotation = rotation; + camera.PivotRotation = rotation; ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("resetRotation", Dalamud.Interface.FontAwesomeIcon.Undo, 1f, "Reset", rotation != 0)) - camera->Rotation = 0; + if(ImBrio.FontIconButtonRight("resetRotation", FontAwesomeIcon.Undo, 1f, "Reset", rotation != 0)) + camera.PivotRotation = 0; const string zoomText = "Zoom"; - float zoom = camera->Camera.Distance; + float zoom = camera.Zoom; ImGui.SetNextItemWidth(width); - if(ImBrio.SliderFloat(zoomText, ref zoom, camera->Camera.MaxDistance, camera->Camera.MinDistance, "%.2f", ImGuiSliderFlags.AlwaysClamp)) - camera->Camera.Distance = zoom; + if(ImBrio.SliderFloat(zoomText, ref zoom, camera.BrioCamera->Camera.MaxDistance, camera.BrioCamera->Camera.MinDistance, "%.2f", ImGuiSliderFlags.AlwaysClamp)) + camera.Zoom = zoom; ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("resetZoom", Dalamud.Interface.FontAwesomeIcon.Undo, 1f, "Reset", zoom != 2.5)) - camera->Camera.Distance = 2.5f; + if(ImBrio.FontIconButtonRight("resetZoom", FontAwesomeIcon.Undo, 1f, "Reset", zoom != 2.5)) + camera.Zoom = 2.5f; const string fovText = "FoV"; - float fov = camera->FoV; + float fov = camera.FoV; ImGui.SetNextItemWidth(width); if(ImBrio.SliderAngle(fovText, ref fov, -44, 120, "%.2f", ImGuiSliderFlags.AlwaysClamp)) - camera->FoV = fov; + camera.FoV = fov; ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("resetFoV", Dalamud.Interface.FontAwesomeIcon.Undo, 1f, "Reset", fov != 0)) - camera->FoV = 0f; + if(ImBrio.FontIconButtonRight("resetFoV", FontAwesomeIcon.Undo, 1f, "Reset", fov != 0)) + camera.FoV = 0f; + + ImGui.Separator(); const string panText = "Pan"; - Vector2 pan = camera->Pan; + Vector2 pan = camera.Pan; ImGui.SetNextItemWidth(width); if(ImGui.DragFloat2(panText, ref pan, 0.001f)) - camera->Pan = pan; + camera.Pan = pan; ImGui.SameLine(); - if(ImBrio.FontIconButtonRight("resetPan", Dalamud.Interface.FontAwesomeIcon.Undo, 1f, "Reset", pan != Vector2.Zero)) - camera->Pan = new Vector2(0, 0); + if(ImBrio.FontIconButtonRight("resetPan", FontAwesomeIcon.Undo, 1f, "Reset", pan != Vector2.Zero)) + camera.Pan = Vector2.Zero; const string angleText = "Angle"; - Vector2 angle = camera->Angle; + Vector2 angle = camera.Angle; ImGui.SetNextItemWidth(width); if(ImGui.DragFloat2(angleText, ref angle, 0.001f)) - camera->Angle = angle; + camera.Angle = angle; - var disable = capability.DisableCollision; + ImGui.Separator(); + + var disable = camera.DisableCollision; if(ImGui.Checkbox("Disable Collision", ref disable)) - capability.DisableCollision = disable; + camera.DisableCollision = disable; ImGui.SameLine(); - var delimit = capability.DelimitCamera; + var delimit = camera.DelimitCamera; if(ImGui.Checkbox("Delimit Camera", ref delimit)) - capability.DelimitCamera = delimit; - - ImGui.Separator(); - - if(ImGui.CollapsingHeader("Camera Presets")) - { - for(int i = 0; i < 3; i++) - { - ImGui.Text($"Preset {i + 1} :"); - - ImGui.SameLine(); - - if(ImGui.Button($"Save##{i}")) - presets[i] = new CameraPresetProperties(capability.PositionOffset, camera->Rotation, - camera->Camera.Distance, camera->FoV, camera->Pan, camera->Angle, - capability.DisableCollision, capability.DelimitCamera); - - if(presets[i].isSet) - { - ImGui.SameLine(); - if(ImGui.Button($"Load##{i}")) - { - capability.PositionOffset = presets[i].offset; - camera->Rotation = presets[i].rotation; - camera->Camera.Distance = presets[i].zoom; - camera->FoV = presets[i].fov; - camera->Pan = presets[i].pan; - camera->Angle = presets[i].angle; - capability.DisableCollision = presets[i].disableCollision; - capability.DelimitCamera = presets[i].delimitCamera; - } - } - } - } + camera.DelimitCamera = delimit; } } } diff --git a/Brio/UI/Controls/Editors/CustomizeEditor.cs b/Brio/UI/Controls/Editors/CustomizeEditor.cs index 9e8177ff..4279c084 100644 --- a/Brio/UI/Controls/Editors/CustomizeEditor.cs +++ b/Brio/UI/Controls/Editors/CustomizeEditor.cs @@ -14,7 +14,7 @@ namespace Brio.UI.Controls.Editors; -internal class CustomizeEditor() +public class CustomizeEditor() { private float MaxItemWidth => ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("XXXXXXXXXX").X; private float LabelStart => MaxItemWidth + ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X * 2f; diff --git a/Brio/UI/Controls/Editors/ExtendedAppearanceEditor.cs b/Brio/UI/Controls/Editors/ExtendedAppearanceEditor.cs index bfed5d8c..19a5e728 100644 --- a/Brio/UI/Controls/Editors/ExtendedAppearanceEditor.cs +++ b/Brio/UI/Controls/Editors/ExtendedAppearanceEditor.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Controls.Editors; -internal class ExtendedAppearanceEditor +public class ExtendedAppearanceEditor { private static float MaxItemWidth => ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("XXXXXXXXXX").X; private static float LabelStart => MaxItemWidth + ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X * 2f; diff --git a/Brio/UI/Controls/Editors/GearEditor.cs b/Brio/UI/Controls/Editors/GearEditor.cs index f828e654..f2f8fa86 100644 --- a/Brio/UI/Controls/Editors/GearEditor.cs +++ b/Brio/UI/Controls/Editors/GearEditor.cs @@ -12,7 +12,7 @@ namespace Brio.UI.Controls.Editors; -internal class GearEditor() +public class GearEditor() { private WeaponModelId BlankItem = new() { Id = 0, Type = 0 }; diff --git a/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs b/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs index 79df1ee8..580d87c1 100644 --- a/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs +++ b/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs @@ -9,7 +9,7 @@ using static Brio.Config.LibraryConfiguration; namespace Brio.UI.Controls.Editors; -internal static class LibrarySourcesEditor +public static class LibrarySourcesEditor { static Vector2 MinimumSize = new(400, 95); diff --git a/Brio/UI/Controls/Editors/ModelShaderEditor.cs b/Brio/UI/Controls/Editors/ModelShaderEditor.cs index 63423d88..b4eb2d2c 100644 --- a/Brio/UI/Controls/Editors/ModelShaderEditor.cs +++ b/Brio/UI/Controls/Editors/ModelShaderEditor.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Controls.Editors; -internal class ModelShaderEditor() +public class ModelShaderEditor() { private static float MaxItemWidth => ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("XXXXXXXXXX").X; private static float LabelStart => MaxItemWidth + ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X * 2f; diff --git a/Brio/UI/Controls/Editors/PosingEditorCommon.cs b/Brio/UI/Controls/Editors/PosingEditorCommon.cs index 471a04d2..0da6042d 100644 --- a/Brio/UI/Controls/Editors/PosingEditorCommon.cs +++ b/Brio/UI/Controls/Editors/PosingEditorCommon.cs @@ -1,8 +1,8 @@ using Brio.Capabilities.Posing; using Brio.Core; using Brio.Game.Posing; -using Brio.UI.Controls.Core; using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; @@ -11,56 +11,62 @@ namespace Brio.UI.Controls.Editors; -internal static class PosingEditorCommon +public static class PosingEditorCommon { public static void DrawSelectionName(PosingCapability posing) { ImGui.Text(posing.Selected.DisplayName); - ImGui.SetWindowFontScale(0.75f); - ImGui.TextDisabled(posing.Selected.Subtitle); - ImGui.SetWindowFontScale(1.0f); + if(posing.Actor.IsProp == false) + { + ImGui.SetWindowFontScale(0.75f); + ImGui.TextDisabled(posing.Selected.Subtitle); + ImGui.SetWindowFontScale(1.0f); + } } - public static void DrawImportOptionEditor(PoseImporterOptions options) + public static void DrawImportOptionEditor(PoseImporterOptions options, bool compact = false) { DrawBoneFilterEditor(options.BoneFilter); - ImGui.Separator(); - - var selected = options.TransformComponents.HasFlag(TransformComponents.Position); - if(ImGui.Checkbox("Position", ref selected)) + if(compact == false) { - if(selected) - options.TransformComponents |= TransformComponents.Position; - else - options.TransformComponents &= ~TransformComponents.Position; - } + ImGui.Separator(); - selected = options.TransformComponents.HasFlag(TransformComponents.Rotation); - if(ImGui.Checkbox("Rotation", ref selected)) - { - if(selected) - options.TransformComponents |= TransformComponents.Rotation; - else - options.TransformComponents &= ~TransformComponents.Rotation; - } + var selected = options.TransformComponents.HasFlag(TransformComponents.Position); + if(ImGui.Checkbox("Position", ref selected)) + { + if(selected) + options.TransformComponents |= TransformComponents.Position; + else + options.TransformComponents &= ~TransformComponents.Position; + } - selected = options.TransformComponents.HasFlag(TransformComponents.Scale); - if(ImGui.Checkbox("Scale", ref selected)) - { - if(selected) - options.TransformComponents |= TransformComponents.Scale; - else - options.TransformComponents &= ~TransformComponents.Scale; - } + selected = options.TransformComponents.HasFlag(TransformComponents.Rotation); + if(ImGui.Checkbox("Rotation", ref selected)) + { + if(selected) + options.TransformComponents |= TransformComponents.Rotation; + else + options.TransformComponents &= ~TransformComponents.Rotation; + } - ImGui.Separator(); + selected = options.TransformComponents.HasFlag(TransformComponents.Scale); + if(ImGui.Checkbox("Scale", ref selected)) + { + if(selected) + options.TransformComponents |= TransformComponents.Scale; + else + options.TransformComponents &= ~TransformComponents.Scale; + } - selected = options.ApplyModelTransform; - if(ImGui.Checkbox("Model Transform", ref selected)) - { - options.ApplyModelTransform = selected; + ImGui.Separator(); + + selected = options.ApplyModelTransform; + if(ImGui.Checkbox("Model Transform", ref selected)) + { + options.ApplyModelTransform = selected; + } } } @@ -155,11 +161,6 @@ public static void DrawMirrorModeSelect(PosingCapability posing, Vector2 buttonS } } - public static void DrawIKSelect(PosingCapability posing) - { - DrawIKSelect(posing, Vector2.Zero); - } - public static void DrawIKSelect(PosingCapability posing, Vector2 buttonSize) { if(posing.Selected.Value is BonePoseInfoId boneId) @@ -174,7 +175,7 @@ public static void DrawIKSelect(PosingCapability posing, Vector2 buttonSize) var ik = bonePose.DefaultIK; bool enabled = ik.Enabled && BrioStyle.EnableStyle; - using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.GizmoRed, enabled)) + using(ImRaii.PushColor(ImGuiCol.Button, TheameManager.CurrentTheame.Accent.AccentColor, enabled)) { if(ImGui.Button("IK", buttonSize)) ImGui.OpenPopup("transform_ik_popup"); diff --git a/Brio/UI/Controls/Editors/PosingTransformEditor.cs b/Brio/UI/Controls/Editors/PosingTransformEditor.cs index 3e660557..4eaa433b 100644 --- a/Brio/UI/Controls/Editors/PosingTransformEditor.cs +++ b/Brio/UI/Controls/Editors/PosingTransformEditor.cs @@ -5,11 +5,12 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; +using OneOf.Types; using System.Numerics; namespace Brio.UI.Controls.Editors; -internal class PosingTransformEditor +public class PosingTransformEditor { private Transform? _trackingTransform; private Vector3? _trackingEuler; @@ -26,28 +27,100 @@ public void Draw(string id, PosingCapability posingCapability, bool compactMode { using(ImRaii.PushId(id)) { + bool isBone = false; + Game.Posing.Skeletons.Bone? realBone = null; selected.Switch( bone => { - var realBone = posingCapability.SkeletonPosing.GetBone(bone); - if(realBone != null && realBone.Skeleton.IsValid && posingCapability.Actor.IsProp == false) + realBone = posingCapability.SkeletonPosing.GetBone(bone); + isBone = realBone != null && realBone.Skeleton.IsValid && posingCapability.Actor.IsProp == false; + + if(isBone) { DrawBoneTransformEditor(posingCapability, bone, compactMode); } else { - DrawModelTransformEditor(posingCapability); + DrawModelTransformEditor(posingCapability, compactMode); } }, - _ => DrawModelTransformEditor(posingCapability), - _ => DrawModelTransformEditor(posingCapability) + _ => DrawModelTransformEditor(posingCapability, compactMode), + _ => DrawModelTransformEditor(posingCapability, compactMode) ); + + if(posingCapability.Actor.IsProp == false) + { + ImGui.Separator(); + + using(ImRaii.Disabled(isBone == false)) + { + if(ImBrio.FontIconButton("propagate", FontAwesomeIcon.Compress, "Propagate", realBone?.EligibleForIK == true)) + ImGui.OpenPopup("transform_propagate_popup"); + + if(compactMode) + { + ImGui.SameLine(); + + PosingEditorCommon.DrawIKSelect(posingCapability, new Vector2(25)); + + ImGui.SameLine(); + + using(ImRaii.Disabled(posingCapability.Selected.Value is None)) + { + if(ImBrio.FontIconButton("clear_selection", FontAwesomeIcon.MinusSquare, "Clear Selection")) + posingCapability.ClearSelection(); + } + + // Select Parent + ImGui.SameLine(); + var parentBone = posingCapability.Selected.Match( + boneSelect => posingCapability.SkeletonPosing.GetBone(boneSelect)?.GetFirstVisibleParent(), + _ => null, + _ => null + ); + + using(ImRaii.Disabled(parentBone == null)) + { + if(ImBrio.FontIconButton(FontAwesomeIcon.LevelUpAlt, new Vector2(25))) + posingCapability.Selected = new BonePoseInfoId(parentBone!.Name, parentBone!.PartialId, PoseInfoSlot.Character); + } + + if(ImGui.IsItemHovered()) + ImGui.SetTooltip("Select Parent"); + } + } + ImGui.SameLine(); + + using(ImRaii.Disabled(true)) + if(ImBrio.FontIconButton("copypaste", FontAwesomeIcon.Clipboard, "Copy/Paste")) + ImGui.OpenPopup("transform_CopyPaste_popup"); + + if(isBone == false) + using(ImRaii.Disabled(posingCapability.ModelPosing.HasOverride == false)) + { + ImGui.SameLine(); + + if(ImBrio.FontIconButtonRight("resetTransform", FontAwesomeIcon.Recycle, 1, tooltip: "Reset Model Transform")) + { + posingCapability.ModelPosing.ResetTransform(); + } + } + + using(var popup = ImRaii.Popup("transform_CopyPaste_popup")) + { + if(popup.Success) + DrawCopyPastePopup(); + } + } } } } private void DrawBoneTransformEditor(PosingCapability posingCapability, BonePoseInfoId boneId, bool compactMode = false) { + bool didChange = false; + bool anyActive = false; + var bone = posingCapability.SkeletonPosing.GetBone(boneId); var bonePose = bone is not null ? posingCapability.SkeletonPosing.GetBonePose(boneId) : null; @@ -58,28 +131,6 @@ private void DrawBoneTransformEditor(PosingCapability posingCapability, BonePose var realEuler = _trackingEuler ?? realTransform.Rotation.ToEuler(); - bool didChange = false; - bool anyActive = false; - - (var pdidChange, var panyActive) = ImBrio.DragFloat3($"###_transformPosition_0", ref realTransform.Position, 0.1f, FontAwesomeIcon.ArrowsUpDownLeftRight, "Position"); - (var rdidChange, var ranyActive) = ImBrio.DragFloat3($"###_transformRotation_0", ref realEuler, 1f, FontAwesomeIcon.ArrowsSpin, "Rotation"); - (var sdidChange, var sanyActive) = ImBrio.DragFloat3($"###_transformScale_0", ref realTransform.Scale, 0.1f, FontAwesomeIcon.ExpandAlt, "Scale"); - - didChange |= pdidChange |= rdidChange |= sdidChange; - anyActive |= panyActive |= ranyActive |= sanyActive; - - ImGui.Spacing(); - - if(ImBrio.FontIconButton("propagate", FontAwesomeIcon.Compress, "Propagate", bone?.EligibleForIK == true)) - ImGui.OpenPopup("transform_propagate_popup"); - - if(compactMode) - { - ImGui.SameLine(); - - PosingEditorCommon.DrawIKSelect(posingCapability); - } - using(var popup = ImRaii.Popup("transform_propagate_popup")) { if(popup.Success && bonePose is not null) @@ -88,6 +139,13 @@ private void DrawBoneTransformEditor(PosingCapability posingCapability, BonePose } } + (var pdidChange, var panyActive) = ImBrio.DragFloat3($"###_transformPosition_0", ref realTransform.Position, 0.1f, FontAwesomeIcon.ArrowsUpDownLeftRight, "Position", enableExpanded: compactMode); + (var rdidChange, var ranyActive) = ImBrio.DragFloat3($"###_transformRotation_0", ref realEuler, 1f, FontAwesomeIcon.ArrowsSpin, "Rotation", enableExpanded: compactMode); + (var sdidChange, var sanyActive) = ImBrio.DragFloat3($"###_transformScale_0", ref realTransform.Scale, 0.1f, FontAwesomeIcon.ExpandAlt, "Scale", enableExpanded: compactMode); + + didChange |= pdidChange |= rdidChange |= sdidChange; + anyActive |= panyActive |= ranyActive |= sanyActive; + realTransform.Rotation = realEuler.ToQuaternion(); var toApply = before + realTransform.CalculateDiff(beforeMods); @@ -114,7 +172,7 @@ private void DrawBoneTransformEditor(PosingCapability posingCapability, BonePose } } - private void DrawModelTransformEditor(PosingCapability posingCapability) + private void DrawModelTransformEditor(PosingCapability posingCapability, bool compactMode = false) { var before = posingCapability.ModelPosing.Transform; var isProp = posingCapability.Actor.IsProp; @@ -124,8 +182,8 @@ private void DrawModelTransformEditor(PosingCapability posingCapability) bool didChange = false; bool anyActive = false; - (var pdidChange, var panyActive) = ImBrio.DragFloat3($"###_transformPosition_0", ref realTransform.Position, 0.1f, FontAwesomeIcon.ArrowsUpDownLeftRight, "Position"); - (var rdidChange, var ranyActive) = ImBrio.DragFloat3($"###_transformRotation_0", ref realEuler, 5.0f, FontAwesomeIcon.ArrowsSpin, "Rotation"); + (var pdidChange, var panyActive) = ImBrio.DragFloat3($"###_transformPosition_1", ref realTransform.Position, 0.1f, FontAwesomeIcon.ArrowsUpDownLeftRight, "Position", enableExpanded: compactMode); + (var rdidChange, var ranyActive) = ImBrio.DragFloat3($"###_transformRotation_1", ref realEuler, 5.0f, FontAwesomeIcon.ArrowsSpin, "Rotation", enableExpanded: compactMode); bool sdidChange = false; bool sanyActive = false; @@ -143,11 +201,10 @@ private void DrawModelTransformEditor(PosingCapability posingCapability) float entryWidth = (size.X - (ImGui.GetStyle().ItemSpacing.X * 2)); ImGui.SetNextItemWidth(entryWidth); - sdidChange |= ImGui.DragFloat($"##transformScale", ref realTransform.Scale.X, 0.1f / 10); - sanyActive |= ImGui.IsItemActive(); + (sanyActive, sdidChange) = ImBrio.DragFloat($"##transformScale", ref realTransform.Scale.X, 0.1f / 10); } else - (sdidChange, sanyActive) = ImBrio.DragFloat3($"###_transformScale_0", ref realTransform.Scale, 0.1f, FontAwesomeIcon.ExpandAlt, "Scale"); + (sdidChange, sanyActive) = ImBrio.DragFloat3($"###_transformScale_1", ref realTransform.Scale, 0.1f, FontAwesomeIcon.ExpandAlt, "Scale", enableExpanded: compactMode); didChange |= pdidChange |= rdidChange |= sdidChange; anyActive |= panyActive |= ranyActive |= sanyActive; @@ -176,6 +233,18 @@ private void DrawModelTransformEditor(PosingCapability posingCapability) } } + private static void DrawCopyPastePopup() + { + if(ImGui.Button("Copy")) + { + + } + if(ImGui.Button("Paste")) + { + + } + } + private static bool DrawPropagateCheckboxes(ref TransformComponents propagate) { var didChange = false; diff --git a/Brio/UI/Controls/RenameActorModal.cs b/Brio/UI/Controls/RenameActorModal.cs index 85b0f3ec..6d55a243 100644 --- a/Brio/UI/Controls/RenameActorModal.cs +++ b/Brio/UI/Controls/RenameActorModal.cs @@ -1,19 +1,20 @@ -using Brio.Entities.Actor; +using Brio.Entities.Core; using Dalamud.Interface.Utility.Raii; using ImGuiNET; using System.Numerics; namespace Brio.UI.Controls; -internal class RenameActorModal + +public class RenameActorModal { static Vector2 MinimumSize = new(400, 95); static bool IsOpen = false; - static ActorEntity? currentActorEntity; + static Entity? currentActorEntity; static string currentActorName = string.Empty; - public static bool Open(ActorEntity actor) + public static bool Open(Entity actor) { if(actor is not null) { diff --git a/Brio/UI/Controls/Selectors/ActionTimelineSelector.cs b/Brio/UI/Controls/Selectors/ActionTimelineSelector.cs index a4aed5fb..ae3cca30 100644 --- a/Brio/UI/Controls/Selectors/ActionTimelineSelector.cs +++ b/Brio/UI/Controls/Selectors/ActionTimelineSelector.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Controls.Selectors; -internal class ActionTimelineSelector(string id) : Selector(id) +public class ActionTimelineSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); @@ -172,7 +172,7 @@ protected override bool Filter(ActionTimelineSelectorEntry item, string search) } } -internal record class ActionTimelineSelectorEntry(string Name, ushort TimelineId, uint SecondaryId, string Key, ActionTimelineSelectorEntry.OriginalType TimelineType, ActionTimelineSelectorEntry.AnimationPurpose Purpose, ActionTimelineSlots Slot, uint Icon) +public record class ActionTimelineSelectorEntry(string Name, ushort TimelineId, uint SecondaryId, string Key, ActionTimelineSelectorEntry.OriginalType TimelineType, ActionTimelineSelectorEntry.AnimationPurpose Purpose, ActionTimelineSlots Slot, uint Icon) { public enum AnimationPurpose { diff --git a/Brio/UI/Controls/Selectors/CompanionSelector.cs b/Brio/UI/Controls/Selectors/CompanionSelector.cs index 541c6969..f0eca5bc 100644 --- a/Brio/UI/Controls/Selectors/CompanionSelector.cs +++ b/Brio/UI/Controls/Selectors/CompanionSelector.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Controls.Selectors; -internal class CompanionSelector(string id) : Selector(id) +public class CompanionSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/DyeSelector.cs b/Brio/UI/Controls/Selectors/DyeSelector.cs index b54ff0be..856b2e33 100644 --- a/Brio/UI/Controls/Selectors/DyeSelector.cs +++ b/Brio/UI/Controls/Selectors/DyeSelector.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Controls.Selectors; -internal class DyeSelector(string id) : Selector(id) +public class DyeSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/FacewearSelector.cs b/Brio/UI/Controls/Selectors/FacewearSelector.cs index 219d0448..02e05176 100644 --- a/Brio/UI/Controls/Selectors/FacewearSelector.cs +++ b/Brio/UI/Controls/Selectors/FacewearSelector.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Controls.Selectors; -internal class FacewearSelector(string id) : Selector(id) +public class FacewearSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/FestivalSelector.cs b/Brio/UI/Controls/Selectors/FestivalSelector.cs index d39d5b85..a67aecdc 100644 --- a/Brio/UI/Controls/Selectors/FestivalSelector.cs +++ b/Brio/UI/Controls/Selectors/FestivalSelector.cs @@ -6,7 +6,7 @@ namespace Brio.UI.Controls.Selectors; -internal class FestivalSelector(string id, IEnumerable entries) : Selector(id) +public class FestivalSelector(string id, IEnumerable entries) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/GearSelector.cs b/Brio/UI/Controls/Selectors/GearSelector.cs index 0984eb6e..b636bda6 100644 --- a/Brio/UI/Controls/Selectors/GearSelector.cs +++ b/Brio/UI/Controls/Selectors/GearSelector.cs @@ -9,7 +9,7 @@ namespace Brio.UI.Controls.Selectors; -internal class GearSelector(string id) : Selector(id) +public class GearSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/NpcSelector.cs b/Brio/UI/Controls/Selectors/NpcSelector.cs index fd5305eb..45de5310 100644 --- a/Brio/UI/Controls/Selectors/NpcSelector.cs +++ b/Brio/UI/Controls/Selectors/NpcSelector.cs @@ -10,7 +10,7 @@ namespace Brio.UI.Controls.Selectors; -internal class NpcSelector(string id) : Selector(id) +public class NpcSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Selectors/Selector.cs b/Brio/UI/Controls/Selectors/Selector.cs index 96da2858..56b95809 100644 --- a/Brio/UI/Controls/Selectors/Selector.cs +++ b/Brio/UI/Controls/Selectors/Selector.cs @@ -9,7 +9,7 @@ namespace Brio.UI.Controls.Selectors; -internal abstract class Selector where T : class +public abstract class Selector where T : class { public T? Selected => _selected; public T? SoftSelected => _softSelected; @@ -266,7 +266,7 @@ protected virtual bool IsItemSelected(T item) } [Flags] -internal enum SelectorFlags +public enum SelectorFlags { None = 0, AllowSearch = 1 << 0, diff --git a/Brio/UI/Controls/Selectors/StatusEffectSelector.cs b/Brio/UI/Controls/Selectors/StatusEffectSelector.cs index 1886d7c2..ab5cad15 100644 --- a/Brio/UI/Controls/Selectors/StatusEffectSelector.cs +++ b/Brio/UI/Controls/Selectors/StatusEffectSelector.cs @@ -13,7 +13,7 @@ public class StatusEffectSelectorHolder public bool _VFXLockEnabled { get; set; } } -internal class StatusEffectSelector(string id) : Selector(id) +public class StatusEffectSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); public bool _VFXLockEnabled = true; diff --git a/Brio/UI/Controls/Selectors/WeatherSelector.cs b/Brio/UI/Controls/Selectors/WeatherSelector.cs index e6551905..359fa7c1 100644 --- a/Brio/UI/Controls/Selectors/WeatherSelector.cs +++ b/Brio/UI/Controls/Selectors/WeatherSelector.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Controls.Selectors; -internal class WeatherSelector(string id) : Selector(id) +public class WeatherSelector(string id) : Selector(id) { protected override Vector2 MinimumListSize { get; } = new(300, 300); diff --git a/Brio/UI/Controls/Stateless/FileUIHelpers.cs b/Brio/UI/Controls/Stateless/FileUIHelpers.cs index e50b4e76..62f7edc5 100644 --- a/Brio/UI/Controls/Stateless/FileUIHelpers.cs +++ b/Brio/UI/Controls/Stateless/FileUIHelpers.cs @@ -1,64 +1,77 @@ using Brio.Capabilities.Actor; using Brio.Capabilities.Posing; using Brio.Config; +using Brio.Core; using Brio.Entities; using Brio.Files; using Brio.Game.Actor.Appearance; +using Brio.Game.Core; using Brio.Game.Posing; using Brio.Game.Scene; using Brio.Game.Types; using Brio.Library; using Brio.Library.Filters; -using Brio.Resources; using Brio.UI.Controls.Core; using Brio.UI.Controls.Editors; +using Brio.UI.Windows; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; +using MessagePack; +using OneOf; using System; using System.Collections.Generic; using System.IO; namespace Brio.UI.Controls.Stateless; -internal class FileUIHelpers +public class FileUIHelpers { - public static void DrawProjectPopup(SceneService sceneService, EntityManager entityManager) + public static void DrawProjectPopup(SceneService sceneService, EntityManager entityManager, ProjectWindow projectWindow, AutoSaveService autoSaveService) { using var popup = ImRaii.Popup("DrawProjectPopup"); if(popup.Success) { using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.Transparent)) { - if(ImGui.Button("Save Project")) + if(ImGui.Button("Save/Load Project")) { - - } - if(ImGui.Button("Load Project")) - { - + projectWindow.IsOpen = true; } + if(ImGui.IsItemHovered()) + ImGui.SetTooltip("Save or Load this Scene"); if(ImGui.Button("View Auto-Saves")) { - + autoSaveService.ShowAutoSaves(); } + if(ImGui.IsItemHovered()) + ImGui.SetTooltip("View Scene Auto-Saves"); ImGui.Separator(); - if(ImGui.Button("Export Scene")) - { - ShowExportSceneModal(entityManager); - } - if(ImGui.Button("Import Scene")) + using(ImRaii.Disabled(true)) { - ShowImportSceneModal(sceneService); + if(ImGui.Button("Export Scene")) + { + ShowExportSceneModal(entityManager, sceneService); + } + if(ImGui.Button("Import Scene")) + { + ShowImportSceneModal(sceneService); + } } } } } static bool freezeOnLoad = false; + static bool smartDefaults = false; + + static bool doExpression = false; + static bool doBody = false; + static bool doTransform = false; + static TransformComponents? transformComponents = null; public static void DrawImportPoseMenuPopup(PosingCapability capability, bool showImportOptions = true) { using var popup = ImRaii.Popup("DrawImportPoseMenuPopup"); @@ -68,36 +81,100 @@ public static void DrawImportPoseMenuPopup(PosingCapability capability, bool sho using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.Transparent)) { - var size = ImGui.CalcTextSize("XXXX Freeze Actor on Import"); + var size = ImGui.GetContentRegionAvail(); //ImGui.CalcTextSize("XXXX Freeze Actor on Import"); size.Y = 44; + var buttonSize = size / 8; + + var with = buttonSize * 4; + ImGui.Checkbox("Freeze Actor on Import", ref freezeOnLoad); ImGui.Separator(); - if(ImGui.Button("Import as Body", size)) + using(ImRaii.Disabled(true)) + ImGui.Checkbox("Smart Import", ref smartDefaults); + + transformComponents ??= capability.PosingService.DefaultImporterOptions.TransformComponents; + + using(ImRaii.Disabled(smartDefaults)) + { + using(ImRaii.Disabled(doExpression)) + { + if(ImBrio.ToggelFontIconButton("ImportPosition", FontAwesomeIcon.ArrowsUpDownLeftRight, buttonSize, transformComponents.Value.HasFlag(TransformComponents.Position), hoverText: "Import Position")) + { + if(transformComponents.Value.HasFlag(TransformComponents.Position)) + transformComponents &= ~TransformComponents.Position; + else + transformComponents |= TransformComponents.Position; + } + ImGui.SameLine(); + if(ImBrio.ToggelFontIconButton("ImportRotation", FontAwesomeIcon.ArrowsSpin, buttonSize, transformComponents.Value.HasFlag(TransformComponents.Rotation), hoverText: "Import Rotation")) + { + if(transformComponents.Value.HasFlag(TransformComponents.Rotation)) + transformComponents &= ~TransformComponents.Rotation; + else + transformComponents |= TransformComponents.Rotation; + } + ImGui.SameLine(); + if(ImBrio.ToggelFontIconButton("ImportScale", FontAwesomeIcon.ExpandAlt, buttonSize, transformComponents.Value.HasFlag(TransformComponents.Scale), hoverText: "Import Scale")) + { + if(transformComponents.Value.HasFlag(TransformComponents.Scale)) + transformComponents &= ~TransformComponents.Scale; + else + transformComponents |= TransformComponents.Scale; + } + } + + ImGui.SameLine(); + if(ImBrio.ToggelFontIconButton("ImportTransform", FontAwesomeIcon.ArrowsToCircle, buttonSize, doTransform, hoverText: "Import Model Transform")) + { + doTransform = !doTransform; + } + + if(smartDefaults == true) + { + transformComponents = null; + } + } + + ImGui.Separator(); + + if(ImBrio.ToggelButton("Import Body", new(size.X, 35), doBody)) + { + doBody = !doBody; + } + + if(ImBrio.ToggelButton("Import Expression", new(size.X, 35), doExpression)) { - ShowImportPoseModal(capability, asBody: true, freezeOnLoad: freezeOnLoad); + doExpression = !doExpression; } - if(ImGui.Button("Import as Expression", size)) + using(ImRaii.Disabled(doExpression || doBody)) { - ShowImportPoseModal(capability, asExpression: true, freezeOnLoad: freezeOnLoad); + if(ImBrio.Button("Import Options", FontAwesomeIcon.Cog, new(size.X, 25), centerTest: true, hoverText: "Import Options")) + ImGui.OpenPopup("import_optionsImportPoseMenuPopup"); } ImGui.Separator(); - if(ImBrio.FontIconButton(FontAwesomeIcon.Cog)) - ImGui.OpenPopup("import_optionsImportPoseMenuPopup"); + if(ImGui.Button("Import", new(size.X, 25))) + { + ShowImportPoseModal(capability, freezeOnLoad: freezeOnLoad, transformComponents: transformComponents, applyModelTransformOverride: doTransform); + } - if(ImGui.IsItemHovered()) - ImGui.SetTooltip("Import Options"); + ImGui.Separator(); - ImGui.SameLine(); + if(ImGui.Button("Import A-Pose", new(size.X, 25))) + { + capability.LoadResourcesPose("Data.BrioAPose.pose", freezeOnLoad: freezeOnLoad); + ImGui.CloseCurrentPopup(); + } - if(ImGui.Button("Import with Options", new(size.X - 32, 25))) + if(ImGui.Button("Import T-Pose", new(size.X, 25))) { - ShowImportPoseModal(capability, freezeOnLoad: freezeOnLoad); + capability.LoadResourcesPose("Data.BrioTPose.pose", freezeOnLoad: freezeOnLoad); + ImGui.CloseCurrentPopup(); } } @@ -105,13 +182,14 @@ public static void DrawImportPoseMenuPopup(PosingCapability capability, bool sho { if(popup2.Success && showImportOptions && Brio.TryGetService(out var service)) { - PosingEditorCommon.DrawImportOptionEditor(service.DefaultImporterOptions); + PosingEditorCommon.DrawImportOptionEditor(service.DefaultImporterOptions, true); } } } } - public static void ShowImportPoseModal(PosingCapability capability, PoseImporterOptions? options = null, bool asExpression = false, bool asBody = false, bool freezeOnLoad = false) + public static void ShowImportPoseModal(PosingCapability capability, PoseImporterOptions? options = null, bool asExpression = false, + bool asBody = false, bool freezeOnLoad = false, TransformComponents? transformComponents = null, bool? applyModelTransformOverride = false) { TypeFilter filter = new("Poses", typeof(CMToolPoseFile), typeof(PoseFile)); @@ -122,11 +200,11 @@ public static void ShowImportPoseModal(PosingCapability capability, PoseImporter { if(r is CMToolPoseFile cmPose) { - capability.ImportPose(cmPose, options: options, asExpression: asExpression, asBody: asBody, freezeOnLoad: freezeOnLoad); + ImportPose(capability, cmPose, options: options, transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); } else if(r is PoseFile pose) { - capability.ImportPose(pose, options: options, asExpression: asExpression, asBody: asBody, freezeOnLoad: freezeOnLoad); + ImportPose(capability, pose, options: options, transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); } }); } @@ -136,16 +214,43 @@ public static void ShowImportPoseModal(PosingCapability capability, PoseImporter { if(r is CMToolPoseFile cmPose) { - capability.ImportPose(cmPose, options: options, asExpression: asExpression, asBody: asBody, freezeOnLoad: freezeOnLoad); + ImportPose(capability, cmPose, options: options, transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); } else if(r is PoseFile pose) { - capability.ImportPose(pose, options: options, asExpression: asExpression, asBody: asBody, freezeOnLoad: freezeOnLoad); + ImportPose(capability, pose, options: options, transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); } }); } } + private static void ImportPose(PosingCapability capability, OneOf rawPoseFile, PoseImporterOptions? options = null, + TransformComponents? transformComponents = null, bool? applyModelTransformOverride = false) + { + if(doBody && doExpression) + { + capability.ImportPose(rawPoseFile, options: capability.PosingService.DefaultIPCImporterOptions, asExpression: false, asBody: false, freezeOnLoad: freezeOnLoad, + transformComponents: null, applyModelTransformOverride: applyModelTransformOverride); + return; + } + + if(doBody) + { + capability.ImportPose(rawPoseFile, options: null, asExpression: false, asBody: true, freezeOnLoad: freezeOnLoad, + transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); + } + else if(doExpression) + { + capability.ImportPose(rawPoseFile, options: null, asExpression: true, asBody: false, freezeOnLoad: freezeOnLoad, + transformComponents: null, applyModelTransformOverride: null); + } + else + { + capability.ImportPose(rawPoseFile, options: options, asExpression: false, asBody: false, freezeOnLoad: freezeOnLoad, + transformComponents: transformComponents, applyModelTransformOverride: applyModelTransformOverride); + } + } + public static void ShowExportPoseModal(PosingCapability capability) { UIManager.Instance.FileDialogManager.SaveFileDialog("Export Pose###export_pose", "Pose File (*.pose){.pose}", "brio", ".pose", @@ -258,7 +363,7 @@ public static void ShowImportMCDFModal(ActorAppearanceCapability capability) }, 1, ConfigurationService.Instance.Configuration.LastMCDFPath, true); } - public static void ShowExportSceneModal(EntityManager entityManager) + public static void ShowExportSceneModal(EntityManager entityManager, SceneService sceneService) { UIManager.Instance.FileDialogManager.SaveFileDialog("Export Scene File###export_scene_window", "Brio Scene File (*.brioscn){.brioscn}", "brioscn", "{.brioscn}", (success, path) => @@ -276,8 +381,17 @@ public static void ShowExportSceneModal(EntityManager entityManager) ConfigurationService.Instance.Save(); } - SceneFile sceneFile = SceneService.GenerateSceneFile(entityManager); - ResourceProvider.Instance.SaveFileDocument(path, sceneFile); + SceneFile sceneFile = sceneService.GenerateSceneFile(); + //ResourceProvider.Instance.SaveFileDocument(path, sceneFile); + + byte[] bytes = MessagePackSerializer.Serialize(sceneFile); + File.WriteAllBytes(path, bytes); + + //TODO REMOVE + path += ".json"; + var json = MessagePackSerializer.ConvertToJson(bytes); + File.WriteAllText(path, json); + Brio.Log.Info("Finished exporting scene"); } }, ConfigurationService.Instance.Configuration.LastScenePath, true); @@ -300,7 +414,7 @@ public static void ShowImportSceneModal(SceneService sceneService) { throw new IOException("The file selected is not a valid scene file"); } - }); + }, true); } } diff --git a/Brio/UI/Controls/Stateless/ImBrio.ApplyToActor.cs b/Brio/UI/Controls/Stateless/ImBrio.ApplyToActor.cs index 57814a87..bc4b59fa 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.ApplyToActor.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.ApplyToActor.cs @@ -5,7 +5,7 @@ namespace Brio.UI.Controls.Stateless; -internal partial class ImBrio +public partial class ImBrio { public static void DrawApplyToActor(EntityManager entityManager, Action callback) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Color.cs b/Brio/UI/Controls/Stateless/ImBrio.Color.cs index d2266aec..dbfa9903 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Color.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Color.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool DrawLabeledColor(string id, uint color, string colorText, string description, Vector2? size = null) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Companions.cs b/Brio/UI/Controls/Stateless/ImBrio.Companions.cs index a2f1af21..4b8dca24 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Companions.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Companions.cs @@ -3,7 +3,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool BorderedGameIcon(string id, CompanionRowUnion union, bool showText = true, ImGuiButtonFlags flags = ImGuiButtonFlags.MouseButtonLeft, Vector2? size = null) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Drag.cs b/Brio/UI/Controls/Stateless/ImBrio.Drag.cs index 0492d2fe..b60b2603 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Drag.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Drag.cs @@ -1,21 +1,49 @@ using Brio.Input; +using Brio.UI.Controls.Core; using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; using ImGuiNET; +using System.Collections.Generic; using System.Numerics; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { - public static (bool anyActive, bool didChange) DragFloat3(string label, ref Vector3 vectorValue, float step = 1.0f, FontAwesomeIcon icon = FontAwesomeIcon.None, string tooltip = "") + private static readonly HashSet expanded = []; + + public static (bool anyActive, bool didChange) DragFloat3(string label, ref Vector3 vectorValue, float step = 1.0f, + FontAwesomeIcon icon = FontAwesomeIcon.None, string tooltip = "", bool enableExpanded = false) { + bool isExpanded = expanded.Contains(label); + if(icon == FontAwesomeIcon.None) { ImGui.Text(label); } else { - Icon(icon); + if(enableExpanded) + { + using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.Transparent)) + { + if(Button($"{label}##Button", icon, new Vector2(25))) + { + if(isExpanded) + { + expanded.Remove(label); + } + else + { + expanded.Add(label); + } + } + } + } + else + { + Icon(icon); + } } ImGui.SameLine(); @@ -27,6 +55,41 @@ public static (bool anyActive, bool didChange) DragFloat3(string label, ref Vect (bool changed, bool active) = DragFloat3Horizontal($"###{label}_drag3", ref vectorValue, step, size); + if(isExpanded && enableExpanded) + { + float height = (GetLineHeight()) * 3 + (ImGui.GetStyle().ItemSpacing.Y * 2) + (ImGui.GetStyle().WindowPadding.Y * 2); + + ImGui.PushStyleColor(ImGuiCol.FrameBg, UIConstants.GizmoBlue); + + float x = vectorValue.X; + (var pdidChange, var panyActive) = DragFloat($"###{label}_x", ref x, step, $"{tooltip} X"); + vectorValue.X = x; + + ImGui.PopStyleColor(); + ImGui.PushStyleColor(ImGuiCol.FrameBg, UIConstants.GizmoGreen); + + float y = vectorValue.Y; + (var rdidChange, var ranyActive) = DragFloat($"###{label}_y", ref y, step, $"{tooltip} Y"); + vectorValue.Y = y; + + ImGui.PopStyleColor(); + ImGui.PushStyleColor(ImGuiCol.FrameBg, UIConstants.GizmoRed); + + float z = vectorValue.Z; + (var sdidChange, var sanyActive) = DragFloat($"###{label}_z", ref z, step, $"{tooltip} Z"); + vectorValue.Z = z; + + changed |= pdidChange |= rdidChange |= sdidChange; + active |= panyActive |= ranyActive |= sanyActive; + + ImGui.PopStyleColor(); + + //if(ImGui.BeginChild($"###{label}_child", new Vector2(GetRemainingWidth(), height), false)) + //{ + // ImGui.EndChild(); + //} + } + return (active, changed); } diff --git a/Brio/UI/Controls/Stateless/ImBrio.Gizmo.cs b/Brio/UI/Controls/Stateless/ImBrio.Gizmo.cs index 8551a5a3..f63dc3ee 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Gizmo.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Gizmo.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrioGizmo +public static partial class ImBrioGizmo { const int numPoints = 144; const int axisHoverMouseDist = 10; diff --git a/Brio/UI/Controls/Stateless/ImBrio.IconSelect.cs b/Brio/UI/Controls/Stateless/ImBrio.IconSelect.cs index 76cc39e5..f8e25ca5 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.IconSelect.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.IconSelect.cs @@ -5,7 +5,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool DrawIconSelector(string id, IconSelectorEntry[] entries, ref int selectedId, int columns = 4, Vector2? iconSize = null, string fallbackImage = "Images.UnknownIcon.png", bool bitField = false) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Image.cs b/Brio/UI/Controls/Stateless/ImBrio.Image.cs index 7d6a6653..d142fd4e 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Image.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Image.cs @@ -5,7 +5,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static void ImageFit(IDalamudTextureWrap texture) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs b/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs index 45e2848a..c73de351 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs @@ -1,7 +1,7 @@ using ImGuiNET; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static float GetRemainingWidth() { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Slider.cs b/Brio/UI/Controls/Stateless/ImBrio.Slider.cs index 77b14aa5..1282fb6a 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Slider.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Slider.cs @@ -4,7 +4,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool SliderFloat3(string label, ref Vector3 value, float min, float max, string format = "%.2f", ImGuiSliderFlags flags = ImGuiSliderFlags.None, float step = 1.0f) { @@ -25,17 +25,17 @@ public static bool SliderFloat3(string label, ref Vector3 value, float min, floa return changed; } - public static bool SliderFloat(string label, ref float value, float min, float max, string format = "%.2f", ImGuiSliderFlags flags = ImGuiSliderFlags.None, float step = 1.0f) + public static bool SliderFloat(string label, ref float value, float min, float max, string format = "%.2f", ImGuiSliderFlags flags = ImGuiSliderFlags.None, float step = 1.0f, string toolTip = "") { - return SliderBase(label, ref value, min, max, format, flags, step, false); + return SliderBase(label, ref value, min, max, format, flags, step, false, toolTip); } - public static bool SliderAngle(string label, ref float value, float min, float max, string format = "%.2f", ImGuiSliderFlags flags = ImGuiSliderFlags.None, float step = 1.0f) + public static bool SliderAngle(string label, ref float value, float min, float max, string format = "%.2f", ImGuiSliderFlags flags = ImGuiSliderFlags.None, float step = 1.0f, string toolTip = "") { - return SliderBase(label, ref value, min, max, format, flags, step, true); + return SliderBase(label, ref value, min, max, format, flags, step, true, toolTip); } - private static bool SliderBase(string label, ref float value, float min, float max, string format, ImGuiSliderFlags flags, float step, bool isAngle = false) + private static bool SliderBase(string label, ref float value, float min, float max, string format, ImGuiSliderFlags flags, float step, bool isAngle = false, string toolTip = "") { bool changed = false; float buttonWidth = ImGui.GetCursorPosX(); @@ -65,11 +65,11 @@ private static bool SliderBase(string label, ref float value, float min, float m if(hasLabel) { - ImGui.SetNextItemWidth((ImGui.GetWindowWidth() * 0.65f) - (buttonWidth * 2) - ImGui.GetStyle().CellPadding.X); + ImGui.SetNextItemWidth((GetRemainingWidth() * 0.75f) - (buttonWidth * 2) - ImGui.GetStyle().CellPadding.X); } else { - ImGui.SetNextItemWidth(ImGui.GetWindowWidth() - ((buttonWidth * 2) + ImGui.GetStyle().CellPadding.X) - (ImGui.GetStyle().WindowPadding.X * 2)); + ImGui.SetNextItemWidth(GetRemainingWidth() - ((buttonWidth * 2) + ImGui.GetStyle().CellPadding.X) - (ImGui.GetStyle().WindowPadding.X * 2)); } if(isAngle) @@ -79,6 +79,9 @@ private static bool SliderBase(string label, ref float value, float min, float m if(ImGui.IsItemHovered()) { + if(string.IsNullOrEmpty(toolTip) == false) + ImGui.SetTooltip(toolTip); + float mouseWheel = ImGui.GetIO().MouseWheel / 10; if(mouseWheel != 0) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Spinner.cs b/Brio/UI/Controls/Stateless/ImBrio.Spinner.cs index 3233d36e..0e22495e 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Spinner.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Spinner.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static void Spinner(ref float angle, float speed = 3.5f) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Tags.cs b/Brio/UI/Controls/Stateless/ImBrio.Tags.cs index 146c6b83..6f60d493 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Tags.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Tags.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool DrawTag(Tag tag) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Text.cs b/Brio/UI/Controls/Stateless/ImBrio.Text.cs index b7ee835e..d962d7a2 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Text.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Text.cs @@ -3,7 +3,7 @@ using ImGuiNET; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static void TextCentered(string text, float width) { @@ -31,7 +31,7 @@ public static void Icon(FontAwesomeIcon icon) ImGui.PushStyleColor(ImGuiCol.ButtonActive, 0); using(ImRaii.PushFont(UiBuilder.IconFont)) { - ImGui.Button(icon.ToIconString(), new(22, 0)); + ImGui.Button(icon.ToIconString(), new(25, 0)); } ImGui.PopStyleColor(); ImGui.PopStyleColor(); diff --git a/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs b/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs index 6e0d3acb..295b09f7 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool ToggleButton(string label, ref bool selected, bool canDeselect = true) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.Weather.cs b/Brio/UI/Controls/Stateless/ImBrio.Weather.cs index 86bee093..4d7cffb5 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Weather.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Weather.cs @@ -3,7 +3,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static bool BorderedGameIcon(string id, WeatherUnion union, bool showText = true, ImGuiButtonFlags flags = ImGuiButtonFlags.MouseButtonLeft, Vector2? size = null) { diff --git a/Brio/UI/Controls/Stateless/ImBrio.cs b/Brio/UI/Controls/Stateless/ImBrio.cs index 6e2e0e35..32225dce 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.cs @@ -1,5 +1,6 @@ using Brio.Resources; using Brio.UI.Controls.Core; +using Brio.UI.Theming; using Dalamud.Interface; using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Utility.Raii; @@ -7,7 +8,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; -internal static partial class ImBrio +public static partial class ImBrio { public static void FontIcon(FontAwesomeIcon icon) { @@ -49,7 +50,7 @@ public static bool FontIconButton(string id, FontAwesomeIcon icon, string? toolt using(ImRaii.PushFont(UiBuilder.IconFont)) { - if(ImGui.Button($"{icon.ToIconString()}###{id}")) + if(ImGui.Button($"{icon.ToIconString()}###{id}", new Vector2(25))) wasClicked = true; } @@ -86,7 +87,7 @@ public static bool FontIconButtonRight(string id, FontAwesomeIcon icon, float po using(ImRaii.PushFont(UiBuilder.IconFont)) { - if(ImGui.Button($"{icon.ToIconString()}###{id}")) + if(ImGui.Button($"{icon.ToIconString()}###{id}", new Vector2(25))) wasClicked = true; } @@ -110,7 +111,7 @@ public static bool Button(string label, FontAwesomeIcon icon) return Button(label, icon, Vector2.Zero); } - public static bool Button(string label, FontAwesomeIcon icon, Vector2 size, string hoverText = "") + public static bool Button(string label, FontAwesomeIcon icon, Vector2 size, string hoverText = "", bool centerTest = false) { bool clicked; @@ -131,7 +132,7 @@ public static bool Button(string label, FontAwesomeIcon icon, Vector2 size, stri float iconR = iconWidth + ImGui.GetStyle().ItemInnerSpacing.X; float textOffset = iconR / innerWidth; - using(ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(textOffset, 0.5f))) + using(ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(textOffset, 0.5f), centerTest == false)) { Vector2 startPos = ImGui.GetCursorPos(); clicked = ImGui.Button(label, size); @@ -159,13 +160,17 @@ public static bool Button(string label, FontAwesomeIcon icon, Vector2 size, stri return clicked; } - public static bool ToggelButton(string lable, bool isToggled, uint toggledColor = UIConstants.GizmoRed, string hoverText = "") + public static bool ToggelButton(string lable, bool isToggled, uint toggledColor = 0, string hoverText = "") { + if(toggledColor == 0) toggledColor = TheameManager.CurrentTheame.Accent.AccentColor; + return ToggelButton(lable, Vector2.Zero, isToggled, toggledColor, hoverText); } - public static bool ToggelButton(string lable, Vector2 size, bool isToggled, uint toggledColor = UIConstants.GizmoRed, string hoverText = "") + public static bool ToggelButton(string lable, Vector2 size, bool isToggled, uint toggledColor = 0, string hoverText = "") { + if(toggledColor == 0) toggledColor = TheameManager.CurrentTheame.Accent.AccentColor; + if(isToggled) ImGui.PushStyleColor(ImGuiCol.Button, toggledColor); @@ -183,16 +188,23 @@ public static bool ToggelButton(string lable, Vector2 size, bool isToggled, uint return clicked; } - public static bool ToggelFontIconButton(string id, FontAwesomeIcon icon, Vector2 size, bool isToggled, uint toggledColor = UIConstants.GizmoRed, string hoverText = "") + public static bool ToggelFontIconButton(string id, FontAwesomeIcon icon, Vector2 size, bool isToggled, uint toggledColor = 0, string hoverText = "") { var clicked = false; + if(toggledColor == 0) toggledColor = TheameManager.CurrentTheame.Accent.AccentColor; + if(isToggled) ImGui.PushStyleColor(ImGuiCol.Button, toggledColor); + if(size.X >= 0 || size.Y >= 0) + { + size += new Vector2(25); + } + using(ImRaii.PushFont(UiBuilder.IconFont)) { - if(ImGui.Button($"{icon.ToIconString()}###{id}")) + if(ImGui.Button($"{icon.ToIconString()}###{id}", size)) clicked = true; } diff --git a/Brio/UI/Entitites/EntityHelpers.cs b/Brio/UI/Entitites/EntityHelpers.cs index be9d701e..1ed96e15 100644 --- a/Brio/UI/Entitites/EntityHelpers.cs +++ b/Brio/UI/Entitites/EntityHelpers.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Entitites; -internal static class EntityHelpers +public static class EntityHelpers { public static void DrawEntitySection(Entity? entity) { diff --git a/Brio/UI/Entitites/EntityHierarchyView.cs b/Brio/UI/Entitites/EntityHierarchyView.cs index 6628dbb8..f079c0f0 100644 --- a/Brio/UI/Entitites/EntityHierarchyView.cs +++ b/Brio/UI/Entitites/EntityHierarchyView.cs @@ -1,9 +1,6 @@ -using Brio.Capabilities.Actor; -using Brio.Entities; -using Brio.Entities.Actor; +using Brio.Entities; using Brio.Entities.Core; -using Brio.UI.Controls.Core; -using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Brio.UI.Widgets.Core; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; @@ -12,7 +9,7 @@ namespace Brio.UI.Entitites; -internal class EntityHierarchyView(EntityManager entityManager) +public class EntityHierarchyView(EntityManager entityManager) { private readonly float buttonWidth = ImGui.GetTextLineHeight() * 13f; private readonly float offsetWidth = 16f; @@ -56,8 +53,12 @@ private void DrawEntity(Entity entity, EntityId? selectedEntityId, float lastOff using(ImRaii.PushColor(ImGuiCol.Button, 0)) { var invsButtonPos = ImGui.GetCursorPos(); - - if(ImGui.Button($"###{entity.Id}_invs_button", new(buttonWidth, 0))) + float width = buttonWidth; + if(entity.ContextButtonCount >= 2) + { + width -= 30 - entity.ContextButtonCount; + } + if(ImGui.Button($"###{entity.Id}_invs_button", new(width, 0))) { Select(entity); } @@ -77,7 +78,7 @@ private void DrawEntity(Entity entity, EntityId? selectedEntityId, float lastOff lastOffset += offsetWidth; } - using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.GizmoRed, isSelected)) + using(ImRaii.PushColor(ImGuiCol.Button, TheameManager.CurrentTheame.Accent.AccentColor, isSelected)) { using(ImRaii.Disabled(true)) { @@ -88,21 +89,11 @@ private void DrawEntity(Entity entity, EntityId? selectedEntityId, float lastOff DrawNode(entity); - if(entity is ActorEntity actor) + if(entity.Flags.HasFlag(EntityFlags.HasContextButton)) { ImGui.SameLine(); - var aac = actor.GetCapability(); - - using(ImRaii.PushColor(ImGuiCol.Button, UIConstants.GizmoRed, aac.IsHidden)) - { - string toolTip = aac.IsHidden ? $"Show {aac.Actor.FriendlyName}" : $"Hide {aac.Actor.FriendlyName}"; - if(ImBrio.FontIconButtonRight($"###{entity.Id}_hideActor", aac.IsHidden ? FontAwesomeIcon.EyeSlash : FontAwesomeIcon.Eye, 1f, toolTip, bordered: false)) - { - aac.ToggleHide(); - } - } - + entity.DrawContextButton(); } using(var popup = ImRaii.Popup($"context_popup{entity.Id}")) diff --git a/Brio/UI/Theming/TheameManager.cs b/Brio/UI/Theming/TheameManager.cs new file mode 100644 index 00000000..bfdf4fda --- /dev/null +++ b/Brio/UI/Theming/TheameManager.cs @@ -0,0 +1,73 @@ +using System.Numerics; + +namespace Brio.UI.Theming; + +public static class TheameManager +{ + + public static Theame CurrentTheame { get; set; } + + static TheameManager() + { + CurrentTheame = new Theame + { + Name = "Default", + Accent = new TheameAccent + { + AccentColor = SetColor(new Vector4(98, 75, 224, 255)), + AccentColorLight = SetColor(new Vector4(98, 75, 224, 255)), + AccentColorStrong = SetColor(new Vector4(98, 75, 224, 255)), + AccentColorDim = SetColor(new Vector4(98, 75, 224, 255)), + + AccentCheckMark = SetColor(new Vector4(98, 75, 224, 255)), + AccentButtonHovered = SetColor(new Vector4(74, 56, 170, 255)), + + AccentTabActive = SetColor(new Vector4(98, 75, 224, 255)), + AccentTabUnfocusedActive = SetColor(new Vector4(73, 48, 205, 255)), + }, + Core = new TheameCore + { + + } + }; + } + + static uint SetColor(Vector4 colorVector) + { + uint r = (uint)(colorVector.X) & 0xFF; + uint g = (uint)(colorVector.Y) & 0xFF; + uint b = (uint)(colorVector.Z) & 0xFF; + uint a = (uint)(colorVector.W) & 0xFF; + + return (a << 24) | (b << 16) | (g << 8) | r; + } +} + +public record class Theame +{ + public required string Name; + + public required TheameAccent Accent; + + public required TheameCore Core; +} + +public record class TheameAccent +{ + public uint AccentColor = 0; + public uint AccentColorLight; + public uint AccentColorStrong; + public uint AccentColorDim; + + + public uint AccentCheckMark; + public uint AccentButtonHovered; + + public uint AccentTabActive; + public uint AccentTabUnfocusedActive; +} + +public record class TheameCore +{ + public uint Text; +} diff --git a/Brio/UI/UIManager.cs b/Brio/UI/UIManager.cs index 61a28e8e..4fbb10a8 100644 --- a/Brio/UI/UIManager.cs +++ b/Brio/UI/UIManager.cs @@ -15,7 +15,7 @@ namespace Brio.UI; -internal class UIManager : IDisposable +public class UIManager : IDisposable { private readonly IDalamudPluginInterface _pluginInterface; private readonly GPoseService _gPoseService; @@ -24,6 +24,7 @@ internal class UIManager : IDisposable private readonly MainWindow _mainWindow; private readonly SettingsWindow _settingsWindow; private readonly InfoWindow _infoWindow; + private readonly ProjectWindow _projectWindow; private readonly UpdateWindow _updateWindow; private readonly LibraryWindow _libraryWindow; private readonly ActorAppearanceWindow _actorAppearanceWindow; @@ -59,6 +60,9 @@ internal class UIManager : IDisposable public static bool IsPosingGraphicalWindowOpen => Instance._graphicalWindow.IsOpen; + public bool IsActorAppearanceWindowOpen => _actorAppearanceWindow.IsOpen; + public bool IsActorPoseWindowOpen => _graphicalWindow.IsOpen; + public UIManager ( IDalamudPluginInterface pluginInterface, @@ -72,6 +76,7 @@ public UIManager InfoWindow infoWindow, UpdateWindow updateWindow, LibraryWindow libraryWindow, + ProjectWindow projectWindow, ActorAppearanceWindow appearanceWindow, ActionTimelineWindow actionTimelineWindow, PosingOverlayWindow overlayWindow, @@ -99,6 +104,7 @@ MareService mareService _libraryWindow = libraryWindow; _infoWindow = infoWindow; _updateWindow = updateWindow; + _projectWindow = projectWindow; _actorAppearanceWindow = appearanceWindow; _actionTimelineWindow = actionTimelineWindow; _overlayWindow = overlayWindow; @@ -119,6 +125,7 @@ MareService mareService _windowSystem.AddWindow(_mainWindow); _windowSystem.AddWindow(_settingsWindow); _windowSystem.AddWindow(_libraryWindow); + _windowSystem.AddWindow(_projectWindow); _windowSystem.AddWindow(_infoWindow); _windowSystem.AddWindow(_updateWindow); _windowSystem.AddWindow(_actorAppearanceWindow); @@ -136,7 +143,6 @@ MareService mareService _pluginInterface.UiBuilder.Draw += DrawUI; _pluginInterface.UiBuilder.OpenConfigUi += ShowSettingsWindow; _pluginInterface.UiBuilder.OpenMainUi += ShowMainWindow; - _pluginInterface.ActivePluginsChanged += ActivePluginsChanged; ApplySettings(); } @@ -156,6 +162,11 @@ public void ToggleGraphicalPosingWindow() _graphicalWindow.IsOpen = !_graphicalWindow.IsOpen; } + public void ToggleProjectWindow() + { + _projectWindow.IsOpen = !_projectWindow.IsOpen; + } + public void ShowSettingsWindow() { _settingsWindow.IsOpen = true; @@ -166,18 +177,6 @@ public void ShowMainWindow() _mainWindow.IsOpen = true; } - private void ActivePluginsChanged(PluginListInvalidationKind kind, bool affectedThisPlugin) - { - foreach(var plugin in _pluginInterface.InstalledPlugins) - { - Brio.Log.Debug($"InstalledPlugins: {plugin}"); - } - - _penumbraService.RefreshPenumbraStatus(); - _glamourerService.RefreshGlamourerStatus(); - _mareService.RefreshMareStatus(); - } - public void NotifyError(string message) { _toastGui.ShowError(message); diff --git a/Brio/UI/Widgets/Actor/ActionTimelineWidget.cs b/Brio/UI/Widgets/Actor/ActionTimelineWidget.cs index 0615c2b2..39260e4f 100644 --- a/Brio/UI/Widgets/Actor/ActionTimelineWidget.cs +++ b/Brio/UI/Widgets/Actor/ActionTimelineWidget.cs @@ -7,11 +7,11 @@ namespace Brio.UI.Widgets.Actor; -internal class ActionTimelineWidget(ActionTimelineCapability capability, EntityManager entityManager, PhysicsService physicsService, ConfigurationService configService) : Widget(capability) +public class ActionTimelineWidget(ActionTimelineCapability capability, EntityManager entityManager, PhysicsService physicsService, ConfigurationService configService) : Widget(capability) { public override string HeaderName => "Animation Control"; - public override WidgetFlags Flags => WidgetFlags.DrawBody | WidgetFlags.HasAdvanced; + public override WidgetFlags Flags => capability.Actor.IsProp ? WidgetFlags.None : WidgetFlags.DrawBody | WidgetFlags.HasAdvanced; private readonly ActionTimelineEditor _editor = new(null!, null!, entityManager, physicsService, configService); diff --git a/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs b/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs index d1c36aae..4edfc617 100644 --- a/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs +++ b/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs @@ -1,4 +1,5 @@ using Brio.Capabilities.Actor; +using Brio.Capabilities.Posing; using Brio.Game.Actor.Appearance; using Brio.Resources; using Brio.UI.Controls.Editors; @@ -13,11 +14,12 @@ namespace Brio.UI.Widgets.Actor; -internal class ActorAppearanceWidget(ActorAppearanceCapability capability) : Widget(capability) +public class ActorAppearanceWidget(ActorAppearanceCapability capability) : Widget(capability) { - public override string HeaderName => "Appearance"; + public override string HeaderName => capability.Actor.IsProp ? "Change Prop" : "Appearance"; - public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.DrawQuickIcons | WidgetFlags.DrawPopup | WidgetFlags.HasAdvanced | WidgetFlags.CanHide; + public override WidgetFlags Flags => capability.Actor.IsProp ? WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.DrawPopup | WidgetFlags.DrawQuickIcons + : WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.DrawQuickIcons | WidgetFlags.DrawPopup | WidgetFlags.HasAdvanced; private static readonly GearSelector _gearSelector = new("gear_selector"); private const ActorEquipSlot _propSlots = ActorEquipSlot.Prop; @@ -26,20 +28,37 @@ internal class ActorAppearanceWidget(ActorAppearanceCapability capability) : Wid public override void DrawBody() { if(Capability.Actor.IsProp) + { DrawPropLoadAppearance(); + ImGui.Separator(); + AppearanceEditorCommon.DrawPenumbraCollectionSwitcher(Capability); + } else { DrawLoadAppearance(); + ImGui.Separator(); AppearanceEditorCommon.DrawPenumbraCollectionSwitcher(Capability); + AppearanceEditorCommon.DrawGlamourerDesignSwitcher(Capability); + AppearanceEditorCommon.DrawCustomizePlusProfileSwitcher(Capability); } } + private void DrawPropLoadAppearance() { var currentAppearance = Capability.CurrentAppearance; var originalAppearance = Capability.OriginalAppearance; + if(ImBrio.FontIconButton("attachweapon", FontAwesomeIcon.Retweet, "Reload Prop")) + { + Capability.AttachWeapon(); + Capability.Actor.GetCapability().LoadResourcesPose("Data.BrioPropPose.pose"); + } + ImGui.SameLine(); + bool didChange = DrawReset(ref currentAppearance, originalAppearance); + ImGui.Separator(); + didChange |= DrawPropSlot(ref currentAppearance, ref currentAppearance.Weapons.OffHand, ActorEquipSlot.Prop | ActorEquipSlot.OffHand); if(didChange) @@ -50,7 +69,7 @@ private bool DrawReset(ref ActorAppearance currentAppearance, ActorAppearance or { bool didChange = false; - var resetTo = ImGui.GetCursorPos(); + //var resetTo = ImGui.GetCursorPos(); bool equipChanged = !currentAppearance.Equipment.Equals(originalAppearance.Equipment) || !currentAppearance.Weapons.Equals(originalAppearance.Weapons) || !currentAppearance.Runtime.Equals(originalAppearance.Runtime); if(ImBrio.FontIconButtonRight("reset_equipment", FontAwesomeIcon.Undo, 1, "Reset Equipment", equipChanged)) { @@ -59,7 +78,7 @@ private bool DrawReset(ref ActorAppearance currentAppearance, ActorAppearance or currentAppearance.Runtime = originalAppearance.Runtime; didChange |= true; } - ImGui.SetCursorPos(resetTo); + //ImGui.SetCursorPos(resetTo); return didChange; } @@ -76,7 +95,7 @@ private bool DrawPropSlot(ref ActorAppearance appearance, ref WeaponModelId equi var model = GameDataProvider.Instance.ModelDatabase.GetModelById(equip, _propSlots); - using(ImRaii.PushId(slot.ToString())) + using(ImRaii.PushId("DrawPropSlot")) { if(ImBrio.BorderedGameIcon("##icon", model?.Icon ?? 0, fallback, size: IconSize)) { @@ -90,7 +109,7 @@ private bool DrawPropSlot(ref ActorAppearance appearance, ref WeaponModelId equi { if(group.Success) { - string description = $"{slot}: {model?.Name ?? "Unknown"}"; + string description = $"{model?.Name ?? "Unknown"}"; ImGui.Text(description); @@ -119,13 +138,6 @@ private bool DrawPropSlot(ref ActorAppearance appearance, ref WeaponModelId equi didChange |= true; } - ImGui.SameLine(); - if(ImBrio.FontIconButton("attachweapon", FontAwesomeIcon.FistRaised, "Attach Weapon", bordered: false)) - { - Capability.AttachWeapon(); - didChange |= true; - } - using(var gearPopup = ImRaii.Popup("gear_popup")) { if(gearPopup.Success) @@ -159,12 +171,12 @@ private void DrawLoadAppearance() ImGui.SameLine(); - if(ImBrio.FontIconButton("import_charafile", FontAwesomeIcon.Download, "Import Character")) + if(ImBrio.FontIconButton("import_charafile", FontAwesomeIcon.FileDownload, "Import Character")) FileUIHelpers.ShowImportCharacterModal(Capability, AppearanceImportOptions.Default); ImGui.SameLine(); - if(ImBrio.FontIconButton("export_charafile", FontAwesomeIcon.FileExport, "Export Character File")) + if(ImBrio.FontIconButton("export_charafile", FontAwesomeIcon.Save, "Save Character File")) FileUIHelpers.ShowExportCharacterModal(Capability); ImGui.SameLine(); diff --git a/Brio/UI/Widgets/Actor/ActorContainerWidget.cs b/Brio/UI/Widgets/Actor/ActorContainerWidget.cs index 85f0d9be..e01747b3 100644 --- a/Brio/UI/Widgets/Actor/ActorContainerWidget.cs +++ b/Brio/UI/Widgets/Actor/ActorContainerWidget.cs @@ -9,17 +9,17 @@ namespace Brio.UI.Widgets.Actor; -internal class ActorContainerWidget(ActorContainerCapability capability) : Widget(capability) +public class ActorContainerWidget(ActorContainerCapability capability) : Widget(capability) { public override string HeaderName => "Actors"; public override WidgetFlags Flags { get { - WidgetFlags flags = WidgetFlags.DefaultOpen | WidgetFlags.DrawBody; + WidgetFlags flags = WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.DrawQuickIcons; if(Capability.CanControlCharacters) - flags |= WidgetFlags.DrawPopup; + flags |= WidgetFlags.DrawPopup | WidgetFlags.CanHide; return flags; } @@ -27,25 +27,8 @@ public override WidgetFlags Flags private ActorEntity? _selectedActor; - public override void DrawBody() + public override void DrawQuickIcons() { - if(ImGui.BeginListBox($"###actorcontainerwidget_{Capability.Entity.Id}_list", new Vector2(-1, 150))) - { - foreach(var child in Capability.Entity.Children) - { - if(child is ActorEntity actorEntity) - { - bool isSelected = actorEntity.Equals(_selectedActor); - if(ImGui.Selectable($"{child.FriendlyName}###actorcontainerwidget_{Capability.Entity.Id}_item_{actorEntity.Id}", isSelected, ImGuiSelectableFlags.AllowDoubleClick)) - { - _selectedActor = actorEntity; - } - } - } - - ImGui.EndListBox(); - } - using(ImRaii.Disabled(!Capability.CanControlCharacters)) { bool hasSelection = _selectedActor != null; @@ -99,6 +82,26 @@ public override void DrawBody() } } + public override void DrawBody() + { + if(ImGui.BeginListBox($"###actorcontainerwidget_{Capability.Entity.Id}_list", new Vector2(-1, 150))) + { + foreach(var child in Capability.Entity.Children) + { + if(child is ActorEntity actorEntity) + { + bool isSelected = actorEntity.Equals(_selectedActor); + if(ImGui.Selectable($"{child.FriendlyName}###actorcontainerwidget_{Capability.Entity.Id}_item_{actorEntity.Id}", isSelected, ImGuiSelectableFlags.AllowDoubleClick)) + { + _selectedActor = actorEntity; + } + } + } + + ImGui.EndListBox(); + } + } + public override void DrawPopup() { if(ImGui.MenuItem("Spawn###containerwidgetpopup_spawnbasic")) diff --git a/Brio/UI/Widgets/Actor/ActorDebugWidget.cs b/Brio/UI/Widgets/Actor/ActorDebugWidget.cs index fa51ff03..ce1768d0 100644 --- a/Brio/UI/Widgets/Actor/ActorDebugWidget.cs +++ b/Brio/UI/Widgets/Actor/ActorDebugWidget.cs @@ -6,7 +6,7 @@ namespace Brio.UI.Widgets.Actor; -internal class ActorDebugWidget(ActorDebugCapability capability) : Widget(capability) +public class ActorDebugWidget(ActorDebugCapability capability) : Widget(capability) { public override string HeaderName => "Debug"; diff --git a/Brio/UI/Widgets/Actor/ActorDynamicPoseWidget.cs b/Brio/UI/Widgets/Actor/ActorDynamicPoseWidget.cs new file mode 100644 index 00000000..de7714c7 --- /dev/null +++ b/Brio/UI/Widgets/Actor/ActorDynamicPoseWidget.cs @@ -0,0 +1,31 @@ +using Brio.Capabilities.Actor; +using Brio.UI.Controls.Stateless; +using Brio.UI.Widgets.Core; +using Dalamud.Interface; +using ImGuiNET; + +namespace Brio.UI.Widgets.Actor; +public class ActorDynamicPoseWidget(ActorDynamicPoseCapability capability) : Widget(capability) +{ + public override string HeaderName => "Dynamic Face Control"; + + public override WidgetFlags Flags => capability.Actor.IsProp ? WidgetFlags.CanHide : + WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.HasAdvanced; + + public override void DrawBody() + { + if(ImBrio.FontIconButton("agc_appearance", FontAwesomeIcon.ArrowsToEye, "A Advanced")) + Capability.TESTactorlook(); + + ImGui.SameLine(); + + if(ImBrio.FontIconButton("agcc_appearance", FontAwesomeIcon.ArrowsToEye, "C Advanced")) + Capability.TESTactorlookClear(); + + } + + public override void ToggleAdvancedWindow() + { + + } +} diff --git a/Brio/UI/Widgets/Actor/ActorLifetimeWidget.cs b/Brio/UI/Widgets/Actor/ActorLifetimeWidget.cs index 2b0d5fb3..501bf098 100644 --- a/Brio/UI/Widgets/Actor/ActorLifetimeWidget.cs +++ b/Brio/UI/Widgets/Actor/ActorLifetimeWidget.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Widgets.Actor; -internal class ActorLifetimeWidget(ActorLifetimeCapability capability) : Widget(capability) +public class ActorLifetimeWidget(ActorLifetimeCapability capability) : Widget(capability) { public override string HeaderName => "Lifetime"; @@ -15,13 +15,6 @@ internal class ActorLifetimeWidget(ActorLifetimeCapability capability) : Widget< public override void DrawQuickIcons() { - if(ImBrio.FontIconButton("lifetimewidget_spawn_prop", FontAwesomeIcon.Cubes, "Spawn Prop")) - { - Capability.SpawnNewProp(false); - } - - ImGui.SameLine(); - if(ImBrio.FontIconButton("lifetimewidget_spawnnew", FontAwesomeIcon.Plus, "Spawn New Actor")) { Capability.SpawnNewActor(false, false, true); @@ -43,9 +36,9 @@ public override void DrawQuickIcons() ImGui.SameLine(); - if(ImBrio.FontIconButton("lifetimewidget_destroy", FontAwesomeIcon.Trash, "Destroy", Capability.CanDestroy)) + if(ImBrio.FontIconButton("lifetimewidget_spawn_prop", FontAwesomeIcon.Cubes, "Spawn Prop")) { - Capability.Destroy(); + Capability.SpawnNewProp(true); } ImGui.SameLine(); @@ -57,6 +50,13 @@ public override void DrawQuickIcons() ImGui.SameLine(); + if(ImBrio.FontIconButton("lifetimewidget_destroy", FontAwesomeIcon.Trash, "Destroy", Capability.CanDestroy)) + { + Capability.Destroy(); + } + + ImGui.SameLine(); + if(ImBrio.FontIconButton("lifetimewidget_rename", FontAwesomeIcon.Signature, "Rename")) { RenameActorModal.Open(Capability.Actor); diff --git a/Brio/UI/Widgets/Actor/CompanionWidget.cs b/Brio/UI/Widgets/Actor/CompanionWidget.cs index 48beecc9..a52855e5 100644 --- a/Brio/UI/Widgets/Actor/CompanionWidget.cs +++ b/Brio/UI/Widgets/Actor/CompanionWidget.cs @@ -8,7 +8,7 @@ using ImGuiNET; namespace Brio.UI.Widgets.Actor; -internal unsafe class CompanionWidget(CompanionCapability capability) : Widget(capability) +public unsafe class CompanionWidget(CompanionCapability capability) : Widget(capability) { public override string HeaderName => Capability.Mode switch { diff --git a/Brio/UI/Widgets/Actor/StatusEffectsWidget.cs b/Brio/UI/Widgets/Actor/StatusEffectsWidget.cs index ab0b0cf7..ec721cf0 100644 --- a/Brio/UI/Widgets/Actor/StatusEffectsWidget.cs +++ b/Brio/UI/Widgets/Actor/StatusEffectsWidget.cs @@ -12,7 +12,7 @@ namespace Brio.UI.Widgets.Actor; -internal class StatusEffectsWidget(StatusEffectCapability capability) : Widget(capability) +public class StatusEffectsWidget(StatusEffectCapability capability) : Widget(capability) { public override string HeaderName => "Status Effects"; diff --git a/Brio/UI/Widgets/Camera/CameraContainerWidget.cs b/Brio/UI/Widgets/Camera/CameraContainerWidget.cs new file mode 100644 index 00000000..be3028ba --- /dev/null +++ b/Brio/UI/Widgets/Camera/CameraContainerWidget.cs @@ -0,0 +1,127 @@ +using Brio.Capabilities.Camera; +using Brio.Entities.Camera; +using Brio.UI.Controls.Editors; +using Brio.UI.Controls.Stateless; +using Brio.UI.Widgets.Core; +using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; +using System.Numerics; + +namespace Brio.UI.Widgets.Camera; + +public class CameraContainerWidget(CameraContainerCapability capability) : Widget(capability) +{ + public override string HeaderName => "Cameras"; + + public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody | WidgetFlags.DrawPopup | WidgetFlags.DrawQuickIcons; + + private CameraEntity? _selectedEntity; + + public override void DrawQuickIcons() + { + using(ImRaii.Disabled(Capability.IsAllowed == false)) + { + bool hasSelection = _selectedEntity != null; + + if(ImBrio.FontIconButton("CameraContainerWidget_New_Camera", FontAwesomeIcon.Plus, "New Camera")) + { + ImGui.OpenPopup("DrawSpawnMenuPopup"); + } + CameraEditor.DrawSpawnMenu(Capability.VirtualCameraManager); + + ImGui.SameLine(); + + using(ImRaii.Disabled(hasSelection == false)) + { + using(ImRaii.Disabled(true)) + if(ImBrio.FontIconButton("CameraLifetime_clone", FontAwesomeIcon.Clone, "Clone Camera")) + { + + } + + ImGui.SameLine(); + + using(ImRaii.Disabled(_selectedEntity?.VirtualCamera.CameraID == 0)) + { + if(ImBrio.FontIconButton("CameraLifetime_destroy", FontAwesomeIcon.Trash, "Destroy Camera")) + { + Capability.VirtualCameraManager.DestroyCamera(_selectedEntity!.VirtualCamera.CameraID); + } + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButton("CameraLifetime_target", FontAwesomeIcon.LocationCrosshairs, "Target Camera")) + { + Capability.VirtualCameraManager.SelectCamera(_selectedEntity!.VirtualCamera); + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButton("containerwidget_selectinhierarchy", FontAwesomeIcon.FolderTree, "Select in Hierarchy", hasSelection)) + { + Capability.VirtualCameraManager.SelectInHierarchy(_selectedEntity!); + } + } + + using(ImRaii.Disabled(Capability.VirtualCameraManager.CamerasCount == 0)) + { + ImGui.SameLine(); + + if(ImBrio.FontIconButton("containerwidget_destroyall", FontAwesomeIcon.Bomb, "Destroy All")) + { + Capability.VirtualCameraManager.DestroyAll(); + } + } + } + } + + public unsafe override void DrawBody() + { + using(ImRaii.Disabled(Capability.IsAllowed == false)) + { + if(ImGui.BeginListBox($"###CameraContainerWidget_{Capability.Entity.Id}_list", new Vector2(-1, 150))) + { + foreach(var child in Capability.Entity.Children) + { + if(child is CameraEntity cameraEntity) + { + bool isSelected = cameraEntity.Equals(_selectedEntity); + if(ImGui.Selectable($"{child.FriendlyName}###CameraContainerWidget_{Capability.Entity.Id}_item_{cameraEntity.Id}", isSelected, ImGuiSelectableFlags.AllowDoubleClick)) + { + _selectedEntity = cameraEntity; + } + } + } + + ImGui.EndListBox(); + } + } + } +} + +public class BrioCameraWidget(BrioCameraCapability capability) : Widget(capability) +{ + public override string HeaderName => "Camera Editor"; + + public override WidgetFlags Flags => WidgetFlags.DrawBody | WidgetFlags.DefaultOpen | WidgetFlags.HasAdvanced; + + public unsafe override void DrawBody() + { + if(Capability.CameraEntity.CameraType == CameraType.Free) + { + CameraEditor.DrawFreeCam("camera_widget_editor", Capability); + } + else if(Capability.CameraEntity.CameraType == CameraType.Cutscene) + { + + } + else + { + CameraEditor.DrawBrioCam("camera_widget_editor", Capability); + } + } + + public override void ToggleAdvancedWindow() => Capability.ShowCameraWindow(); +} diff --git a/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs b/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs new file mode 100644 index 00000000..e46b4c83 --- /dev/null +++ b/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs @@ -0,0 +1,96 @@ +using Brio.Capabilities.Camera; +using Brio.UI.Controls; +using Brio.UI.Controls.Editors; +using Brio.UI.Controls.Stateless; +using Brio.UI.Widgets.Core; +using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using ImGuiNET; + +namespace Brio.UI.Widgets.Camera; + +public class CameraLifetimeWidget(CameraLifetimeCapability capability) : Widget(capability) +{ + public override string HeaderName => "Lifetime"; + + public override WidgetFlags Flags => WidgetFlags.DrawPopup | WidgetFlags.DrawQuickIcons; + + public override void DrawQuickIcons() + { + using(ImRaii.Disabled(Capability.IsAllowed == false)) + { + if(ImBrio.FontIconButton("CameraLifetime_spawnnew", FontAwesomeIcon.Plus, "New Camera")) + { + ImGui.OpenPopup("DrawSpawnMenuPopup"); + } + CameraEditor.DrawSpawnMenu(Capability.VirtualCameraManager); + + ImGui.SameLine(); + + using(ImRaii.Disabled(true)) + if(ImBrio.FontIconButton("CameraLifetime_clone", FontAwesomeIcon.Clone, "Clone Camera", Capability.CanClone)) + { + + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButton("CameraLifetime_target", FontAwesomeIcon.Bullseye, "Target Camera")) + { + Capability.VirtualCameraManager.SelectCamera(Capability.VirtualCamera); + } + + ImGui.SameLine(); + + using(ImRaii.Disabled(Capability.CameraEntity.CameraID == 0)) + { + if(ImBrio.FontIconButton("CameraLifetime_destroy", FontAwesomeIcon.Trash, "Destroy Camera", Capability.CanDestroy)) + { + Capability.VirtualCameraManager.DestroyCamera(Capability.CameraEntity.CameraID); + } + + ImGui.SameLine(); + + if(ImBrio.FontIconButton("CameraLifetime_rename", FontAwesomeIcon.Signature, "Rename")) + { + RenameActorModal.Open(Capability.Entity); + } + } + } + } + + public override void DrawPopup() + { + if(Capability.IsAllowed == false) + return; + + if(ImGui.MenuItem("Target###CameraLifetime_target")) + { + Capability.VirtualCameraManager.SelectCamera(Capability.VirtualCamera); + } + + if(Capability.CanClone) + { + using(ImRaii.Disabled(true)) + if(ImGui.MenuItem("Clone###CameraLifetime_clone")) + { + + } + } + + if(Capability.CanDestroy) + { + if(ImGui.MenuItem("Destroy###CameraLifetime_destroy")) + { + Capability.VirtualCameraManager.DestroyCamera(Capability.CameraEntity.CameraID); + } + + if(ImGui.MenuItem($"Rename {Capability.CameraEntity.FriendlyName}###CameraLifetime_rename")) + { + ImGui.CloseCurrentPopup(); + + RenameActorModal.Open(Capability.Entity); + } + } + } +} diff --git a/Brio/UI/Widgets/Camera/CameraWidget.cs b/Brio/UI/Widgets/Camera/CameraWidget.cs deleted file mode 100644 index b2befcd0..00000000 --- a/Brio/UI/Widgets/Camera/CameraWidget.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Brio.Capabilities.Camera; -using Brio.UI.Controls.Editors; -using Brio.UI.Widgets.Core; - -namespace Brio.UI.Widgets.Camera; - -internal class CameraWidget : Widget -{ - public override string HeaderName => "Camera"; - - public override WidgetFlags Flags => WidgetFlags.DrawBody | WidgetFlags.DefaultOpen | WidgetFlags.HasAdvanced; - - public CameraWidget(CameraCapability capability) : base(capability) - { - } - - public unsafe override void DrawBody() - { - CameraEditor.Draw("camera_widget_editor", Capability); - } - - public override void ToggleAdvancedWindow() => Capability.ShowCameraWindow(); -} diff --git a/Brio/UI/Widgets/Core/Widget.cs b/Brio/UI/Widgets/Core/Widget.cs index f4d7864c..b56f3b6d 100644 --- a/Brio/UI/Widgets/Core/Widget.cs +++ b/Brio/UI/Widgets/Core/Widget.cs @@ -3,7 +3,7 @@ namespace Brio.UI.Widgets.Core; -internal interface IWidget +public interface IWidget { public string HeaderName { get; } public WidgetFlags Flags { get; } @@ -17,7 +17,7 @@ internal interface IWidget public void ToggleAdvancedWindow(); } -internal abstract class Widget(T capability) : IWidget where T : Capability +public abstract class Widget(T capability) : IWidget where T : Capability { public T Capability { get; } = capability; public abstract string HeaderName { get; } @@ -33,7 +33,7 @@ public virtual void ToggleAdvancedWindow() { } } [Flags] -internal enum WidgetFlags +public enum WidgetFlags { None = 0, DefaultOpen = 1 << 0, diff --git a/Brio/UI/Widgets/Core/WidgetHelpers.cs b/Brio/UI/Widgets/Core/WidgetHelpers.cs index b56fe025..46dfe470 100644 --- a/Brio/UI/Widgets/Core/WidgetHelpers.cs +++ b/Brio/UI/Widgets/Core/WidgetHelpers.cs @@ -7,7 +7,7 @@ namespace Brio.UI.Widgets.Core; -internal class WidgetHelpers +public class WidgetHelpers { public static void DrawBodies(IEnumerable capabilities) { diff --git a/Brio/UI/Widgets/Debug/DebugWidget.cs b/Brio/UI/Widgets/Debug/DebugWidget.cs index 92f42bbc..ac640fbc 100644 --- a/Brio/UI/Widgets/Debug/DebugWidget.cs +++ b/Brio/UI/Widgets/Debug/DebugWidget.cs @@ -6,7 +6,7 @@ namespace Brio.UI.Widgets.Debug; -internal class DebugWidget(DebugCapability capability, IClientState _clientState) : Widget(capability) +public class DebugWidget(DebugCapability capability, IClientState _clientState) : Widget(capability) { public override string HeaderName => "Debug"; @@ -75,8 +75,8 @@ private void DrawMisc() ImGui.Text($"MapId - {_clientState.MapId}"); ImGui.Text($"TerritoryType - {_clientState.TerritoryType}"); - ImGui.Text($"CurrentWorld - {_clientState.LocalPlayer.CurrentWorld.Value.InternalName}"); - ImGui.Text($"HomeWorld - {_clientState.LocalPlayer.HomeWorld.Value.InternalName}"); + ImGui.Text($"CurrentWorld - {_clientState.LocalPlayer.CurrentWorld.Value.Name}"); + ImGui.Text($"HomeWorld - {_clientState.LocalPlayer.HomeWorld.Value.Name}"); ImGui.Text(io.Framerate.ToString("F2") + " FPS"); } diff --git a/Brio/UI/Widgets/Posing/PosingWidget.cs b/Brio/UI/Widgets/Posing/PosingWidget.cs index 91a643fb..da7d195f 100644 --- a/Brio/UI/Widgets/Posing/PosingWidget.cs +++ b/Brio/UI/Widgets/Posing/PosingWidget.cs @@ -6,12 +6,11 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using ImGuiNET; -using OneOf.Types; using System.Numerics; namespace Brio.UI.Widgets.Posing; -internal class PosingWidget(PosingCapability capability) : Widget(capability) +public class PosingWidget(PosingCapability capability) : Widget(capability) { public override string HeaderName => "Posing"; @@ -33,6 +32,10 @@ public override void DrawBody() private void DrawButtons() { + if(Capability.Actor.TryGetCapability(out var capability) == false) + { + return; + } var overlayOpen = Capability.OverlayOpen; if(ImBrio.FontIconButton("overlay", overlayOpen ? FontAwesomeIcon.EyeSlash : FontAwesomeIcon.Eye, overlayOpen ? "Close Overlay" : "Open Overlay")) @@ -42,40 +45,19 @@ private void DrawButtons() ImGui.SameLine(); - if(Capability.Actor.TryGetCapability(out var capability)) + if(capability.Actor.IsProp == false) { - if(ImBrio.ToggelFontIconButton("freezeActor", FontAwesomeIcon.Snowflake, new Vector2(110, 0), capability.SpeedMultiplier == 0, hoverText: capability.SpeedMultiplierOverride == 0 ? "Un-Freeze Character" : "Freeze Character")) + if(ImBrio.FontIconButton("import", FontAwesomeIcon.FileDownload, "Import Pose")) { - if(capability.SpeedMultiplierOverride == 0) - capability.ResetOverallSpeedOverride(); - else - capability.SetOverallSpeedOverride(0f); + ImGui.OpenPopup("DrawImportPoseMenuPopup"); } - } - - ImGui.SameLine(); - - if(ImBrio.FontIconButton("import", FontAwesomeIcon.Download, "Import Pose")) - { - ImGui.OpenPopup("DrawImportPoseMenuPopup"); - } - - FileUIHelpers.DrawImportPoseMenuPopup(Capability); - - ImGui.SameLine(); - if(ImBrio.FontIconButton("export", FontAwesomeIcon.FileExport, "Export Pose")) - FileUIHelpers.ShowExportPoseModal(Capability); + FileUIHelpers.DrawImportPoseMenuPopup(Capability); - if(capability.Actor.IsProp == false) - { ImGui.SameLine(); - using(ImRaii.Disabled(Capability.Selected.Value is None)) - { - if(ImBrio.FontIconButton("clear_selection", FontAwesomeIcon.MinusSquare, "Clear Selection")) - Capability.ClearSelection(); - } + if(ImBrio.FontIconButton("export", FontAwesomeIcon.Save, "Save Pose")) + FileUIHelpers.ShowExportPoseModal(Capability); ImGui.SameLine(); @@ -101,6 +83,19 @@ private void DrawButtons() ImGui.SameLine(); + if(capability.Actor.IsProp == false) + { + if(ImBrio.ToggelFontIconButton("freezeActor", FontAwesomeIcon.Snowflake, new Vector2(0), capability.SpeedMultiplier == 0, hoverText: capability.SpeedMultiplierOverride == 0 ? "Un-Freeze Character" : "Freeze Character")) + { + if(capability.SpeedMultiplierOverride == 0) + capability.ResetOverallSpeedOverride(); + else + capability.SetOverallSpeedOverride(0f); + + } + ImGui.SameLine(); + } + if(ImBrio.FontIconButtonRight("reset", FontAwesomeIcon.Undo, 1, "Reset Pose", Capability.HasOverride)) { Capability.Reset(false, false, true); diff --git a/Brio/UI/Widgets/World/FestivalWidget.cs b/Brio/UI/Widgets/World/FestivalWidget.cs index 49859d6b..2d4a87fe 100644 --- a/Brio/UI/Widgets/World/FestivalWidget.cs +++ b/Brio/UI/Widgets/World/FestivalWidget.cs @@ -10,7 +10,7 @@ namespace Brio.UI.Widgets.World; -internal class FestivalWidget : Widget +public class FestivalWidget : Widget { public override string HeaderName => "Festivals"; public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody; diff --git a/Brio/UI/Widgets/World/TimeWidget.cs b/Brio/UI/Widgets/World/TimeWidget.cs index dd308733..5a1566e3 100644 --- a/Brio/UI/Widgets/World/TimeWidget.cs +++ b/Brio/UI/Widgets/World/TimeWidget.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Widgets.World; -internal class TimeWidget(TimeCapability timeCapability) : Widget(timeCapability) +public class TimeWidget(TimeCapability timeCapability) : Widget(timeCapability) { public override string HeaderName => "Time"; public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody; diff --git a/Brio/UI/Widgets/World/WeatherWidget.cs b/Brio/UI/Widgets/World/WeatherWidget.cs index 9355c2a4..4217633f 100644 --- a/Brio/UI/Widgets/World/WeatherWidget.cs +++ b/Brio/UI/Widgets/World/WeatherWidget.cs @@ -10,7 +10,7 @@ namespace Brio.UI.Widgets.World; -internal class WeatherWidget(WeatherCapability weatherCapability) : Widget(weatherCapability) +public class WeatherWidget(WeatherCapability weatherCapability) : Widget(weatherCapability) { public override string HeaderName => "Weather"; public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody; diff --git a/Brio/UI/Widgets/World/WorldRenderingWidget.cs b/Brio/UI/Widgets/World/WorldRenderingWidget.cs index 451bc4b1..95541bb0 100644 --- a/Brio/UI/Widgets/World/WorldRenderingWidget.cs +++ b/Brio/UI/Widgets/World/WorldRenderingWidget.cs @@ -4,7 +4,7 @@ namespace Brio.UI.Widgets.World; -internal class WorldRenderingWidget(WorldRenderingCapability worldRenderingCapability) : Widget(worldRenderingCapability) +public class WorldRenderingWidget(WorldRenderingCapability worldRenderingCapability) : Widget(worldRenderingCapability) { public override string HeaderName => "Rendering"; public override WidgetFlags Flags => WidgetFlags.DefaultOpen | WidgetFlags.DrawBody; diff --git a/Brio/UI/Windows/InfoWindow.cs b/Brio/UI/Windows/InfoWindow.cs index abeaf4d8..224bc35f 100644 --- a/Brio/UI/Windows/InfoWindow.cs +++ b/Brio/UI/Windows/InfoWindow.cs @@ -7,15 +7,19 @@ namespace Brio.UI.Windows; -internal class InfoWindow : Window +public class InfoWindow : Window { private readonly ConfigurationService _configurationService; private readonly UpdateWindow _updateWindow; - public InfoWindow(ConfigurationService configurationService, UpdateWindow updateWindow) : base($"{Brio.Name} Welcome###brio_info_window", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.AlwaysAutoResize) + public InfoWindow(ConfigurationService configurationService, UpdateWindow updateWindow) : base($"{Brio.Name} Welcome###brio_info_window", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize) { Namespace = "brio_info_namespace"; + this.AllowClickthrough = false; + this.AllowPinning = false; + this.ForceMainWindow = true; + _configurationService = configurationService; _updateWindow = updateWindow; @@ -41,8 +45,8 @@ public override void Draw() A Big Thank you to (Sufferhymn), (Night Song), (Alvar Valo), (Yasumi), (YikesXD), (Selitha), (AquilaHK), (LotusEcho), & (Yume) for their support on Kofi! - Also, Thank you, to: (@MKhayle), (@ashna_ff14), (@Yuki-Codes), (@danma3x), (@snaeling), - (@WorstAquaPlayer), (@Caraxi), & (@gris-fuego), for their contributions to Brio! + Also, Thank you, to: (Ashadow700), (@MKhayle), (@ashna_ff14), (@Yuki-Codes), (@danma3x), (@snaeling), + (@WorstAquaPlayer), (@Caraxi), (@Enth) & (@gris-fuego), for their contributions to Brio! Maintained & Developed by: Minmoose. Originally Developed by: Asgard. diff --git a/Brio/UI/Windows/LibraryWindow.cs b/Brio/UI/Windows/LibraryWindow.cs index 25cbd3d5..4d5758f6 100644 --- a/Brio/UI/Windows/LibraryWindow.cs +++ b/Brio/UI/Windows/LibraryWindow.cs @@ -11,6 +11,7 @@ using Brio.UI.Controls.Core; using Brio.UI.Controls.Editors; using Brio.UI.Controls.Stateless; +using Brio.UI.Theming; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; @@ -24,14 +25,14 @@ namespace Brio.UI.Windows; -internal class LibraryWindow : Window +public class LibraryWindow : Window { private static float WindowContentWidth => ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; private static float WindowContentHeight => ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y; private static Vector2 MinimumSize = new(785, 435); - private const float InfoPaneWidth = 350; + private const float InfoPaneWidth = 285; private const float SearchWidth = 400; private const int MaxTagsInSuggest = 25; private const float PathBarButtonWidth = 25; @@ -301,7 +302,7 @@ public override bool DrawConditions() public override void Draw() { - DrawInternal(); + DrawLibrary(); } public void DrawModal() @@ -317,12 +318,12 @@ public void DrawModal() { if(popup.Success) { - DrawInternal(); + DrawLibrary(); } } } - private void DrawInternal() + private void DrawLibrary() { using(ImRaii.PushId("##brio_library")) { @@ -440,7 +441,7 @@ private void DrawInternal() var config = ConfigurationService.Instance.Configuration; bool isFavorite = config.Library.Favorites.Contains(ieb.Identifier); - using(ImRaii.PushColor(ImGuiCol.Text, isFavorite ? UIConstants.GizmoRed : UIConstants.ToggleButtonInactive)) + using(ImRaii.PushColor(ImGuiCol.Text, isFavorite ? TheameManager.CurrentTheame.Accent.AccentColor : UIConstants.ToggleButtonInactive)) { if(ImBrio.FontIconButton(FontAwesomeIcon.Heart)) { @@ -712,7 +713,7 @@ private unsafe void DrawSearch() { float searchBarWidth = ImBrio.GetRemainingWidth(); float searchBarHeight = ImBrio.GetLineHeight(); - Vector2 searchbarPosition = ImGui.GetCursorScreenPos(); + Vector2 searchBarPosition = ImGui.GetCursorScreenPos(); using(ImRaii.PushColor(ImGuiCol.ChildBg, ImGui.GetColorU32(ImGuiCol.FrameBg))) { @@ -817,7 +818,7 @@ private unsafe void DrawSearch() _searchLostFocus = 0; } - _searchSuggestPos = new Vector2(searchbarPosition.X, searchbarPosition.Y + searchBarHeight); + _searchSuggestPos = new Vector2(searchBarPosition.X, searchBarPosition.Y + searchBarHeight); _searchSuggestSize = new Vector2(searchBarWidth, searchBarHeight); } } diff --git a/Brio/UI/Windows/MainWindow.cs b/Brio/UI/Windows/MainWindow.cs index 4fe32991..50b2387a 100644 --- a/Brio/UI/Windows/MainWindow.cs +++ b/Brio/UI/Windows/MainWindow.cs @@ -1,7 +1,10 @@ using Brio.Config; using Brio.Entities; +using Brio.Game.Core; +using Brio.Game.GPose; using Brio.Game.Scene; using Brio.Input; +using Brio.UI.Controls.Core; using Brio.UI.Controls.Stateless; using Brio.UI.Entitites; using Dalamud.Interface; @@ -13,7 +16,7 @@ namespace Brio.UI.Windows; -internal class MainWindow : Window, IDisposable +public class MainWindow : Window, IDisposable { private readonly SettingsWindow _settingsWindow; private readonly InfoWindow _infoWindow; @@ -23,6 +26,9 @@ internal class MainWindow : Window, IDisposable private readonly EntityManager _entityManager; private readonly EntityHierarchyView _entitySelector; private readonly SceneService _sceneService; + private readonly ProjectWindow _projectWindow; + private readonly GPoseService _gPoseService; + private readonly AutoSaveService _autoSaveService; public MainWindow( ConfigurationService configService, @@ -31,7 +37,10 @@ public MainWindow( LibraryWindow libraryWindow, EntityManager entityManager, InputService input, - SceneService sceneService + SceneService sceneService, + GPoseService gPoseService, + ProjectWindow projectWindow, + AutoSaveService autoSaveService ) : base($"{Brio.Name} Scene Manager [{configService.Version}]###brio_main_window", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.AlwaysAutoResize) { @@ -45,13 +54,20 @@ SceneService sceneService _entityManager = entityManager; _entitySelector = new(_entityManager); _sceneService = sceneService; + _projectWindow = projectWindow; + _gPoseService = gPoseService; + _autoSaveService = autoSaveService; SizeConstraints = new WindowSizeConstraints { - MaximumSize = new Vector2(270, 5000), + MaximumSize = new Vector2(270, 1030), MinimumSize = new Vector2(270, 200) }; + this.AllowClickthrough = false; + this.AllowPinning = false; + this.ForceMainWindow = true; + input.AddListener(KeyBindEvents.Interface_ToggleBrioWindow, this.OnMainWindowToggle); input.AddListener(KeyBindEvents.Interface_ToggleBindPromptWindow, this.OnPromptWindowToggle); } @@ -60,20 +76,29 @@ public override void Draw() { DrawHeaderButtons(); - var rootEntity = _entityManager.RootEntity; - - if(rootEntity is null) - return; + if(_gPoseService.IsGPosing == false) + { + using(ImRaii.PushColor(ImGuiCol.Text, UIConstants.GizmoRed)) + ImGui.Text("Open GPose to use Brio!"); + } - using(var container = ImRaii.Child("###entity_hierarchy_container", new Vector2(-1, ImGui.GetTextLineHeight() * 15f), true)) + using(ImRaii.Disabled(_gPoseService.IsGPosing == false)) { - if(container.Success) + var rootEntity = _entityManager.RootEntity; + + if(rootEntity is null) + return; + + using(var container = ImRaii.Child("###entity_hierarchy_container", new Vector2(-1, ImGui.GetTextLineHeight() * 18f), true)) { - _entitySelector.Draw(rootEntity); + if(container.Success) + { + _entitySelector.Draw(rootEntity); + } } - } - EntityHelpers.DrawEntitySection(_entityManager.SelectedEntity); + EntityHelpers.DrawEntitySection(_entityManager.SelectedEntity); + } } private void OnMainWindowToggle() @@ -88,29 +113,30 @@ private void OnPromptWindowToggle() _configurationService.ApplyChange(); } - private const int Line1NumberOfButtons = 2; - private const int Line2NumberOfButtons = 0; private void DrawHeaderButtons() { float buttonWidths = 25; - float line1FinalWidth = ImBrio.GetRemainingWidth() - ((buttonWidths * Line1NumberOfButtons) + (ImGui.GetStyle().ItemSpacing.X * Line1NumberOfButtons) + ImGui.GetStyle().WindowBorderSize); - float line2FinalWidth = ImBrio.GetRemainingWidth() - ((buttonWidths * Line2NumberOfButtons) + (ImGui.GetStyle().ItemSpacing.X * Line2NumberOfButtons) + ImGui.GetStyle().WindowBorderSize); + float line1FinalWidth = ImBrio.GetRemainingWidth() - ((buttonWidths * 2) + (ImGui.GetStyle().ItemSpacing.X * 2) + ImGui.GetStyle().WindowBorderSize); float line1Width = (line1FinalWidth / 2) - 3; - if(ImBrio.Button(" Project", FontAwesomeIcon.FolderOpen, new Vector2(line1Width, 0))) + using(ImRaii.Disabled(_gPoseService.IsGPosing == false)) { - ImGui.OpenPopup("DrawProjectPopup"); - } + // This fixes a bug with text scaling + { + Vector2 startPos = ImGui.GetCursorPos(); + ImGui.SetCursorPos(new(-100, -100)); + ImBrio.Button("0000", FontAwesomeIcon.Bug, new Vector2(0, 0)); + ImGui.SetCursorPos(startPos); + } - FileUIHelpers.DrawProjectPopup(_sceneService, _entityManager); + if(ImBrio.Button("Project", FontAwesomeIcon.FolderOpen, new Vector2(line1Width, 0))) + ImGui.OpenPopup("DrawProjectPopup"); - ImGui.SameLine(); - if(ImBrio.Button("Library", FontAwesomeIcon.Book, new Vector2(line1Width, 0))) - _libraryWindow.Toggle(); - - if(ImGui.IsItemHovered()) - ImGui.SetTooltip("Open the Library"); + ImGui.SameLine(); + if(ImBrio.Button("Library", FontAwesomeIcon.Book, new Vector2(line1Width, 0))) + _libraryWindow.Toggle(); + } ImGui.SameLine(); if(ImBrio.FontIconButton(FontAwesomeIcon.InfoCircle, new(buttonWidths, 0))) @@ -127,7 +153,7 @@ private void DrawHeaderButtons() ImGui.SetTooltip("Settings"); // - // Line 2 + FileUIHelpers.DrawProjectPopup(_sceneService, _entityManager, _projectWindow, _autoSaveService); } public void Dispose() diff --git a/Brio/UI/Windows/ProjectWindow.cs b/Brio/UI/Windows/ProjectWindow.cs new file mode 100644 index 00000000..f762df74 --- /dev/null +++ b/Brio/UI/Windows/ProjectWindow.cs @@ -0,0 +1,215 @@ +using Brio.Game.Core; +using Brio.Game.GPose; +using Brio.UI.Controls.Core; +using Brio.UI.Controls.Stateless; +using Dalamud.Interface; +using Dalamud.Interface.Utility.Raii; +using Dalamud.Interface.Windowing; +using ImGuiNET; +using System; +using System.Numerics; + +namespace Brio.UI.Windows; + +public class ProjectWindow : Window, IDisposable +{ + private readonly ProjectSystem _projectSystem; + private readonly GPoseService _gPoseService; + + int selected = 0; + static Project? selectedItem; + private const float InfoPaneWidth = 200; + + public ProjectWindow(ProjectSystem projectSystem, GPoseService gPoseService) : base($"Project Window BETA###brio_project_window", ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse) + { + Namespace = "brio_project_namespace"; + + _projectSystem = projectSystem; + _gPoseService = gPoseService; + + WindowSizeConstraints constraints = new() + { + MinimumSize = new(600, 400), + MaximumSize = new(785, 435) + }; + this.SizeConstraints = constraints; + + _gPoseService.OnGPoseStateChange += GPoseService_OnGPoseStateChange; + } + + string currentActorName = string.Empty; + string currentActorDis = string.Empty; + public override void Draw() + { + using(ImRaii.PushColor(ImGuiCol.Text, UIConstants.GizmoMagenta)) + ImGui.Text("Project System is in Beta. NOTE: Projects might not be compatible from version to version!"); + + ImBrio.ToggleButtonStrip("library_filters_selector", new Vector2(ImBrio.GetRemainingWidth(), ImBrio.GetLineHeight()), ref selected, ["Load", "Save"]); + + var firstPos = ImGui.GetCursorPos(); + + using(ImRaii.Disabled(selected != 0 || _projectSystem.IsLoading)) + DrawLoad(); + + if(selected == 1) + { + var windowSize = ImGui.GetWindowSize(); + + var lastPos = ImGui.GetCursorPos(); + + ImGui.SetCursorPos(firstPos); + + using(var child = ImRaii.Child("###new_pane", new Vector2(ImBrio.GetRemainingWidth(), ImBrio.GetRemainingHeight()), false)) + { + if(child.Success) + { + ImGui.Text($"Save New Project"); + + ImGui.InputText("Project Name###brio_popup_name", ref currentActorName, 35); + ImGui.InputText("Project Description###brio_popup_dis", ref currentActorDis, 35); + + using(ImRaii.Disabled(string.IsNullOrEmpty(currentActorName))) + if(ImBrio.Button("Save Project", FontAwesomeIcon.Save, new(135, 0), centerTest: true, hoverText: "Save Project")) + { + _projectSystem.NewProject(currentActorName, currentActorDis); + + selected = 0; + + currentActorName = string.Empty; + currentActorDis = string.Empty; + } + } + } + + ImGui.SetCursorPos(lastPos); + } + } + + bool destroyAll = false; + bool doDelete = false; + public void DrawLoad() + { + var windowSize = ImGui.GetWindowSize(); + using(var child = ImRaii.Child("###left_pane", new Vector2(windowSize.X - InfoPaneWidth, -1), false, ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)) + { + if(child.Success == false) + return; + + float entriesPaneHeight = ImBrio.GetRemainingHeight() - ImBrio.GetLineHeight() - ImGui.GetStyle().ItemSpacing.Y; + float entriesPaneWidth = ImBrio.GetRemainingWidth(); + using(var entriesChild = ImRaii.Child("###entries_pane", new Vector2(entriesPaneWidth, entriesPaneHeight), true)) + { + if(entriesChild.Success == false) + return; + + int x = 0; + foreach(var item in _projectSystem.BrioProjects.Projects) + { + bool selected = false; + + if(selectedItem is not null && selectedItem.Equals(item)) + selected = true; + + x++; + var selected2 = DrawSourceItem(x, item, selected); + + if(selected2) + { + selectedItem = item; + } + } + } + + using(ImRaii.Disabled(selectedItem is null)) + { + if(ImBrio.Button("Load", FontAwesomeIcon.FileImport, new(120, 0), centerTest: true, hoverText: "Load Project")) + { + _projectSystem.LoadProject(selectedItem!, destroyAll); + } + + ImGui.SameLine(); + + if(ImGui.Checkbox("Override Current Scene", ref destroyAll)) + { + + } + } + } + + ImGui.SameLine(); + + using(var child = ImRaii.Child("###right_pane", new Vector2(ImBrio.GetRemainingWidth(), -1), false, ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)) + { + if(child.Success == false) + return; + + float paneHeight = ImBrio.GetRemainingHeight() - (ImBrio.GetLineHeight() + ImGui.GetStyle().ItemSpacing.Y); + + using(var child2 = ImRaii.Child("###library_info_pane", new Vector2(ImBrio.GetRemainingWidth(), paneHeight), true, + ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)) + { + if(child2.Success == false) + return; + + if(selectedItem is not null) + { + ImGui.Text(selectedItem.Name); + + if(string.IsNullOrEmpty(selectedItem.Description) == false) + ImGui.Text(selectedItem.Description); + } + } + using(ImRaii.Disabled(selectedItem is null)) + { + ImGui.Checkbox("###doDelete", ref doDelete); + ImGui.SameLine(); + using(ImRaii.Disabled(doDelete == false)) + if(ImBrio.Button("Delete", FontAwesomeIcon.Trash, new(120, 0), centerTest: true, hoverText: "Delete Project")) + { + _projectSystem.DeleteProject(selectedItem!); + selectedItem = null; + } + } + } + + } + + private static bool DrawSourceItem(int id, Project project, bool isSelected) + { + float itemHeight = (ImBrio.GetLineHeight() * 3) + ImGui.GetStyle().ItemSpacing.Y; + + float itemTop = ImGui.GetCursorPosY(); + bool isSelectedItem = isSelected; + ImGui.Selectable($"###settings_source_{id}_selectable", ref isSelectedItem, ImGuiSelectableFlags.None, new(ImBrio.GetRemainingWidth(), itemHeight)); + + bool isHover = ImGui.IsItemHovered(); + + ImGui.SetCursorPosY(itemTop + ImGui.GetStyle().FramePadding.Y); + + ImGui.Text(project.Name ?? "No Name Source"); + + if(project.Created.HasValue) + ImGui.Text($"Created: {project.Created.Value:g}"); + + ImGui.Text(project.Description ?? "No Description"); + + ImGui.SetCursorPosY(itemTop + itemHeight + ImGui.GetStyle().ItemSpacing.Y); + + ImGui.Separator(); + + return isSelectedItem; + } + + private void GPoseService_OnGPoseStateChange(bool newState) + { + if(newState == false) + { + this.IsOpen = false; + } + } + + public void Dispose() + { + _gPoseService.OnGPoseStateChange -= GPoseService_OnGPoseStateChange; + } +} diff --git a/Brio/UI/Windows/SettingsWindow.cs b/Brio/UI/Windows/SettingsWindow.cs index 67c82a67..ffc8334f 100644 --- a/Brio/UI/Windows/SettingsWindow.cs +++ b/Brio/UI/Windows/SettingsWindow.cs @@ -2,6 +2,7 @@ using Brio.Input; using Brio.IPC; using Brio.Resources; +using Brio.UI.Controls.Core; using Brio.UI.Controls.Editors; using Brio.UI.Controls.Stateless; using Brio.Web; @@ -14,13 +15,14 @@ namespace Brio.UI.Windows; -internal class SettingsWindow : Window +public class SettingsWindow : Window { private readonly ConfigurationService _configurationService; private readonly PenumbraService _penumbraService; private readonly GlamourerService _glamourerService; private readonly WebService _webService; private readonly BrioIPCService _brioIPCService; + private readonly CustomizePlusService _customizePlusService; private readonly MareService _mareService; public SettingsWindow( @@ -28,6 +30,7 @@ public SettingsWindow( PenumbraService penumbraService, GlamourerService glamourerService, WebService webService, + CustomizePlusService customizePlusService, BrioIPCService brioIPCService, MareService mareService) : base($"{Brio.Name} Settings###brio_settings_window", ImGuiWindowFlags.NoResize) { @@ -39,6 +42,7 @@ public SettingsWindow( _webService = webService; _brioIPCService = brioIPCService; _mareService = mareService; + _customizePlusService = customizePlusService; Size = new Vector2(450, 450); } @@ -77,7 +81,6 @@ public override void Draw() { IsOpen = false; } - } else { @@ -190,11 +193,18 @@ private void DrawDisplaySettings() _configurationService.Configuration.Interface.CensorActorNames = censorActorNames; _configurationService.ApplyChange(); } + + bool enableBrioColor = _configurationService.Configuration.Appearance.EnableBrioColor; + if(ImGui.Checkbox("Enable Brio Color", ref enableBrioColor)) + { + _configurationService.Configuration.Appearance.EnableBrioColor = enableBrioColor; + _configurationService.ApplyChange(); + } } private void DrawSceneTab() { - using(var tab = ImRaii.TabItem("Scene")) + using(var tab = ImRaii.TabItem("Auto-Save")) { if(tab.Success) { @@ -219,139 +229,187 @@ private void DrawThirdPartyIPC() { if(ImGui.CollapsingHeader("Third-Party", ImGuiTreeNodeFlags.DefaultOpen)) { - bool enablePenumbra = _configurationService.Configuration.IPC.AllowPenumbraIntegration; - if(ImGui.Checkbox("Allow Penumbra Integration", ref enablePenumbra)) + bool enableCustomizePlus = _configurationService.Configuration.IPC.AllowCustomizePlusIntegration; + if(ImGui.Checkbox("Allow Customize+ Integration", ref enableCustomizePlus)) { - _configurationService.Configuration.IPC.AllowPenumbraIntegration = enablePenumbra; + _configurationService.Configuration.IPC.AllowCustomizePlusIntegration = enableCustomizePlus; _configurationService.ApplyChange(); + _customizePlusService.CheckStatus(true); } - using(ImRaii.Disabled(!enablePenumbra)) + var customizePlusStatus = _customizePlusService.CheckStatus(); + using(ImRaii.Disabled(!enableCustomizePlus)) { - ImGui.Text($"Penumbra Status: {(_penumbraService.IsPenumbraAvailable ? "Active" : "Inactive")}"); + ImGui.Text($"Customize+ Status: {customizePlusStatus}"); ImGui.SameLine(); - if(ImBrio.FontIconButton("refresh_penumbra", FontAwesomeIcon.Sync, "Refresh Penumbra Status")) + if(ImBrio.FontIconButton("refresh_Customize", FontAwesomeIcon.Sync, "Refresh Customize+ Status")) { - _penumbraService.RefreshPenumbraStatus(); + _customizePlusService.CheckStatus(true); } } + } - bool enableGlamourer = _configurationService.Configuration.IPC.AllowGlamourerIntegration; - if(ImGui.Checkbox("Allow Glamourer Integration", ref enableGlamourer)) + if(ImGui.CollapsingHeader("Third-Party [Penumbra Based]", ImGuiTreeNodeFlags.DefaultOpen)) + { + var penumbraStatus = _penumbraService.CheckStatus(); + var penumbraUnavailable = penumbraStatus is IPCStatus.None or IPCStatus.NotInstalled or IPCStatus.VersionMismatch or IPCStatus.Error; + + if(penumbraUnavailable) { - _configurationService.Configuration.IPC.AllowGlamourerIntegration = enableGlamourer; - _configurationService.ApplyChange(); + using(ImRaii.PushColor(ImGuiCol.Text, UIConstants.GizmoRed)) + ImGui.Text("Please Install Penumbra"); } - using(ImRaii.Disabled(!enableGlamourer)) + using(ImRaii.Disabled(penumbraUnavailable)) { - ImGui.Text($"Glamourer Status: {(_glamourerService.IsGlamourerAvailable ? "Active" : "Inactive")}"); - ImGui.SameLine(); - if(ImBrio.FontIconButton("refresh_glamourer", FontAwesomeIcon.Sync, "Refresh Glamourer Status")) + bool enablePenumbra = _configurationService.Configuration.IPC.AllowPenumbraIntegration; + if(ImGui.Checkbox("Allow Penumbra Integration", ref enablePenumbra)) { - _glamourerService.RefreshGlamourerStatus(); + _configurationService.Configuration.IPC.AllowPenumbraIntegration = enablePenumbra; + _configurationService.ApplyChange(); + _penumbraService.CheckStatus(true); } - } - - bool enableMare = _configurationService.Configuration.IPC.AllowMareIntegration; - if(ImGui.Checkbox("Allow Mare Synchronos Integration", ref enableMare)) - { - _configurationService.Configuration.IPC.AllowMareIntegration = enableMare; - _configurationService.ApplyChange(); - } - using(ImRaii.Disabled(!enableMare)) - { - ImGui.Text($"Mare Synchronos Status: {(_mareService.IsMareAvailable ? "Active" : "Inactive")}"); + ImGui.Text($"Penumbra Status: {penumbraStatus}"); ImGui.SameLine(); - if(ImBrio.FontIconButton("refresh_mare", FontAwesomeIcon.Sync, "Refresh Mare Synchronos Status")) + if(ImBrio.FontIconButton("refresh_penumbra", FontAwesomeIcon.Sync, "Refresh Penumbra Status")) { - _mareService.RefreshMareStatus(); + _penumbraService.CheckStatus(true); } - } - } - } - private void DrawImportScene() - { + using(ImRaii.Disabled(!enablePenumbra)) + { + bool enableGlamourer = _configurationService.Configuration.IPC.AllowGlamourerIntegration; + if(ImGui.Checkbox("Allow Glamourer Integration", ref enableGlamourer)) + { + _configurationService.Configuration.IPC.AllowGlamourerIntegration = enableGlamourer; + _configurationService.ApplyChange(); + _glamourerService.CheckStatus(true); + } - if(ImGui.CollapsingHeader("General", ImGuiTreeNodeFlags.DefaultOpen)) - { - bool destroyActorsBeforeImport = _configurationService.Configuration.SceneDestoryActorsBeforeImport; - if(ImGui.Checkbox("Destroy Actors before Scene import", ref destroyActorsBeforeImport)) - { - _configurationService.Configuration.SceneDestoryActorsBeforeImport = destroyActorsBeforeImport; - _configurationService.ApplyChange(); - } - } + var glamourerStatus = _glamourerService.CheckStatus(); + using(ImRaii.Disabled(!enableGlamourer)) + { + ImGui.Text($"Glamourer Status: {glamourerStatus}"); + ImGui.SameLine(); + if(ImBrio.FontIconButton("refresh_glamourer", FontAwesomeIcon.Sync, "Refresh Glamourer Status")) + { + _glamourerService.CheckStatus(true); + } + } - if(ImGui.CollapsingHeader("Import", ImGuiTreeNodeFlags.DefaultOpen)) - { + bool enableMare = _configurationService.Configuration.IPC.AllowMareIntegration; - bool applyModelTransform = _configurationService.Configuration.Import.ApplyModelTransform; - if(ImGui.Checkbox("Apply Model Transform on Import", ref applyModelTransform)) - { - _configurationService.Configuration.Import.ApplyModelTransform = applyModelTransform; - _configurationService.ApplyChange(); - } + if(ImGui.Checkbox("Allow Mare Synchronos Integration", ref enableMare)) + { + _configurationService.Configuration.IPC.AllowMareIntegration = enableMare; + _configurationService.ApplyChange(); + _mareService.CheckStatus(true); + } - var positionTransformType = _configurationService.Configuration.Import.PositionTransformType; - ImGui.SetNextItemWidth(200); - using(var combo = ImRaii.Combo("Position", positionTransformType.ToString())) - { - if(combo.Success) - { - foreach(var poseImportTransformType in Enum.GetValues()) + var mareStatus = _mareService.CheckStatus(); + using(ImRaii.Disabled(!enableMare)) { - if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == positionTransformType)) + ImGui.Text($"Mare Synchronos Status: {mareStatus}"); + ImGui.SameLine(); + if(ImBrio.FontIconButton("refresh_mare", FontAwesomeIcon.Sync, "Refresh Mare Synchronos Status")) { - _configurationService.Configuration.Import.PositionTransformType = poseImportTransformType; - _configurationService.ApplyChange(); + _mareService.CheckStatus(true); } } + + _glamourerService.Disabled = !enablePenumbra; + _mareService.Disabled = _glamourerService.Disabled; } } + } + } - var rotationTransformType = _configurationService.Configuration.Import.RotationTransformType; - ImGui.SetNextItemWidth(200); - using(var combo = ImRaii.Combo("Rotation", rotationTransformType.ToString())) + private void DrawImportScene() + { + if(ImGui.CollapsingHeader("General", ImGuiTreeNodeFlags.DefaultOpen)) + { + var enabled = _configurationService.Configuration.AutoSave.AutoSaveSystemEnabled; + if(ImGui.Checkbox("Auto-Save Enabled", ref enabled)) + _configurationService.Configuration.AutoSave.AutoSaveSystemEnabled = enabled; + + using(ImRaii.Disabled(!enabled)) { - if(combo.Success) + var saveInterval = _configurationService.Configuration.AutoSave.AutoSaveInterval; + if(ImGui.SliderInt("Auto-Save Interval", ref saveInterval, 15, 500, "%d seconds")) { - foreach(var poseImportTransformType in Enum.GetValues()) - { - if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == rotationTransformType)) - { - _configurationService.Configuration.Import.RotationTransformType = poseImportTransformType; - _configurationService.ApplyChange(); - } - } + _configurationService.Configuration.AutoSave.AutoSaveInterval = saveInterval; } - } - var scaleTransformType = _configurationService.Configuration.Import.ScaleTransformType; - ImGui.SetNextItemWidth(200); - using(var combo = ImRaii.Combo("Scale", scaleTransformType.ToString())) - { - if(combo.Success) + var maxSaves = _configurationService.Configuration.AutoSave.MaxAutoSaves; + if(ImGui.SliderInt("Max Auto-Saves", ref maxSaves, 3, 30)) { - foreach(var poseImportTransformType in Enum.GetValues()) - { - if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == scaleTransformType)) - { - _configurationService.Configuration.Import.ScaleTransformType = poseImportTransformType; - _configurationService.ApplyChange(); - } - } + _configurationService.Configuration.AutoSave.MaxAutoSaves = maxSaves; } - } + //bool applyModelTransform = _configurationService.Configuration.Import.ApplyModelTransform; + //if(ImGui.Checkbox("Apply Model Transform on Import", ref applyModelTransform)) + //{ + // _configurationService.Configuration.Import.ApplyModelTransform = applyModelTransform; + // _configurationService.ApplyChange(); + //} + + //var positionTransformType = _configurationService.Configuration.Import.PositionTransformType; + //ImGui.SetNextItemWidth(200); + //using(var combo = ImRaii.Combo("Position", positionTransformType.ToString())) + //{ + // if(combo.Success) + // { + // foreach(var poseImportTransformType in Enum.GetValues()) + // { + // if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == positionTransformType)) + // { + // _configurationService.Configuration.Import.PositionTransformType = poseImportTransformType; + // _configurationService.ApplyChange(); + // } + // } + // } + //} + + //var rotationTransformType = _configurationService.Configuration.Import.RotationTransformType; + //ImGui.SetNextItemWidth(200); + //using(var combo = ImRaii.Combo("Rotation", rotationTransformType.ToString())) + //{ + // if(combo.Success) + // { + // foreach(var poseImportTransformType in Enum.GetValues()) + // { + // if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == rotationTransformType)) + // { + // _configurationService.Configuration.Import.RotationTransformType = poseImportTransformType; + // _configurationService.ApplyChange(); + // } + // } + // } + //} + + //var scaleTransformType = _configurationService.Configuration.Import.ScaleTransformType; + //ImGui.SetNextItemWidth(200); + //using(var combo = ImRaii.Combo("Scale", scaleTransformType.ToString())) + //{ + // if(combo.Success) + // { + // foreach(var poseImportTransformType in Enum.GetValues()) + // { + // if(ImGui.Selectable($"{poseImportTransformType}", poseImportTransformType == scaleTransformType)) + // { + // _configurationService.Configuration.Import.ScaleTransformType = poseImportTransformType; + // _configurationService.ApplyChange(); + // } + // } + // } + //} + } } } private void DrawBrioIPC() { - if(ImGui.CollapsingHeader("Brio", ImGuiTreeNodeFlags.DefaultOpen)) { bool enableBrioIpc = _configurationService.Configuration.IPC.EnableBrioIPC; @@ -363,15 +421,14 @@ private void DrawBrioIPC() ImGui.Text($"Brio IPC Status: {(_brioIPCService.IsIPCEnabled ? "Active" : "Inactive")}"); bool enableWebApi = _configurationService.Configuration.IPC.AllowWebAPI; - if(ImGui.Checkbox("Enable Web API", ref enableWebApi)) + if(ImGui.Checkbox("Enable Brio API", ref enableWebApi)) { _configurationService.Configuration.IPC.AllowWebAPI = enableWebApi; _configurationService.ApplyChange(); } - ImGui.Text($"Web API Status: {(_webService.IsRunning ? "Active" : "Inactive")}"); + ImGui.Text($"Brio API Status: {(_webService.IsRunning ? "Active" : "Inactive")}"); } - } private void DrawNPCAppearanceHack() @@ -601,7 +658,7 @@ private void DrawAdvancedTab() { ImGui.Checkbox("Enable [ Reset Settings to Default ] Button", ref resetSettings); - using(ImRaii.Disabled(resetSettings)) + using(ImRaii.Disabled(!resetSettings)) { if(ImGui.Button("Reset Settings to Default", new(170, 0))) { @@ -613,7 +670,6 @@ private void DrawAdvancedTab() } } - } private void DrawEnvironmentSection() @@ -709,7 +765,6 @@ private void DrawKeysTab() { ImGui.EndDisabled(); } - } } @@ -721,6 +776,5 @@ private void DrawKeyBind(KeyBindEvents evt) { _configurationService.ApplyChange(); } - } } diff --git a/Brio/UI/Windows/Specialized/ActionTimelineWindow.cs b/Brio/UI/Windows/Specialized/ActionTimelineWindow.cs index 920faeda..81f132ed 100644 --- a/Brio/UI/Windows/Specialized/ActionTimelineWindow.cs +++ b/Brio/UI/Windows/Specialized/ActionTimelineWindow.cs @@ -1,6 +1,7 @@ using Brio.Capabilities.Actor; using Brio.Config; using Brio.Entities; +using Brio.Entities.Actor; using Brio.Game.Cutscene; using Brio.Game.GPose; using Brio.Game.Posing; @@ -11,7 +12,7 @@ namespace Brio.UI.Windows.Specialized; -internal class ActionTimelineWindow : Window, IDisposable +public class ActionTimelineWindow : Window, IDisposable { private readonly ActionTimelineEditor _editor; private readonly EntityManager _entityManager; @@ -40,6 +41,11 @@ public ActionTimelineWindow(EntityManager entityManager, CutsceneManager cutscen public override bool DrawConditions() { + if(_entityManager.SelectedEntity is ActorEntity actor && actor.IsProp == true) + { + return false; + } + if(!_entityManager.SelectedHasCapability()) { return false; diff --git a/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs b/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs index 170423fe..531987e1 100644 --- a/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs +++ b/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs @@ -1,5 +1,6 @@ using Brio.Capabilities.Actor; using Brio.Entities; +using Brio.Entities.Actor; using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; using Brio.Game.GPose; @@ -14,7 +15,7 @@ namespace Brio.UI.Windows.Specialized; -internal class ActorAppearanceWindow : Window, IDisposable +public class ActorAppearanceWindow : Window, IDisposable { private readonly CustomizeEditor _customizeEditor; private readonly GearEditor _gearEditor; @@ -49,6 +50,11 @@ public ActorAppearanceWindow(EntityManager entityManager, GPoseService gPoseServ public override bool DrawConditions() { + if(_entityManager.SelectedEntity is ActorEntity actor && actor.IsProp == true) + { + return false; + } + if(!_entityManager.SelectedHasCapability()) { return false; diff --git a/Brio/UI/Windows/Specialized/CameraWindow.cs b/Brio/UI/Windows/Specialized/CameraWindow.cs index 0eefc26f..5a304890 100644 --- a/Brio/UI/Windows/Specialized/CameraWindow.cs +++ b/Brio/UI/Windows/Specialized/CameraWindow.cs @@ -1,34 +1,46 @@ using Brio.Capabilities.Camera; +using Brio.Capabilities.Core; using Brio.Entities; using Brio.Entities.Camera; +using Brio.Entities.Core; +using Brio.Game.Camera; using Brio.Game.GPose; using Brio.UI.Controls.Editors; using Dalamud.Interface.Windowing; +using ImGuiNET; using System; namespace Brio.UI.Windows.Specialized; -internal class CameraWindow : Window, IDisposable +public class CameraWindow : Window, IDisposable { private readonly EntityManager _entityManager; private readonly GPoseService _gPoseService; + private readonly VirtualCameraManager _virtualCameraService; - public CameraWindow(EntityManager entityManager, GPoseService gPoseService) : base("Brio - Camera###brio_camera_window") + public CameraWindow(EntityManager entityManager, GPoseService gPoseService, VirtualCameraManager virtualCameraService) : base($"{Brio.Name} - Camera###brio_camera_window") { Namespace = "brio_camera_namespace"; _entityManager = entityManager; _gPoseService = gPoseService; + _virtualCameraService = virtualCameraService; _gPoseService.OnGPoseStateChange += OnGPoseStateChange; } public override bool DrawConditions() { - if(!_entityManager.TryGetEntity("camera", out var camEntity)) + if(!_entityManager.TryGetEntity("cameras", out var cameraContainerEntity)) return false; - if(!camEntity.HasCapability()) + if(!cameraContainerEntity.TryGetCapability(out var cameraContainerCap)) + return false; + + if(!_entityManager.TryGetEntity(new CameraId(cameraContainerCap.CurrentCamera.CameraID), out var camEntity)) + return false; + + if(!camEntity.HasCapability()) return false; return base.DrawConditions(); @@ -36,13 +48,33 @@ public override bool DrawConditions() public override void Draw() { - if(_entityManager.TryGetEntity("camera", out var camEntity)) + if(_entityManager.TryGetEntity("cameras", out var cameraContainerEntity)) { - if(camEntity.TryGetCapability(out var camCap)) + if(cameraContainerEntity.TryGetCapability(out var cameraContainerCap)) { - CameraEditor.Draw("posing_camera_editor", camCap); + if(_entityManager.TryGetEntity(new CameraId(cameraContainerCap.CurrentCamera.CameraID), out var camEntity)) + { + if(camEntity.TryGetCapability(out var camBrioCap)) + { + ImGui.Text($" {camEntity.FriendlyName}"); + + ImGui.Separator(); + + if(camBrioCap.CameraEntity.CameraType == CameraType.Free) + { + CameraEditor.DrawFreeCam("camera_widget_editor", camBrioCap); + } + else if(camBrioCap.CameraEntity.CameraType == CameraType.Cutscene) + { + + } + else + { + CameraEditor.DrawBrioCam("camera_widget_editor", camBrioCap); + } + } + } } - return; } } diff --git a/Brio/UI/Windows/Specialized/KeyBindPromptWindow.cs b/Brio/UI/Windows/Specialized/KeyBindPromptWindow.cs index 4edf5d04..a51dc004 100644 --- a/Brio/UI/Windows/Specialized/KeyBindPromptWindow.cs +++ b/Brio/UI/Windows/Specialized/KeyBindPromptWindow.cs @@ -8,7 +8,7 @@ namespace Brio.UI.Windows.Specialized; -internal class KeyBindPromptWindow : Window, IDisposable +public class KeyBindPromptWindow : Window, IDisposable { private readonly InputService _inputService; private readonly ConfigurationService _configurationService; diff --git a/Brio/UI/Windows/Specialized/PosingGraphicalWindow.cs b/Brio/UI/Windows/Specialized/PosingGraphicalWindow.cs index 953f3af4..ba4f6d99 100644 --- a/Brio/UI/Windows/Specialized/PosingGraphicalWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingGraphicalWindow.cs @@ -3,6 +3,7 @@ using Brio.Config; using Brio.Core; using Brio.Entities; +using Brio.Entities.Actor; using Brio.Game.Actor.Appearance; using Brio.Game.Camera; using Brio.Game.GPose; @@ -23,7 +24,7 @@ namespace Brio.UI.Windows.Specialized; -internal class PosingGraphicalWindow : Window, IDisposable +public class PosingGraphicalWindow : Window, IDisposable { private const float RightPanelWidth = 250; @@ -62,6 +63,11 @@ public PosingGraphicalWindow(EntityManager entityManager, CameraService cameraSe public override bool DrawConditions() { + if(_entityManager.SelectedEntity is ActorEntity actor && actor.IsProp == true) + { + return false; + } + if(!_entityManager.SelectedHasCapability() || !_entityManager.SelectedHasCapability()) { return false; @@ -287,7 +293,6 @@ private static void DrawButtons(PosingCapability posing) _ => null ); - using(ImRaii.Disabled(parentBone == null)) { if(ImBrio.FontIconButton(FontAwesomeIcon.LevelUpAlt, new Vector2(buttonWidth, 0))) diff --git a/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs b/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs index 92471456..5c3e17c3 100644 --- a/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs @@ -15,7 +15,7 @@ namespace Brio.UI.Windows.Specialized; -internal class PosingOverlayToolbarWindow : Window +public class PosingOverlayToolbarWindow : Window { private readonly PosingOverlayWindow _overlayWindow; private readonly EntityManager _entityManager; @@ -38,6 +38,11 @@ public PosingOverlayToolbarWindow(PosingOverlayWindow overlayWindow, EntityManag _overlayTransformWindow = overlayTransformWindow; _posingService = posingService; _configurationService = configurationService; + + this.AllowClickthrough = false; + this.AllowPinning = false; + this.ForceMainWindow = true; + ShowCloseButton = false; } diff --git a/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs b/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs index 7b55a400..d111657c 100644 --- a/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs @@ -4,6 +4,7 @@ using Brio.Entities; using Brio.Game.Camera; using Brio.Game.GPose; +using Brio.Game.Input; using Brio.Game.Posing; using Brio.Input; using Brio.UI.Controls.Editors; @@ -20,7 +21,7 @@ namespace Brio.UI.Windows.Specialized; -internal class PosingOverlayWindow : Window, IDisposable +public class PosingOverlayWindow : Window, IDisposable { private readonly EntityManager _entityManager; @@ -28,6 +29,7 @@ internal class PosingOverlayWindow : Window, IDisposable private readonly ConfigurationService _configurationService; private readonly PosingService _posingService; private readonly GPoseService _gPoseService; + private readonly GameInputService _gameInputService; private List _selectingFrom = []; private Transform? _trackingTransform; @@ -36,8 +38,8 @@ internal class PosingOverlayWindow : Window, IDisposable private const int _gizmoId = 142857; private const string _boneSelectPopupName = "brio_bone_select_popup"; - public PosingOverlayWindow(EntityManager entityManager, CameraService cameraService, ConfigurationService configService, PosingService posingService, GPoseService gPoseService) - : base("##brio_posing_overlay_window", ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration, true) + public PosingOverlayWindow(EntityManager entityManager, CameraService cameraService, GameInputService gameInputService, ConfigurationService configService, PosingService posingService, GPoseService gPoseService) + : base("##brio_posing_overlay_window", ImGuiWindowFlags.AlwaysAutoResize, true) { Namespace = "brio_posing_overlay_namespace"; @@ -47,6 +49,7 @@ public PosingOverlayWindow(EntityManager entityManager, CameraService cameraServ _configurationService = configService; _posingService = posingService; _gPoseService = gPoseService; + _gameInputService = gameInputService; _gPoseService.OnGPoseStateChange += OnGPoseStateChanged; } @@ -56,15 +59,18 @@ public override void PreDraw() base.PreDraw(); ImGuiHelpers.SetNextWindowPosRelativeMainViewport(new Vector2(0, 0), ImGuiCond.Always); SizeCondition = ImGuiCond.Always; + var io = ImGui.GetIO(); - Size = io.DisplaySize * ImGui.GetFontSize(); + Size = io.DisplaySize; - Flags = ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration; + Flags = ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoCollapse; ImGuizmo.SetID(_gizmoId); - if(ImGuizmo.IsUsing() && _trackingTransform.HasValue) + if(_trackingTransform.HasValue) + { Flags &= ~ImGuiWindowFlags.NoInputs; + } } public override void Draw() @@ -89,6 +95,20 @@ private unsafe void DrawContent(PosingCapability posing) var uiState = new OverlayUIState(overlayConfig); var clickables = new List(); + if(posing.Selected.Value is not null and BonePoseInfoId) + { + _gameInputService.AllowEscape = false; + + if(InputService.IsKeyBindDown(KeyBindEvents.Poseing_Esc)) + { + posing.ClearSelection(); + } + } + else + { + _gameInputService.AllowEscape = true; + } + CalculateClickables(posing, uiState, overlayConfig, ref clickables); HandleSkeletonInput(posing, uiState, clickables); @@ -287,7 +307,6 @@ private void DrawPopup(PosingCapability posing) posing.Selected = _selectingFrom[selectedIndex].Item; } - } } } @@ -475,14 +494,14 @@ public void Dispose() private class OverlayUIState(PosingConfiguration configuration) { - public bool PopupOpen = ImGui.IsPopupOpen(_boneSelectPopupName); - public bool UsingGizmo = ImGuizmo.IsUsing(); - public bool HoveringGizmo = ImGuizmo.IsOver(); - public bool AnyActive = ImGui.IsAnyItemActive(); - public bool AnyWindowHovered = ImGui.IsWindowHovered(ImGuiHoveredFlags.AnyWindow); - public bool UserDisablingSkeleton = InputService.IsKeyBindDown(KeyBindEvents.Posing_DisableSkeleton); - public bool UserDisablingGizmo = InputService.IsKeyBindDown(KeyBindEvents.Posing_DisableGizmo); - public bool UserHidingOverlay = InputService.IsKeyBindDown(KeyBindEvents.Posing_HideOverlay); + public bool PopupOpen => ImGui.IsPopupOpen(_boneSelectPopupName); + public bool UsingGizmo => ImGuizmo.IsUsing(); + public bool HoveringGizmo => ImGuizmo.IsOver(); + public bool AnyActive => ImGui.IsAnyItemActive(); + public bool AnyWindowHovered => ImGui.IsWindowHovered(ImGuiHoveredFlags.AnyWindow); + public bool UserDisablingSkeleton => InputService.IsKeyBindDown(KeyBindEvents.Posing_DisableSkeleton); + public bool UserDisablingGizmo => InputService.IsKeyBindDown(KeyBindEvents.Posing_DisableGizmo); + public bool UserHidingOverlay => InputService.IsKeyBindDown(KeyBindEvents.Posing_HideOverlay); public bool AnythingBusy => PopupOpen || UsingGizmo || AnyActive || AnyWindowHovered; @@ -500,7 +519,7 @@ private class OverlayUIState(PosingConfiguration configuration) public bool GizmoEnabled => !PopupOpen && !AnyClickableClicked && !AnyClickableHovered && !UserDisablingGizmo; } - internal class ClickableItem + public class ClickableItem { public PosingSelectionType Item = null!; diff --git a/Brio/UI/Windows/Specialized/PosingTransformWindow.cs b/Brio/UI/Windows/Specialized/PosingTransformWindow.cs index ac9e39f9..8e6a5b25 100644 --- a/Brio/UI/Windows/Specialized/PosingTransformWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingTransformWindow.cs @@ -14,7 +14,7 @@ namespace Brio.UI.Windows.Specialized; -internal class PosingTransformWindow : Window +public class PosingTransformWindow : Window { private readonly EntityManager _entityManager; private readonly PosingService _posingService; diff --git a/Brio/UI/Windows/UpdateWindow.cs b/Brio/UI/Windows/UpdateWindow.cs index fffcbd42..c8183c6a 100644 --- a/Brio/UI/Windows/UpdateWindow.cs +++ b/Brio/UI/Windows/UpdateWindow.cs @@ -9,7 +9,7 @@ namespace Brio.UI.Windows; -internal class UpdateWindow : Window +public class UpdateWindow : Window { private readonly List _changelogTest = []; private const float _closeButtonWidth = 210f; @@ -64,7 +64,7 @@ public override void Draw() ImGui.SetCursorPosX(((ImBrio.GetRemainingWidth() - _closeButtonWidth) / 2)); - if(ImBrio.Button("Close", Dalamud.Interface.FontAwesomeIcon.SquareXmark, new Vector2(_closeButtonWidth, 0))) + if(ImBrio.Button("Close", Dalamud.Interface.FontAwesomeIcon.SquareXmark, new Vector2(_closeButtonWidth, 0), centerTest: true)) { this.IsOpen = false; } diff --git a/Brio/Web/ActorWebController.cs b/Brio/Web/ActorWebController.cs index 28cf2b6e..aaf42862 100644 --- a/Brio/Web/ActorWebController.cs +++ b/Brio/Web/ActorWebController.cs @@ -10,7 +10,7 @@ namespace Brio.Web; -internal class ActorWebController(IFramework framework, ActorSpawnService actorSpawnService, ActorRedrawService redrawService) : WebApiController +public class ActorWebController(IFramework framework, ActorSpawnService actorSpawnService, ActorRedrawService redrawService) : WebApiController { private readonly IFramework _framework = framework; private readonly ActorSpawnService _actorSpawnService = actorSpawnService; diff --git a/Brio/Web/WebService.cs b/Brio/Web/WebService.cs index 41a9de8c..71442c01 100644 --- a/Brio/Web/WebService.cs +++ b/Brio/Web/WebService.cs @@ -6,7 +6,7 @@ namespace Brio.Web; -internal class WebService : IDisposable +public class WebService : IDisposable { public bool IsRunning => _shouldBeRunning && _webServer != null && _webServer.State == WebServerState.Listening; diff --git a/Resources/Images/BrioIcon.png b/Resources/Images/BrioIcon.png index 70bb32d6..6e93d265 100644 Binary files a/Resources/Images/BrioIcon.png and b/Resources/Images/BrioIcon.png differ diff --git a/Resources/Templates/repo.tmpl b/Resources/Templates/repo.tmpl index 91de3091..4eb002b5 100644 --- a/Resources/Templates/repo.tmpl +++ b/Resources/Templates/repo.tmpl @@ -1,9 +1,9 @@ [ { - "Author": "Asgard, Minmoose and Contributors", + "Author": "Minmoose, Asgard and Contributors", "Name": "Brio", "Punchline": "Enhanced GPosing.", - "Description": "Control actors during GPose sessions.", + "Description": "Control & edit actors during GPose sessions.", "InternalName": "Brio", "AssemblyVersion": "{version}", "TestingAssemblyVersion": "{version}", @@ -18,7 +18,10 @@ "gpose", "brio", "posing", - "animation" + "pose", + "animation", + "xat", + "cutscene" ] } ]