diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index ef6c92af..974fe780 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -18,14 +18,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 + submodules: true - name: Install .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Download Dalamud run: | @@ -33,10 +34,10 @@ jobs: Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - name: Restore Dependencies - run: dotnet restore Brio.sln + run: dotnet restore Brio.slnx - name: Build Brio - run: dotnet build --no-restore Brio.sln /p:Configuration=Release /p:DebugType=None /p:DebugSymbols=false /p:Version=0.0.0.1 + run: dotnet build --no-restore Brio.slnx /p:Configuration=Release /p:DebugType=None /p:DebugSymbols=false /p:Version=0.0.0.1 - name: Zip Release uses: TheDoctor0/zip-release@0.6.0 diff --git a/.github/workflows/build-staging.yml b/.github/workflows/build-staging.yml index 9d29e124..07a56d37 100644 --- a/.github/workflows/build-staging.yml +++ b/.github/workflows/build-staging.yml @@ -18,12 +18,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - + submodules: true + - name: Install .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: dotnet-version: 10.0.x @@ -33,10 +34,10 @@ jobs: Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - name: Restore Dependencies - run: dotnet restore Brio.sln + run: dotnet restore Brio.slnx - name: Build Brio - run: dotnet build --no-restore Brio.sln /p:Configuration=Release /p:DebugType=None /p:DebugSymbols=false /p:Version=0.0.0.1 + run: dotnet build --no-restore Brio.slnx /p:Configuration=Release /p:DebugType=None /p:DebugSymbols=false /p:Version=0.0.0.1 - name: Zip Release uses: TheDoctor0/zip-release@0.6.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 39f07771..6e0df80f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -57,7 +57,7 @@ jobs: # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: recursive @@ -91,8 +91,8 @@ jobs: run: | Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - dotnet restore Brio.sln - dotnet build --no-restore Brio.sln /p:Configuration=Release /p:Version=0.0.0.1 + dotnet restore Brio.slnx + dotnet build --no-restore Brio.slnx /p:Configuration=Release /p:Version=0.0.0.1 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/release-brio-testing.yml b/.github/workflows/release-brio-testing.yml index f6f9d013..5bd08894 100644 --- a/.github/workflows/release-brio-testing.yml +++ b/.github/workflows/release-brio-testing.yml @@ -19,14 +19,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - + submodules: true + - name: Install .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Download Dalamud run: | @@ -34,10 +35,10 @@ jobs: Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - name: Restore Dependencies - run: dotnet restore Brio.sln + run: dotnet restore Brio.slnx - name: Build Brio - run: dotnet build Brio.sln --no-restore /p:Configuration=Release /p:Version=${{ github.event.inputs.version-testing }} + run: dotnet build Brio.slnx --no-restore /p:Configuration=Release /p:Version=${{ github.event.inputs.version-testing }} - name: Zip Release uses: TheDoctor0/zip-release@0.6.0 diff --git a/.github/workflows/release-brio.yml b/.github/workflows/release-brio.yml index 89684d5c..34d6b58c 100644 --- a/.github/workflows/release-brio.yml +++ b/.github/workflows/release-brio.yml @@ -16,14 +16,15 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - + submodules: true + - name: Install .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v5 with: - dotnet-version: 9.0.x + dotnet-version: 10.0.x - name: Download Dalamud run: | @@ -31,10 +32,10 @@ jobs: Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - name: Restore Dependencies - run: dotnet restore Brio.sln + run: dotnet restore Brio.slnx - name: Build Brio - run: dotnet build Brio.sln --no-restore /p:Configuration=Release /p:Version=${{ github.event.inputs.version }} + run: dotnet build Brio.slnx --no-restore /p:Configuration=Release /p:Version=${{ github.event.inputs.version }} - name: Zip Release uses: TheDoctor0/zip-release@0.6.0 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..fa8f7d09 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Libs/Brio API"] + path = Libs/Brio API + url = https://github.com/Etheirys/Brio.API.git diff --git a/Brio.sln b/Brio.sln deleted file mode 100644 index acfcb1d8..00000000 --- a/Brio.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.8.34316.72 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brio", "Brio\Brio.csproj", "{6E14631E-8223-427D-8A03-550EEE66B842}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6E14631E-8223-427D-8A03-550EEE66B842}.Debug|x64.ActiveCfg = Debug|x64 - {6E14631E-8223-427D-8A03-550EEE66B842}.Debug|x64.Build.0 = Debug|x64 - {6E14631E-8223-427D-8A03-550EEE66B842}.Release|x64.ActiveCfg = Release|x64 - {6E14631E-8223-427D-8A03-550EEE66B842}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5E2A0464-B31C-449B-B345-80D9E0F949A6} - EndGlobalSection -EndGlobal diff --git a/Brio/Brio.cs b/Brio/Brio.cs index 5f52265f..09dc8d50 100644 --- a/Brio/Brio.cs +++ b/Brio/Brio.cs @@ -14,13 +14,13 @@ using Brio.Game.World; using Brio.Input; using Brio.IPC; +using Brio.IPC.API; using Brio.Library; using Brio.Library.Sources; using Brio.MCDF.Game.FileCache; using Brio.MCDF.Game.Services; using Brio.Resources; using Brio.UI; -using Brio.UI.Controls.Stateless; using Brio.UI.Windows; using Brio.UI.Windows.Specialized; using Brio.Web; @@ -132,17 +132,24 @@ private static ServiceCollection SetupServices(DalamudServices dalamudServices) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + // API & Web + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + // IPC - serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - // Web - serviceCollection.AddSingleton(); - // Entity serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -204,7 +211,6 @@ private static ServiceCollection SetupServices(DalamudServices dalamudServices) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - // serviceCollection.AddSingleton(); return serviceCollection; } diff --git a/Brio/Brio.csproj b/Brio/Brio.csproj index 0d69d999..f1c67884 100644 --- a/Brio/Brio.csproj +++ b/Brio/Brio.csproj @@ -1,7 +1,7 @@ - + - net9.0-windows + net10.0-windows x64 enable preview @@ -32,6 +32,10 @@ + + + + Never diff --git a/Brio/Brio.json b/Brio/Brio.json index f6a96817..31299f4f 100644 --- a/Brio/Brio.json +++ b/Brio/Brio.json @@ -12,7 +12,7 @@ "animation" ], "DownloadCount": 646779, - "DalamudApiLevel": 13, + "DalamudApiLevel": 14, "LoadRequiredState": 0, "LoadSync": false, "CanUnloadAsync": false, diff --git a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs index 60fbc94a..7d9b0da5 100644 --- a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs +++ b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs @@ -1,4 +1,5 @@ -using Brio.Core; +using Brio.API; +using Brio.Core; using Brio.Entities; using Brio.Entities.Actor; using Brio.Entities.Core; @@ -103,14 +104,14 @@ public ActorAppearanceCapability(ActorEntity parent, CharacterHandlerService cha SetSelectedProfile(); } - public async Task LoadMCDF(string path) + public async Task LoadMCDF(string path) { try { if(_mCDFService.IsApplyingMCDF) { Brio.NotifyError("Another MCDF is loading, Please wait for it to finish."); - return; + return BrioApiResult.IsApplyingMCDF; } Entity.LoadingDescription = "Loading MCDF..."; @@ -125,27 +126,38 @@ public async Task LoadMCDF(string path) { Brio.Log.Warning(ex, "Exception while Loading MCDF"); Brio.NotifyError("MCDF Loading failed! Try again!"); + + return BrioApiResult.UnknownError; } finally { Entity.IsLoading = false; } + + if(HasMCDF) + return BrioApiResult.Success; + + return BrioApiResult.UnknownError; } - public async Task SaveMcdf(string path, string dis) + public async Task SaveMcdf(string path, string dis) { try { Entity.LoadingDescription = "Saving MCDF..."; Entity.IsLoading = true; await _mCDFService.SaveMCDF(path, dis, GameObject); + + return BrioApiResult.Success; } catch(Exception ex) { Brio.Log.Warning(ex, "Exception while Loading MCDF"); Brio.NotifyError("MCDF Export failed! Try again!"); + + return BrioApiResult.UnknownError; } - finally + finally { Entity.IsLoading = false; } diff --git a/Brio/Capabilities/Posing/PosingCapability.cs b/Brio/Capabilities/Posing/PosingCapability.cs index 5e51de09..d77b777f 100644 --- a/Brio/Capabilities/Posing/PosingCapability.cs +++ b/Brio/Capabilities/Posing/PosingCapability.cs @@ -228,7 +228,7 @@ internal void ImportPose_Internal(OneOf rawPoseFile, P if(asExpression == false) ModelPosing.ImportModelPose(poseFile, options, asScene, applyModelTransform); - + if(expressionPhase2) { var bone = SkeletonPosing.GetBone("j_kao", PoseInfoSlot.Character); diff --git a/Brio/Capabilities/World/FestivalCapability.cs b/Brio/Capabilities/World/FestivalCapability.cs index 29238a42..7691ee4d 100644 --- a/Brio/Capabilities/World/FestivalCapability.cs +++ b/Brio/Capabilities/World/FestivalCapability.cs @@ -3,6 +3,7 @@ using Brio.Game.World; using Brio.UI.Widgets.World; using System.Collections.Generic; +using System.Linq; using static Brio.Game.World.FestivalService; namespace Brio.Capabilities.World; @@ -14,7 +15,7 @@ public class FestivalCapability : Capability public bool CanModify => _festivalService.CanModify; public bool CanAdd => _festivalService.HasMoreSlots; public bool HasOverride => _festivalService.HasOverride; - public uint[] ActiveFestivals => _festivalService.EngineActiveFestivals; + public uint[] ActiveFestivals => [.. _festivalService.EngineActiveFestivals.Select(f => f.Id)]; public IReadOnlyDictionary AllFestivals => _festivalService.FestivalList; diff --git a/Brio/Config/EnvironmentConfiguration.cs b/Brio/Config/EnvironmentConfiguration.cs index 7d881c54..6251295a 100644 --- a/Brio/Config/EnvironmentConfiguration.cs +++ b/Brio/Config/EnvironmentConfiguration.cs @@ -1,4 +1,5 @@ namespace Brio.Config; + public class EnvironmentConfiguration { public bool ResetWeatherOnGPoseExit { get; set; } = true; diff --git a/Brio/Config/LibraryConfiguration.cs b/Brio/Config/LibraryConfiguration.cs index 853142c2..846dc8d4 100644 --- a/Brio/Config/LibraryConfiguration.cs +++ b/Brio/Config/LibraryConfiguration.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; namespace Brio.Config; + public class LibraryConfiguration { public float IconSize { get; set; } = 120; diff --git a/Brio/Core/ComponentSet.cs b/Brio/Core/ComponentSet.cs index 3434f105..8444f590 100644 --- a/Brio/Core/ComponentSet.cs +++ b/Brio/Core/ComponentSet.cs @@ -95,7 +95,7 @@ public void Remove(int address) } public void Clear() - { + { Array.Clear(Components, 0, Components.Length); AvailableIndices.Clear(); diff --git a/Brio/Core/DalamudServices.cs b/Brio/Core/DalamudServices.cs index 9d7c6c9e..c9466c4a 100644 --- a/Brio/Core/DalamudServices.cs +++ b/Brio/Core/DalamudServices.cs @@ -1,6 +1,4 @@ -using Dalamud.Game; -using Dalamud.Game.ClientState.Objects; -using Dalamud.IoC; +using Dalamud.IoC; using Dalamud.Plugin; using Dalamud.Plugin.Services; diff --git a/Brio/Core/MathHelpers.cs b/Brio/Core/MathHelpers.cs index 00e8fd22..dc61ffcc 100644 --- a/Brio/Core/MathHelpers.cs +++ b/Brio/Core/MathHelpers.cs @@ -10,17 +10,17 @@ public static class MathHelpers { public const float DegreesToRadians = MathF.PI / 180.0f; public const float RadiansToDegrees = 180.0f / MathF.PI; - + public const float Deg2Rad = MathF.PI * 2.0f / 360.0f; public const float Rad2Deg = 1.0f / Deg2Rad; - public static Quaternion ToEulerAngles(this Vector3 euler) + public static Quaternion ToEulerAngles(this Vector3 euler) => FromEulerRad(euler * Deg2Rad); public static Quaternion Normalize(Quaternion value) { var sqrMagnitude = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; - + var length = MathF.Sqrt(sqrMagnitude); if(length < float.Epsilon) return Quaternion.Identity; diff --git a/Brio/Core/NativeHelpers.cs b/Brio/Core/NativeHelpers.cs index ee2aed3c..d0bd170f 100644 --- a/Brio/Core/NativeHelpers.cs +++ b/Brio/Core/NativeHelpers.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; namespace Brio.Core; + public static class NativeHelpers { public static (nint Aligned, nint Unaligned) AllocateAlignedMemory(int sizeInBytes, int alignment) diff --git a/Brio/Entities/Debug/DebugEntity.cs b/Brio/Entities/Debug/DebugEntity.cs index cd242897..dcc531f2 100644 --- a/Brio/Entities/Debug/DebugEntity.cs +++ b/Brio/Entities/Debug/DebugEntity.cs @@ -13,7 +13,7 @@ public class DebugEntity(IServiceProvider provider) : Entity(FixedId, provider) public override string FriendlyName => "Debug"; public override FontAwesomeIcon Icon => FontAwesomeIcon.Bug; - public override EntityFlags Flags => EntityFlags.AllowOutsideGpose; + public override EntityFlags Flags => EntityFlags.AllowOutsideGpose; public override void OnAttached() { diff --git a/Brio/Entities/World/LightEntity.cs b/Brio/Entities/World/LightEntity.cs index 15961ad3..ba3671de 100644 --- a/Brio/Entities/World/LightEntity.cs +++ b/Brio/Entities/World/LightEntity.cs @@ -24,7 +24,7 @@ public override string FriendlyName { if(GameLight.IsGPoseLight) return $"GPose Light ({indexName})"; - + return $"Light ({indexName})"; } diff --git a/Brio/Files/AnamnesisCharaFile.cs b/Brio/Files/AnamnesisCharaFile.cs index 033bb337..737546f3 100644 --- a/Brio/Files/AnamnesisCharaFile.cs +++ b/Brio/Files/AnamnesisCharaFile.cs @@ -13,6 +13,7 @@ using System.Numerics; namespace Brio.Files; + public class AnamnesisCharaFileInfo(EntityManager entityManager, ConfigurationService configurationService) : AppliableActorFileInfoBase(entityManager, configurationService) { public override string Name => "Character File"; diff --git a/Brio/Files/ChangelogFile.cs b/Brio/Files/ChangelogFile.cs index b3514973..96f6e473 100644 --- a/Brio/Files/ChangelogFile.cs +++ b/Brio/Files/ChangelogFile.cs @@ -20,7 +20,7 @@ public class ChangelogEntry public string Tagline { get; set; } public string Date { get; set; } public bool? IsCurrent { get; set; } - public string Message { get; set; } + public string Message { get; set; } [YamlMember(DefaultValuesHandling = DefaultValuesHandling.Preserve)] public List Versions { get; set; } diff --git a/Brio/Game/Actor/ActionTimelineService.cs b/Brio/Game/Actor/ActionTimelineService.cs index 256d1e9d..6197469e 100644 --- a/Brio/Game/Actor/ActionTimelineService.cs +++ b/Brio/Game/Actor/ActionTimelineService.cs @@ -1,6 +1,5 @@ using Brio.Capabilities.Actor; using Brio.Entities; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.Character; diff --git a/Brio/Game/Actor/ActorAppearanceService.cs b/Brio/Game/Actor/ActorAppearanceService.cs index 65f808f1..89dfde95 100644 --- a/Brio/Game/Actor/ActorAppearanceService.cs +++ b/Brio/Game/Actor/ActorAppearanceService.cs @@ -6,7 +6,6 @@ using Brio.Game.Core; using Brio.Game.GPose; using Brio.IPC; -using Dalamud.Game; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Hooking; using Dalamud.Plugin.Services; diff --git a/Brio/Game/Actor/ActorLookAtService.cs b/Brio/Game/Actor/ActorLookAtService.cs index b159d4cc..181dcfa6 100644 --- a/Brio/Game/Actor/ActorLookAtService.cs +++ b/Brio/Game/Actor/ActorLookAtService.cs @@ -10,7 +10,6 @@ using Brio.Game.Actor.Extensions; using Brio.Game.Camera; using Brio.Game.GPose; -using Dalamud.Game; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Hooking; using Dalamud.Plugin.Services; diff --git a/Brio/Game/Actor/ActorSpawnService.cs b/Brio/Game/Actor/ActorSpawnService.cs index 37b0d8ee..c35ebe0d 100644 --- a/Brio/Game/Actor/ActorSpawnService.cs +++ b/Brio/Game/Actor/ActorSpawnService.cs @@ -10,6 +10,7 @@ using Brio.Game.Posing; using Brio.Game.Types; using Brio.IPC; +using Brio.IPC.API; using Brio.Resources; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; @@ -39,9 +40,11 @@ public class ActorSpawnService : IDisposable private readonly ActorLookAtService _actorLookAtService; private readonly CharacterHandlerService _characterHandlerService; + //private readonly BrioIPCProviders _brioIPCProviders; + private readonly Dictionary _createdIndexes = []; - public unsafe ActorSpawnService(ObjectMonitorService monitorService, CustomizePlusService customizePlusService, ActorLookAtService actorLookAtService, CharacterHandlerService characterHandlerService, + public unsafe ActorSpawnService(ObjectMonitorService monitorService, /* BrioIPCProviders brioIPCProviders,*/ CustomizePlusService customizePlusService, ActorLookAtService actorLookAtService, CharacterHandlerService characterHandlerService, ActorAppearanceService actorAppearanceService, PosingService posingService, GlamourerService glamourerService, EntityManager entityManager, IObjectTable objectTable, IClientState clientState, IFramework framework, GPoseService gPoseService, ActorRedrawService actorRedrawService, TargetService targetService) @@ -59,6 +62,8 @@ public unsafe ActorSpawnService(ObjectMonitorService monitorService, CustomizePl _actorAppearanceService = actorAppearanceService; _customizePlusService = customizePlusService; + //_brioIPCProviders = brioIPCProviders; + _actorLookAtService = actorLookAtService; _characterHandlerService = characterHandlerService; @@ -141,6 +146,7 @@ public unsafe bool CloneCharacter(ICharacter sourceCharacter, [MaybeNullWhen(fal _actorRedrawService.DrawWhenReady(companion); } + //_brioIPCProviders.ActorSpawned.Invoke(outCharacter); return true; } @@ -274,6 +280,8 @@ public void CleanObject(IGameObject? go, bool disposing) _actorLookAtService.RemoveObjectFromLook(go); _ = _characterHandlerService.Revert(go, disposing); + + //_brioIPCProviders.ActorDespawned.Invoke(go); } public void DestroyCompanion(ICharacter character) @@ -410,11 +418,11 @@ public unsafe void Dispose() public enum SpawnFlags { None = 0, - ReserveCompanionSlot = 1 << 0, - CopyPosition = 1 << 1, - IsProp = 1 << 2, - IsEffect = 1 << 3, - SetDefaultAppearance = 1 << 4, + ReserveCompanionSlot = 1 << 1, + CopyPosition = 1 << 2, + IsProp = 1 << 4, + IsEffect = 1 << 8, + SetDefaultAppearance = 1 << 16, Prop = IsProp | SetDefaultAppearance | CopyPosition, Effect = IsEffect | SetDefaultAppearance | CopyPosition, diff --git a/Brio/Game/Actor/ActorVFXService.cs b/Brio/Game/Actor/ActorVFXService.cs index 0a66a72c..1bcc9e4d 100644 --- a/Brio/Game/Actor/ActorVFXService.cs +++ b/Brio/Game/Actor/ActorVFXService.cs @@ -1,6 +1,6 @@ using Brio.Game.Actor.Extensions; -using Dalamud.Game; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Plugin.Services; using System; using NativeGameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; diff --git a/Brio/Game/Actor/Extensions/CharacterExtensions.cs b/Brio/Game/Actor/Extensions/CharacterExtensions.cs index e7e0be1b..396bb453 100644 --- a/Brio/Game/Actor/Extensions/CharacterExtensions.cs +++ b/Brio/Game/Actor/Extensions/CharacterExtensions.cs @@ -7,11 +7,11 @@ using global::Brio.Game.Types; using System; using System.Collections.Generic; -using StructsDrawObjectData = FFXIVClientStructs.FFXIV.Client.Game.Character.DrawObjectData; using StructsBattleCharacter = FFXIVClientStructs.FFXIV.Client.Game.Character.BattleChara; using StructsCharacter = FFXIVClientStructs.FFXIV.Client.Game.Character.Character; using StructsCharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase; using StructsDrawDataContainer = FFXIVClientStructs.FFXIV.Client.Game.Character.DrawDataContainer; +using StructsDrawObjectData = FFXIVClientStructs.FFXIV.Client.Game.Character.DrawObjectData; public static class CharacterExtensions { @@ -131,7 +131,7 @@ public static unsafe IReadOnlyList GetCharacterBases(this ICh charaBase = go.GetWeaponCharacterBase(ActorEquipSlot.Prop); if(charaBase != null) list.Add(new CharacterBaseInfo { CharacterBase = charaBase, Slot = PoseInfoSlot.Prop }); - + charaBase = go.GetOrnamentBase(); if(charaBase != null) list.Add(new CharacterBaseInfo() { CharacterBase = charaBase, Slot = PoseInfoSlot.Ornament }); diff --git a/Brio/Game/Camera/BrioCamera.cs b/Brio/Game/Camera/BrioCamera.cs index e1b5e397..16685549 100644 --- a/Brio/Game/Camera/BrioCamera.cs +++ b/Brio/Game/Camera/BrioCamera.cs @@ -31,7 +31,7 @@ public struct BrioCamera [FieldOffset(0x140)] public Vector2 Angle; [FieldOffset(0x160)] public Vector2 Pan; // Pan, Tilt [FieldOffset(0x170)] public float Roll; - + [FieldOffset(0x180)] public int Mode; // 0 = 1st Person. 1 = 3rd Person. 2+ = Restrictive camera control [FieldOffset(0x218)] public Vector2 Collide; @@ -89,7 +89,7 @@ private readonly Vector3 ConvertToVector3() Brio.Log.Debug($"rotY: {rotY * MathHelpers.RadiansToDegrees}"); - if (rotY == 0f) + if(rotY == 0f) { // apply offset for Y if no other Y rotation is applied Brio.Log.Debug("rotY returned 0, applying offset as rotation.Y"); @@ -103,7 +103,7 @@ private readonly Vector3 ConvertToVector3() return rotation; } - public readonly Vector3 RotationAsVector3 => new(Angle.X - Pan.X, -Angle.Y - Pan.Y, Roll); + public readonly Vector3 RotationAsVector3 => new(Angle.X - Pan.X, -Angle.Y - Pan.Y, 0); public readonly Quaternion CalculateDirectionAsQuaternion() => (new Vector3(-(Angle.Y + Pan.Y), ((Angle.X + MathF.PI) % MathF.Tau) - Pan.X, 0.0f) diff --git a/Brio/Game/Camera/CameraService.cs b/Brio/Game/Camera/CameraService.cs index e71875fe..0959987e 100644 --- a/Brio/Game/Camera/CameraService.cs +++ b/Brio/Game/Camera/CameraService.cs @@ -4,7 +4,6 @@ using Brio.Game.Cutscene; using Brio.Game.GPose; using Brio.Input; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.Control; diff --git a/Brio/Game/Camera/VirtualCamera.cs b/Brio/Game/Camera/VirtualCamera.cs index 13caf971..240c40d3 100644 --- a/Brio/Game/Camera/VirtualCamera.cs +++ b/Brio/Game/Camera/VirtualCamera.cs @@ -1,6 +1,5 @@ using FFXIVClientStructs.FFXIV.Client.Game.Control; using MessagePack; -using System; using System.Numerics; namespace Brio.Game.Camera; diff --git a/Brio/Game/Camera/VirtualCameraManager.cs b/Brio/Game/Camera/VirtualCameraManager.cs index 60366f62..923de57f 100644 --- a/Brio/Game/Camera/VirtualCameraManager.cs +++ b/Brio/Game/Camera/VirtualCameraManager.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Numerics; -using Brio.Config; +using Brio.Config; using Brio.Core; using Brio.Entities; using Brio.Entities.Camera; @@ -11,6 +8,9 @@ using Brio.Input; using Microsoft.Extensions.DependencyInjection; using Swan; +using System; +using System.Collections.Generic; +using System.Numerics; namespace Brio.Game.Camera; @@ -28,8 +28,8 @@ public class VirtualCameraManager : IDisposable private CameraEntity? DefaultCamera; private float _moveSpeed = 0.03f; - private float DefaultMovementSpeed => _configurationService.Configuration.Interface.DefaultFreeCameraMovementSpeed; - private float DefaultMouseSensitivity => _configurationService.Configuration.Interface.DefaultFreeCameraMouseSensitivity; + private float DefaultMovementSpeed => _configurationService.Configuration.Interface.DefaultFreeCameraMovementSpeed; + private float DefaultMouseSensitivity => _configurationService.Configuration.Interface.DefaultFreeCameraMouseSensitivity; public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPoseService, EntityManager entityManager, ConfigurationService configurationService) { @@ -48,7 +48,7 @@ public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPose private readonly Dictionary _createdCameras = []; public List SpawnedCameraEntities => [.. _createdCameras.Values]; - + public CameraEntity? SelectedCameraEntity; public (bool, int) CreateCamera(CameraType cameraType, bool selectCamera = true, bool targetNewInHierarch = true, VirtualCamera? virtualCamera = null) @@ -57,7 +57,7 @@ public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPose { var oldCam = CurrentCamera; CurrentCamera?.DeactivateCamera(); - + int cameraId = _nextCameraId + 1; var camEnt = ActivatorUtilities.CreateInstance(_serviceProvider, cameraId, cameraType); @@ -157,7 +157,7 @@ public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPose oldCameraEntity = oldCamEnt; } - if (oldCameraEntity == null) + if(oldCameraEntity == null) { Brio.Log.Error("No camera found to clone"); return (false, -1); diff --git a/Brio/Game/Core/ObjectMonitorService.cs b/Brio/Game/Core/ObjectMonitorService.cs index 294d74b7..7990b3ad 100644 --- a/Brio/Game/Core/ObjectMonitorService.cs +++ b/Brio/Game/Core/ObjectMonitorService.cs @@ -1,5 +1,4 @@ using Brio.Game.Actor.Interop; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; diff --git a/Brio/Game/Core/TargetService.cs b/Brio/Game/Core/TargetService.cs index e75ef8c5..e4a75c03 100644 --- a/Brio/Game/Core/TargetService.cs +++ b/Brio/Game/Core/TargetService.cs @@ -2,7 +2,6 @@ using Brio.Entities; using Brio.Entities.Actor; using Brio.Game.GPose; -using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; diff --git a/Brio/Game/Cutscene/CutsceneManager.cs b/Brio/Game/Cutscene/CutsceneManager.cs index 7e0bd440..99a33ce2 100644 --- a/Brio/Game/Cutscene/CutsceneManager.cs +++ b/Brio/Game/Cutscene/CutsceneManager.cs @@ -4,10 +4,8 @@ using Brio.Game.Actor.Extensions; using Brio.Game.Camera; using Brio.Game.GPose; -using Brio.Input; using Brio.UI; using Brio.UI.Controls.Editors; -using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using System; @@ -69,7 +67,8 @@ public void OnGPoseStateChange(bool newState) public void StartAllActors() { - _framework.RunOnFrameworkThread(() => { + _framework.RunOnFrameworkThread(() => + { foreach(var actor in _entityManager.TryGetAllActors()) { if(actor.TryGetCapability(out ActionTimelineCapability? atCap)) @@ -154,7 +153,7 @@ public void StopPlayback() { if(IsRunning is false || CameraPath is null) return null; - + if(DelayStart) { if(Stopwatch.ElapsedMilliseconds > DelayTime) diff --git a/Brio/Game/GPose/GPoseService.cs b/Brio/Game/GPose/GPoseService.cs index b78a4733..3099176e 100644 --- a/Brio/Game/GPose/GPoseService.cs +++ b/Brio/Game/GPose/GPoseService.cs @@ -1,5 +1,4 @@ using Brio.Config; -using Dalamud.Game; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Hooking; using Dalamud.Plugin.Services; diff --git a/Brio/Game/Input/GameInputService.cs b/Brio/Game/Input/GameInputService.cs index ee6b153e..35e3fb79 100644 --- a/Brio/Game/Input/GameInputService.cs +++ b/Brio/Game/Input/GameInputService.cs @@ -2,8 +2,6 @@ using Brio.Game.Camera; using Brio.Game.GPose; using Brio.Input; -using Dalamud.Game; -using Dalamud.Game.ClientState.Keys; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.UI; @@ -114,7 +112,7 @@ public unsafe void HandleInputDetour(IntPtr arg1, IntPtr arg2, IntPtr arg3, Mous keyboardFrame->KeyState[i] = 0; } } - + if(_configurationService.Configuration.InputManager.Enable) { if(_requireMod) diff --git a/Brio/Game/Posing/BoneFilter.cs b/Brio/Game/Posing/BoneFilter.cs index 2200577c..8a305dd1 100644 --- a/Brio/Game/Posing/BoneFilter.cs +++ b/Brio/Game/Posing/BoneFilter.cs @@ -61,7 +61,7 @@ public unsafe bool IsBoneValid(Bone bone, PoseInfoSlot slot, bool considerHidden if(slot is PoseInfoSlot.Ornament) return OrnamentsAllowed; - + if(slot is PoseInfoSlot.Prop) return PropAllowed; @@ -94,7 +94,7 @@ public unsafe bool IsBoneValid(Bone bone, PoseInfoSlot slot, bool considerHidden public bool OtherAllowed => _allowedCategories.Any((x) => x == "other"); - public bool OrnamentsAllowed => _allowedCategories.Any((x) => x == "ornament"); + public bool OrnamentsAllowed => _allowedCategories.Any((x) => x == "ornament"); public bool PropAllowed => _allowedCategories.Any((x) => x == "prop"); diff --git a/Brio/Game/Posing/IKService.cs b/Brio/Game/Posing/IKService.cs index c3933e37..dee7efca 100644 --- a/Brio/Game/Posing/IKService.cs +++ b/Brio/Game/Posing/IKService.cs @@ -1,6 +1,6 @@ using Brio.Core; using Brio.Game.Posing.Skeletons; -using Dalamud.Game; +using Dalamud.Plugin.Services; using FFXIVClientStructs.Havok.Animation.Rig; using FFXIVClientStructs.Havok.Common.Base.Container.Array; using FFXIVClientStructs.Havok.Common.Base.Math.Vector; @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; namespace Brio.Game.Posing; + public unsafe class IKService : IDisposable { delegate* unmanaged _ccdSolverCtr; diff --git a/Brio/Game/Posing/PhysicsService.cs b/Brio/Game/Posing/PhysicsService.cs index 97e0ee06..fc1fee71 100644 --- a/Brio/Game/Posing/PhysicsService.cs +++ b/Brio/Game/Posing/PhysicsService.cs @@ -10,7 +10,6 @@ // using Brio.Game.GPose; -using Dalamud.Game; using Dalamud.Memory; using Dalamud.Plugin.Services; using System; diff --git a/Brio/Game/Posing/SkeletonService.cs b/Brio/Game/Posing/SkeletonService.cs index 9d1c57b7..b920de1d 100644 --- a/Brio/Game/Posing/SkeletonService.cs +++ b/Brio/Game/Posing/SkeletonService.cs @@ -6,7 +6,6 @@ using Brio.Game.Core; using Brio.Game.GPose; using Brio.Game.Posing.Skeletons; -using Dalamud.Game; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Hooking; using Dalamud.Plugin.Services; @@ -67,7 +66,7 @@ public SkeletonService(EntityManager entityManager, ObjectMonitorService monitor _updateBonePhysicsHook = hooking.HookFromAddress(scanner.ScanText(updateBonePhysicsAddress), UpdateBonePhysicsDetour); _updateBonePhysicsHook.Enable(); - var finalizeSkeletonsHook = "40 53 55 57 41 55 48 83 EC 68"; // JMP in Framework.TaskRenderGraphicsRender + var finalizeSkeletonsHook = "40 53 55 57 41 55 48 83 EC ?? ?? 48 ?? ?? ?? ?? ?? ?? ?? 48"; // JMP in Framework.TaskRenderGraphicsRender _finalizeSkeletonsHook = hooking.HookFromAddress(scanner.ScanText(finalizeSkeletonsHook), FinalizeSkeletonsHook); _finalizeSkeletonsHook.Enable(); diff --git a/Brio/Game/Posing/Skeletons/Bone.cs b/Brio/Game/Posing/Skeletons/Bone.cs index d42718b5..8aabc716 100644 --- a/Brio/Game/Posing/Skeletons/Bone.cs +++ b/Brio/Game/Posing/Skeletons/Bone.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using Brio.Core; +using Brio.Core; using Brio.Resources; +using System; +using System.Collections.Generic; using static FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase; namespace Brio.Game.Posing.Skeletons; diff --git a/Brio/Game/World/FestivalService.cs b/Brio/Game/World/FestivalService.cs index 4bbde854..b2fc6a93 100644 --- a/Brio/Game/World/FestivalService.cs +++ b/Brio/Game/World/FestivalService.cs @@ -27,35 +27,34 @@ public unsafe class FestivalService : IDisposable private readonly IFramework _framework; private readonly GPoseService _gPoseService; private readonly ResourceProvider _resourceProvider; + private readonly IObjectTable _objectTable; - private readonly Queue _pendingChanges = new(); - private uint[]? _originalState; + private readonly Queue _pendingChanges = new(); + private GameMain.Festival[]? _originalState; - // TODO: Handle festival subid properly (I wonder want this meant (KEN)) - - public uint[] EngineActiveFestivals + public GameMain.Festival[] EngineActiveFestivals { get { - uint[] activeFestivals = new uint[4]; + GameMain.Festival[] activeFestivals = new GameMain.Festival[4]; var engineFestivals = GameMain.Instance()->ActiveFestivals; - for(int i = 0; i < MaxFestivals; i++) + for (int i = 0; i < MaxFestivals; i++) { - fixed(GameMain.Festival* festival = &engineFestivals[i]) - activeFestivals[i] = *((uint*)festival); + activeFestivals[i] = engineFestivals[i]; } return activeFestivals; } } - public FestivalService(IClientState clientState, IToastGui toastGui, GameDataProvider gameDataProvider, IFramework framework, GPoseService gPoseService, ResourceProvider resourceProvider) + public FestivalService(IClientState clientState, IObjectTable objects, IToastGui toastGui, GameDataProvider gameDataProvider, IFramework framework, GPoseService gPoseService, ResourceProvider resourceProvider) { _clientState = clientState; _toastGui = toastGui; _framework = framework; _gPoseService = gPoseService; _resourceProvider = resourceProvider; + _objectTable = objects; FestivalList = BuildFestivalList(gameDataProvider); @@ -80,15 +79,15 @@ public bool AddFestival(uint festival) if(!CheckFestivalRestrictions(festival)) return false; - var active = EngineActiveFestivals.ToArray(); + var active = EngineActiveFestivals; var copy = active.ToArray(); for(int i = 0; i < MaxFestivals; ++i) { - if(active[i] == 0) + if(active[i].Id == 0) { SnapshotFestivalsIfNeeded(); - copy[i] = festival; + copy[i] = new GameMain.Festival() { Id = festival, Phase = 1 }; _pendingChanges.Enqueue(copy); return true; } @@ -102,15 +101,15 @@ public bool RemoveFestival(uint festival) if(!CheckFestivalRestrictions(festival)) return false; - var active = EngineActiveFestivals.ToArray(); + var active = EngineActiveFestivals; var copy = active.ToArray(); - + for(int i = 0; i < MaxFestivals; ++i) { - if(active[i] == festival) + if(active[i].Id == festival) { SnapshotFestivalsIfNeeded(); - copy[i] = 0; + copy[i] = new GameMain.Festival() { Id = 0, Phase = 0 }; _pendingChanges.Enqueue(copy); return true; } @@ -136,15 +135,23 @@ public unsafe void ResetFestivals(bool tryThisFrame = false) } } - private void PublicApply(uint[] festivals, bool applyNow = true) + private void PublicApply(GameMain.Festival[] festivals, bool applyNow = true) { if(applyNow) { - GameMain.Instance()->SetActiveFestivals(festivals[0], festivals[1], festivals[2], festivals[3]); + GameMain.Instance()->SetActiveFestivals( + festivals[0].Id, festivals[0].Phase, + festivals[1].Id, festivals[1].Phase, + festivals[2].Id, festivals[2].Phase, + festivals[3].Id, festivals[3].Phase); } else { - GameMain.Instance()->QueueActiveFestivals(festivals[0], festivals[1], festivals[2], festivals[3]); + GameMain.Instance()->QueueActiveFestivals( + festivals[0].Id, festivals[0].Phase, + festivals[1].Id, festivals[1].Phase, + festivals[2].Id, festivals[2].Phase, + festivals[3].Id, festivals[3].Phase); } } @@ -161,7 +168,7 @@ private bool CheckFestivalRestrictions(uint festivalId, bool showError = true) { if(_clientState.TerritoryType == festival.AreaExclusion.TerritoryType) { - var localPlayer = _clientState.LocalPlayer; + var localPlayer = _objectTable.LocalPlayer; if(localPlayer == null) return false; diff --git a/Brio/Game/World/LightingService.cs b/Brio/Game/World/LightingService.cs index 7d53a746..d40a66ff 100644 --- a/Brio/Game/World/LightingService.cs +++ b/Brio/Game/World/LightingService.cs @@ -13,7 +13,6 @@ using Brio.Game.Camera; using Brio.Game.GPose; using Dalamud.Bindings.ImGuizmo; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.Event; diff --git a/Brio/Game/World/TimeService.cs b/Brio/Game/World/TimeService.cs index ba136bae..10cda66f 100644 --- a/Brio/Game/World/TimeService.cs +++ b/Brio/Game/World/TimeService.cs @@ -1,6 +1,5 @@ using Brio.Config; using Brio.Game.GPose; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.System.Framework; diff --git a/Brio/Game/World/WeatherService.cs b/Brio/Game/World/WeatherService.cs index 0b29277a..c8147ed2 100644 --- a/Brio/Game/World/WeatherService.cs +++ b/Brio/Game/World/WeatherService.cs @@ -3,7 +3,6 @@ using Brio.Game.GPose; using Brio.Game.Types; using Brio.Resources; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; diff --git a/Brio/Game/World/WorldRenderingService.cs b/Brio/Game/World/WorldRenderingService.cs index 018a388c..39a5e8cb 100644 --- a/Brio/Game/World/WorldRenderingService.cs +++ b/Brio/Game/World/WorldRenderingService.cs @@ -1,6 +1,5 @@ using Brio.Config; using Brio.Game.GPose; -using Dalamud.Game; using Dalamud.Hooking; using Dalamud.Plugin.Services; using System; diff --git a/Brio/IPC/API/ActorAPI.cs b/Brio/IPC/API/ActorAPI.cs new file mode 100644 index 00000000..5470dbfa --- /dev/null +++ b/Brio/IPC/API/ActorAPI.cs @@ -0,0 +1,113 @@ +using Brio.API; +using Brio.API.Interface; +using Brio.Capabilities.Actor; +using Brio.Entities; +using Brio.Game.Actor; +using Brio.Game.Actor.Extensions; +using Brio.Game.Core; +using Brio.Game.GPose; +using Brio.MCDF.Game.Services; +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using System.Linq; + +namespace Brio.IPC.API; + +public unsafe class ActorAPI(ActorSpawnService actorSpawnService, MCDFService mCDFService, IFramework framework, GPoseService gPoseService, EntityManager entityManager) : IActor +{ + private readonly MCDFService _mCDFService = mCDFService; + private readonly GPoseService _gPoseService = gPoseService; + private readonly ActorSpawnService _actorSpawnService = actorSpawnService; + private readonly EntityManager _entityManager = entityManager; + private readonly IFramework _framework = framework; + + public bool Despawn(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return false; + + return _actorSpawnService.DestroyObject(gameObject); + } + + public bool Exists(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return false; + + return _entityManager.EntityExists(gameObject.Native()); + } + + public IGameObject[]? GetAllActors() + { + if(_gPoseService.IsGPosing == false) return null; + + return _entityManager.TryGetAllActorsAsGameObject().ToArray(); + } + + public BrioApiResult LoadMCDF(IGameObject gameObject, string path) + { + if(_gPoseService.IsGPosing == false) return BrioApiResult.IsNotInGPose; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actorAppearanceCapability)) + { + return actorAppearanceCapability.LoadMCDF(path).Result; + } + } + + return BrioApiResult.UnknownError; + } + + public BrioApiResult SaveMCDF(IGameObject gameObject, string path, string description) + { + if(_gPoseService.IsGPosing == false) return BrioApiResult.IsNotInGPose; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actorAppearanceCapability)) + { + return actorAppearanceCapability.SaveMcdf(path, description).Result; + } + } + + return BrioApiResult.UnknownError; + } + + public IGameObject? Spawn(global::Brio.API.Enums.SpawnFlags spawnFlags, bool selectInHierarchy, bool spawnFrozen) + { + if(_gPoseService.IsGPosing == false) return null; + + var flags = (SpawnFlags)(ulong)spawnFlags; + + if(_actorSpawnService.CreateCharacter(out var character, flags, disableSpawnCompanion: !flags.HasFlag(SpawnFlags.ReserveCompanionSlot))) + { + if(selectInHierarchy) + { + _entityManager.SetSelectedEntity(character); + } + + if(spawnFrozen) + { + _framework.RunUntilSatisfied( + () => character.Native()->IsReadyToDraw(), + (__) => + { + if(_entityManager.TryGetEntity(character.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actionTimeline)) + { + actionTimeline.SetOverallSpeedOverride(0); + } + } + }, + 100, + dontStartFor: 2 + ); + } + + return character; + } + + return null; + } +} diff --git a/Brio/IPC/API/AnimationAPI.cs b/Brio/IPC/API/AnimationAPI.cs new file mode 100644 index 00000000..f914590f --- /dev/null +++ b/Brio/IPC/API/AnimationAPI.cs @@ -0,0 +1,82 @@ +using Brio.API.Interface; +using Brio.Capabilities.Actor; +using Brio.Entities; +using Brio.Game.Actor.Extensions; +using Brio.Game.GPose; +using Dalamud.Game.ClientState.Objects.Types; + +namespace Brio.IPC.API; + +public unsafe class AnimationAPI(GPoseService gPoseService, EntityManager entityManager) : IAnimation +{ + private readonly GPoseService _gPoseService = gPoseService; + private readonly EntityManager _entityManager = entityManager; + + public bool SetActorAnimation(IGameObject gameObject, string animationID, bool playOnLoad) + { + return false; + } + + public bool FreezeActor(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actionTimeline)) + { + actionTimeline.StopSpeedAndResetTimeline(); + return true; + } + } + + return false; + } + + public bool UnFreezeActor(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actionTimeline)) + { + actionTimeline.SetOverallSpeedOverride(1); + return true; + } + } + + return false; + } + + public float GetActorSpeed(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return 0; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actionTimeline)) + { + return actionTimeline.SpeedMultiplier; + } + } + + return 0; + } + + public bool SetActorSpeed(IGameObject gameObject, float speed) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var actionTimeline)) + { + actionTimeline.SetOverallSpeedOverride(speed); + return true; + } + } + + return false; + } +} diff --git a/Brio/IPC/API/BrioAPIService.cs b/Brio/IPC/API/BrioAPIService.cs new file mode 100644 index 00000000..9ecdcc19 --- /dev/null +++ b/Brio/IPC/API/BrioAPIService.cs @@ -0,0 +1,35 @@ +using Brio.API; +using Brio.API.Interface; +using Brio.Config; +using System; + +namespace Brio.IPC.API; + +public class BrioAPIService(ConfigurationService configurationService, StateAPI stateAPI, ActorAPI actorAPI, EnvironmentAPI environmentAPI, PosingAPI posingAPI, AnimationAPI animationAPI) : IBrioAPI, IDisposable +{ + public const int MajorVersion = 3; + public const int MinorVersion = 0; + + private readonly ConfigurationService _configurationService = configurationService; + + public bool IsIPCEnabled => _configurationService.Configuration.IPC.EnableBrioIPC; + + + public bool Valid { get; private set; } = true; + + + public IState State { get; } = stateAPI; + + public IActor Actor { get; } = actorAPI; + + public IEnvironment Environment { get; } = environmentAPI; + + public IPosing Posing { get; } = posingAPI; + + public IAnimation Animation { get; } = animationAPI; + + public void Dispose() + { + Valid = false; + } +} diff --git a/Brio/IPC/API/BrioIPCProviders.cs b/Brio/IPC/API/BrioIPCProviders.cs new file mode 100644 index 00000000..5c2b3e28 --- /dev/null +++ b/Brio/IPC/API/BrioIPCProviders.cs @@ -0,0 +1,77 @@ +using Brio.API; +using Brio.API.Helpers; +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Plugin; +using FFXIVClientStructs.FFXIV.Client.Game.Object; +using System; +using System.Collections.Generic; + +namespace Brio.IPC.API; + +public class BrioIPCProviders : IDisposable +{ + private readonly List _providers; + + private readonly BrioEventProvider _deinitializedProvider; + private readonly BrioEventProvider _initializedProvider; + + public readonly BrioEventProvider ActorDespawned; + public readonly BrioEventProvider ActorSpawned; + + + public BrioIPCProviders(IDalamudPluginInterface pi, BrioAPIService brioAPI) + { + _deinitializedProvider = Deinitialized.Provider(pi); + _initializedProvider = Initialized.Provider(pi); + + ActorDespawned = global::Brio.API.ActorDestroyed.Provider(pi); + ActorSpawned = global::Brio.API.ActorSpawned.Provider(pi); + + _providers = [ + ApiVersion.Provider(pi, brioAPI.State), + IsAvailable.Provider(pi, brioAPI.State), + IsValidGPoseSession.Provider(pi, brioAPI.State), + + SpawnActor.Provider(pi, brioAPI.Actor), + DespawnActor.Provider(pi, brioAPI.Actor), + ActorExists.Provider(pi, brioAPI.Actor), + GetAllActors.Provider(pi, brioAPI.Actor), + LoadMCDF.Provider(pi, brioAPI.Actor), + SaveMCDF.Provider(pi, brioAPI.Actor), + + SetActorSpeed.Provider(pi, brioAPI.Animation), + GetActorSpeed.Provider(pi, brioAPI.Animation), + FreezeActor.Provider(pi, brioAPI.Animation), + UnFreezeActor.Provider(pi, brioAPI.Animation), + + FreezePhysics.Provider(pi, brioAPI.Environment), + UnFreezePhysics.Provider(pi, brioAPI.Environment), + + SetModelTransform.Provider(pi, brioAPI.Posing), + GetModelTransform.Provider(pi, brioAPI.Posing), + ResetModelTransform.Provider(pi, brioAPI.Posing), + LoadPoseFromFile.Provider(pi, brioAPI.Posing), + LoadPoseFromJson.Provider(pi, brioAPI.Posing), + GetPoseAsJson.Provider(pi, brioAPI.Posing), + ResetPose.Provider(pi, brioAPI.Posing) + ]; + + _initializedProvider.Invoke(); + } + + public void Dispose() + { + foreach(var provider in _providers) + { + provider.Dispose(); + } + + + _initializedProvider.Dispose(); + _deinitializedProvider.Invoke(); + _deinitializedProvider.Dispose(); + + ActorDespawned.Dispose(); + ActorSpawned.Dispose(); + } +} diff --git a/Brio/IPC/API/EnvironmentAPI.cs b/Brio/IPC/API/EnvironmentAPI.cs new file mode 100644 index 00000000..652ad5f4 --- /dev/null +++ b/Brio/IPC/API/EnvironmentAPI.cs @@ -0,0 +1,25 @@ +using Brio.API.Interface; +using Brio.Game.GPose; +using Brio.Game.Posing; + +namespace Brio.IPC.API; + +public class EnvironmentAPI(GPoseService gPoseService, PhysicsService physicsService) : IEnvironment +{ + private readonly GPoseService _gPoseService = gPoseService; + private readonly PhysicsService _physicsService = physicsService; + + public bool FreezePhysics() + { + if(_gPoseService.IsGPosing == false) return false; + + return _physicsService.FreezeEnable(); + } + + public bool UnFreezePhysics() + { + if(_gPoseService.IsGPosing == false) return false; + + return _physicsService.FreezeRevert(); + } +} diff --git a/Brio/IPC/API/PosingAPI.cs b/Brio/IPC/API/PosingAPI.cs new file mode 100644 index 00000000..7ed09b11 --- /dev/null +++ b/Brio/IPC/API/PosingAPI.cs @@ -0,0 +1,166 @@ +using Brio.API.Interface; +using Brio.Capabilities.Posing; +using Brio.Core; +using Brio.Entities; +using Brio.Entities.Core; +using Brio.Files; +using Brio.Game.Actor.Extensions; +using Brio.Game.GPose; +using Dalamud.Game.ClientState.Objects.Types; +using System.Numerics; + +namespace Brio.IPC.API; + +public unsafe class PosingAPI(GPoseService gPoseService, EntityManager entityManager) : IPosing +{ + private readonly GPoseService _gPoseService = gPoseService; + private readonly EntityManager _entityManager = entityManager; + + public (Vector3?, Quaternion?, Vector3?) GetModelTransform(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return (null, null, null); + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var transformCapability)) + { + var transform = transformCapability.Transform; + + return (transform.Position, transform.Rotation, transform.Scale); + } + } + return (null, null, null); + } + + public string? GetPoseAsJson(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return null; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var posingCapability)) + { + var pose = posingCapability.ExportPose(); + + return JsonSerializer.Serialize(pose); + } + } + return null; + } + + public bool LoadPoseFromFile(IGameObject gameObject, string filename) + { + if(_gPoseService.IsGPosing == false || string.IsNullOrEmpty(filename)) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var posingCapability)) + { + posingCapability.ImportPose(filename); + + return true; + } + } + return false; + } + + public bool LoadPoseFromJson(IGameObject gameObject, bool isLegacyCMToolPose, string json) + { + if(_gPoseService.IsGPosing == false || string.IsNullOrEmpty(json)) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out Entity? entity) && entity is not null) + { + if(entity.TryGetCapability(out var posingCapability)) + { + try + { + if(isLegacyCMToolPose) + { + posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: true); + } + else + { + posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: true); + } + + return true; + } + catch + { + Brio.NotifyError("Invalid pose file loaded from IPC."); + } + } + } + + return false; + } + + public bool ResetModelTransform(IGameObject gameObject) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var transformCapability)) + { + transformCapability.ResetTransform(); + return true; + } + } + return false; + } + + public bool ResetPose(IGameObject gameObject, bool clearHistory) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var posingCapability)) + { + posingCapability.Reset(false, false, clearHistory); + + return true; + } + } + + return false; + } + + public bool SetModelTransform(IGameObject gameObject, Vector3? position, Quaternion? rotation, Vector3? scale, bool relativeMode) + { + if(_gPoseService.IsGPosing == false) return false; + + if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) + { + if(entity.TryGetCapability(out var transformCapability)) + { + var transform = transformCapability.Transform; + + if(relativeMode) + { + if(position.HasValue) + transform.Position += position.Value; + if(rotation.HasValue) + transform.Rotation += rotation.Value; + if(scale.HasValue) + transform.Scale += scale.Value; + } + else + { + if(position.HasValue) + transform.Position = position.Value; + if(rotation.HasValue) + transform.Rotation = rotation.Value; + if(scale.HasValue) + transform.Scale = scale.Value; + } + + transformCapability.Transform = transform; + + return true; + } + } + return false; + } +} diff --git a/Brio/IPC/API/StateAPI.cs b/Brio/IPC/API/StateAPI.cs new file mode 100644 index 00000000..beeb5065 --- /dev/null +++ b/Brio/IPC/API/StateAPI.cs @@ -0,0 +1,16 @@ +using Brio.API.Interface; +using Brio.Game.GPose; + +namespace Brio.IPC.API; + +public class StateAPI(GPoseService gPoseService) : IState +{ + + private readonly GPoseService _gPoseService = gPoseService; + + public (int Breaking, int Feature) ApiVersion => (BrioAPIService.MajorVersion, BrioAPIService.MinorVersion); + + public bool IsAvailable => true; + + public bool IsValidGPoseSession => _gPoseService.IsGPosing; +} diff --git a/Brio/IPC/BrioIPCService.cs b/Brio/IPC/BrioIPCService.cs deleted file mode 100644 index 0f726cd2..00000000 --- a/Brio/IPC/BrioIPCService.cs +++ /dev/null @@ -1,571 +0,0 @@ -using Brio.Capabilities.Actor; -using Brio.Capabilities.Posing; -using Brio.Config; -using Brio.Core; -using Brio.Entities; -using Brio.Entities.Core; -using Brio.Files; -using Brio.Game.Actor; -using Brio.Game.Actor.Extensions; -using Brio.Game.Core; -using Brio.Game.GPose; -using Brio.Game.Posing; -using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Plugin; -using Dalamud.Plugin.Ipc; -using Dalamud.Plugin.Services; -using System; -using System.Linq; -using System.Numerics; -using System.Threading.Tasks; - -namespace Brio.IPC; -public class BrioIPCService : IDisposable -{ - public static readonly (int, int) CurrentApiVersion = (2, 0); - - public bool IsIPCEnabled { get; private set; } = false; - - // - - public const string ApiVersion_IPCName = "Brio.ApiVersion"; - private ICallGateProvider<(int, int)>? API_Version_IPC; - - - public const string Actor_Spawn_IPCName = "Brio.Actor.Spawn"; - private ICallGateProvider? Actor_Spawn_IPC; - - public const string Actor_SpawnAsync_IPCName = "Brio.Actor.SpawnAsync"; - private ICallGateProvider>? Actor_SpawnAsync_IPC; - - public const string Actor_SpawnExAsync_IPCName = "Brio.Actor.SpawnExAsync"; - private ICallGateProvider>? Actor_SpawnExAsync_IPC; - - public const string Actor_SpawnEx_IPCName = "Brio.Actor.SpawnEx"; - private ICallGateProvider? Actor_SpawnEx_IPC; - - - public const string Actor_Despawn_IPCName = "Brio.Actor.Despawn"; - private ICallGateProvider? Actor_DespawnActor_IPC; - - - public const string Actor_SetModelTransform_IPCName = "Brio.Actor.SetModelTransform"; - private ICallGateProvider? Actor_SetModelTransform_IPC; - - public const string Actor_GetModelTransform_IPCName = "Brio.Actor.GetModelTransform"; - private ICallGateProvider? Actor_GetModelTransform_IPC; - - public const string Actor_ResetModelTransform_IPCName = "Brio.Actor.ResetModelTransform"; - private ICallGateProvider? Actor_ResetModelTransform_IPC; - - - public const string Actor_PoseLoadFromFile_IPCName = "Brio.Actor.Pose.LoadFromFile"; - private ICallGateProvider? Actor_Pose_LoadFromFile_IPC; - - public const string Actor_PoseLoadFromJson_IPCName = "Brio.Actor.Pose.LoadFromJson"; - private ICallGateProvider? Actor_Pose_LoadFromJson_IPC; - - public const string Actor_PoseGetAsJson_IPCName = "Brio.Actor.Pose.GetPoseAsJson"; - private ICallGateProvider? Actor_Pose_GetFromJson_IPC; - - public const string Actor_Pose_Reset_IPCName = "Brio.Actor.Pose.Reset"; - private ICallGateProvider? Actor_Pose_Reset_IPC; - - public const string Actor_Exists_IPCName = "Brio.Actor.Exists"; - private ICallGateProvider? Actor_Exists_IPC; - - public const string Actor_GetAll_IPCName = "Brio.Actor.GetAll"; - private ICallGateProvider? Actor_GetAll_IPC; - - - public const string Actor_SetSpeed_IPCName = "Brio.Actor.SetSpeed"; - private ICallGateProvider? Actor_SetSpeed_IPC; - - public const string Actor_GetSpeed_IPCName = "Brio.Actor.GetSpeed"; - private ICallGateProvider? Actor_GetSpeed_IPC; - - public const string Actor_Freeze_IPCName = "Brio.Actor.Freeze"; - private ICallGateProvider? Actor_Freeze_IPC; - - public const string Actor_UnFreeze_IPCName = "Brio.Actor.UnFreeze"; - private ICallGateProvider? Actor_UnFreeze_IPC; - - public const string FreezePhysics_IPCName = "Brio.FreezePhysics"; - private ICallGateProvider? FreezePhysics_IPC; - - public const string UnFreezePhysics_IPCName = "Brio.UnFreezePhysics"; - private ICallGateProvider? UnFreezePhysics_IPC; - - // - - private readonly ActorSpawnService _actorSpawnService; - private readonly GPoseService _gPoseService; - private readonly ConfigurationService _configurationService; - private readonly EntityManager _entityManager; - private readonly IDalamudPluginInterface _pluginInterface; - private readonly IFramework _framework; - private readonly PhysicsService _physicsService; - - public BrioIPCService(ActorSpawnService actorSpawnService, GPoseService gPoseService, ConfigurationService configurationService, EntityManager entityManager, - IDalamudPluginInterface pluginInterface, IFramework framework, PhysicsService physicsService) - { - _actorSpawnService = actorSpawnService; - _gPoseService = gPoseService; - _configurationService = configurationService; - _entityManager = entityManager; - _pluginInterface = pluginInterface; - _framework = framework; - _physicsService = physicsService; - - if(_configurationService.Configuration.IPC.EnableBrioIPC) - CreateIPC(); - - _configurationService.OnConfigurationChanged += OnConfigurationChanged; - } - private void OnConfigurationChanged() - { - if(IsIPCEnabled != _configurationService.Configuration.IPC.EnableBrioIPC) - { - if(_configurationService.Configuration.IPC.EnableBrioIPC) - CreateIPC(); - else - DisposeIPC(); - } - } - - private void CreateIPC() - { - API_Version_IPC = _pluginInterface.GetIpcProvider<(int, int)>(ApiVersion_IPCName); - API_Version_IPC.RegisterFunc(ApiVersion_Impl); - - - Actor_Spawn_IPC = _pluginInterface.GetIpcProvider(Actor_Spawn_IPCName); - Actor_Spawn_IPC.RegisterFunc(SpawnActor); - - Actor_SpawnAsync_IPC = _pluginInterface.GetIpcProvider>(Actor_SpawnAsync_IPCName); - Actor_SpawnAsync_IPC.RegisterFunc(SpawnActorAsync_Impl); - - Actor_SpawnExAsync_IPC = _pluginInterface.GetIpcProvider>(Actor_SpawnExAsync_IPCName); - Actor_SpawnExAsync_IPC.RegisterFunc(SpawnExAsync_Impl); - - Actor_SpawnEx_IPC = _pluginInterface.GetIpcProvider(Actor_SpawnEx_IPCName); - Actor_SpawnEx_IPC.RegisterFunc(SpawnEx); - - Actor_DespawnActor_IPC = _pluginInterface.GetIpcProvider(Actor_Despawn_IPCName); - Actor_DespawnActor_IPC.RegisterFunc(DespawnActor); - - Actor_SetModelTransform_IPC = _pluginInterface.GetIpcProvider(Actor_SetModelTransform_IPCName); - Actor_SetModelTransform_IPC.RegisterFunc(ActorSetModelTransform_Impl); - - Actor_GetModelTransform_IPC = _pluginInterface.GetIpcProvider(Actor_GetModelTransform_IPCName); - Actor_GetModelTransform_IPC.RegisterFunc(ActorGetModelTransform_Impl); - - Actor_ResetModelTransform_IPC = _pluginInterface.GetIpcProvider(Actor_ResetModelTransform_IPCName); - Actor_ResetModelTransform_IPC.RegisterFunc(ActorResetModelTransform_Impl); - - Actor_Pose_LoadFromFile_IPC = _pluginInterface.GetIpcProvider(Actor_PoseLoadFromFile_IPCName); - Actor_Pose_LoadFromFile_IPC.RegisterFunc(LoadFromFile_Impl); - - Actor_Pose_LoadFromJson_IPC = _pluginInterface.GetIpcProvider(Actor_PoseLoadFromJson_IPCName); - Actor_Pose_LoadFromJson_IPC.RegisterFunc(LoadFromJson_Impl); - - Actor_Pose_GetFromJson_IPC = _pluginInterface.GetIpcProvider(Actor_PoseGetAsJson_IPCName); - Actor_Pose_GetFromJson_IPC.RegisterFunc(GetPoseAsJson_Impl); - - Actor_Pose_Reset_IPC = _pluginInterface.GetIpcProvider(Actor_Pose_Reset_IPCName); - Actor_Pose_Reset_IPC.RegisterFunc(ResetPose_Impl); - - Actor_Exists_IPC = _pluginInterface.GetIpcProvider(Actor_Exists_IPCName); - Actor_Exists_IPC.RegisterFunc(ActorExists_Impl); - - Actor_GetAll_IPC = _pluginInterface.GetIpcProvider(Actor_GetAll_IPCName); - Actor_GetAll_IPC.RegisterFunc(ActorGetAll_Impl); - - Actor_SetSpeed_IPC = _pluginInterface.GetIpcProvider(Actor_SetSpeed_IPCName); - Actor_SetSpeed_IPC.RegisterFunc(SetActorSpeed_Impl); - - Actor_GetSpeed_IPC = _pluginInterface.GetIpcProvider(Actor_GetSpeed_IPCName); - Actor_GetSpeed_IPC.RegisterFunc(GetActorSpeed_Impl); - - Actor_Freeze_IPC = _pluginInterface.GetIpcProvider(Actor_Freeze_IPCName); - Actor_Freeze_IPC.RegisterFunc(FreezActor_Impl); - - Actor_UnFreeze_IPC = _pluginInterface.GetIpcProvider(Actor_UnFreeze_IPCName); - Actor_UnFreeze_IPC.RegisterFunc(UnFreezActor_Impl); - - FreezePhysics_IPC = _pluginInterface.GetIpcProvider(FreezePhysics_IPCName); - FreezePhysics_IPC.RegisterFunc(FreezePhysics_Impl); - - UnFreezePhysics_IPC = _pluginInterface.GetIpcProvider(UnFreezePhysics_IPCName); - UnFreezePhysics_IPC.RegisterFunc(UnFreezePhysics_Impl); - - IsIPCEnabled = true; - } - private void DisposeIPC() - { - API_Version_IPC?.UnregisterFunc(); - - Actor_Spawn_IPC?.UnregisterFunc(); - Actor_SpawnAsync_IPC?.UnregisterFunc(); - Actor_SpawnExAsync_IPC?.UnregisterFunc(); - - Actor_DespawnActor_IPC?.UnregisterFunc(); - - Actor_SetModelTransform_IPC?.UnregisterFunc(); - Actor_GetModelTransform_IPC?.UnregisterFunc(); - - Actor_Pose_LoadFromFile_IPC?.UnregisterFunc(); - Actor_Pose_LoadFromJson_IPC?.UnregisterFunc(); - Actor_Pose_GetFromJson_IPC?.UnregisterFunc(); - - Actor_Freeze_IPC?.UnregisterFunc(); - Actor_GetSpeed_IPC?.UnregisterFunc(); - Actor_GetAll_IPC?.UnregisterFunc(); - Actor_SetSpeed_IPC?.UnregisterFunc(); - - Actor_Exists_IPC?.UnregisterFunc(); - - Actor_Pose_Reset_IPC?.UnregisterFunc(); - - Actor_UnFreeze_IPC?.UnregisterFunc(); - FreezePhysics_IPC?.UnregisterFunc(); - UnFreezePhysics_IPC?.UnregisterFunc(); - - API_Version_IPC = null; - - Actor_Spawn_IPC = null; - Actor_SpawnAsync_IPC = null; - Actor_SpawnExAsync_IPC = null; - - Actor_DespawnActor_IPC = null; - - Actor_SetModelTransform_IPC = null; - Actor_GetModelTransform_IPC = null; - - Actor_Pose_LoadFromFile_IPC = null; - Actor_Pose_LoadFromJson_IPC = null; - Actor_Pose_GetFromJson_IPC = null; - - Actor_Freeze_IPC = null; - Actor_GetSpeed_IPC = null; - Actor_GetAll_IPC = null; - Actor_SetSpeed_IPC = null; - - Actor_Exists_IPC = null; - - Actor_Pose_Reset_IPC = null; - - Actor_UnFreeze_IPC = null; - FreezePhysics_IPC = null; - UnFreezePhysics_IPC = null; - - IsIPCEnabled = false; - } - - // - - private (int, int) ApiVersion_Impl() => CurrentApiVersion; - - private Task SpawnActorAsync_Impl() => _framework.RunOnTick(SpawnActor); - private IGameObject? SpawnActor() - { - if(_gPoseService.IsGPosing == false) return null; - - if(_actorSpawnService.CreateCharacter(out var character, SpawnFlags.Default, disableSpawnCompanion: true)) - return character; - - return null; - } - - private async Task SpawnExAsync_Impl(bool spawnCompanion, bool selectInHierarchy, bool spawnFrozen) => await _framework.RunOnTick(() => SpawnEx(spawnCompanion, selectInHierarchy, spawnFrozen)); - private IGameObject? SpawnEx(bool spawnCompanionSlot, bool selectInHierarchy, bool spawnFrozen) - { - if(_gPoseService.IsGPosing == false) return null; - - SpawnFlags flags = SpawnFlags.Default; - if(spawnCompanionSlot) - { - flags |= SpawnFlags.ReserveCompanionSlot; - } - - if(_actorSpawnService.CreateCharacter(out var character, flags, disableSpawnCompanion: !spawnCompanionSlot)) - { - if(selectInHierarchy) - { - _entityManager.SetSelectedEntity(character); - } - - if(spawnFrozen) - { - unsafe - { - _framework.RunUntilSatisfied( - () => character.Native()->IsReadyToDraw(), - (__) => - { - if(_entityManager.TryGetEntity(character.Native(), out var entity)) - { - if(entity.TryGetCapability(out var actionTimeline)) - { - actionTimeline.SetOverallSpeedOverride(0); - } - } - }, - 100, - dontStartFor: 2 - ); - } - } - - return character; - } - - return null; - } - - private bool DespawnActor(IGameObject gameObject) - { - if(_gPoseService.IsGPosing == false) return false; - - return _actorSpawnService.DestroyObject(gameObject); - } - - private unsafe bool ActorSetModelTransform_Impl(IGameObject gameObject, Vector3? position, Quaternion? rotation, Vector3? scale, bool additiveMode) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var transformCapability)) - { - var transform = transformCapability.Transform; - - if(additiveMode) - { - if(position.HasValue) - transform.Position += position.Value; - if(rotation.HasValue) - transform.Rotation += rotation.Value; - if(scale.HasValue) - transform.Scale += scale.Value; - } - else - { - if(position.HasValue) - transform.Position = position.Value; - if(rotation.HasValue) - transform.Rotation = rotation.Value; - if(scale.HasValue) - transform.Scale = scale.Value; - } - - transformCapability.Transform = transform; - - return true; - } - } - return false; - } - private unsafe (Vector3?, Quaternion?, Vector3?) ActorGetModelTransform_Impl(IGameObject gameObject) - { - if(_gPoseService.IsGPosing == false) return (null, null, null); - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var transformCapability)) - { - var transform = transformCapability.Transform; - - return (transform.Position, transform.Rotation, transform.Scale); - } - } - return (null, null, null); - } - private unsafe bool ActorResetModelTransform_Impl(IGameObject gameObject) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var transformCapability)) - { - transformCapability.ResetTransform(); - return true; - } - } - return false; - } - - private unsafe bool LoadFromFile_Impl(IGameObject gameObject, string fileURI) - { - if(_gPoseService.IsGPosing == false || string.IsNullOrEmpty(fileURI)) return false; - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var posingCapability)) - { - posingCapability.ImportPose(fileURI); - - return true; - } - } - return false; - } - private unsafe bool LoadFromJson_Impl(IGameObject gameObject, string json, bool isLegacyCMToolPose) - { - if(_gPoseService.IsGPosing == false || string.IsNullOrEmpty(json)) return false; - - if(_entityManager.TryGetEntity(gameObject.Native(), out Entity? entity) && entity is not null) - { - if(entity.TryGetCapability(out var posingCapability)) - { - try - { - if(isLegacyCMToolPose) - { - posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: true); - } - else - { - posingCapability.ImportPose(JsonSerializer.Deserialize(json), null, asIPCpose: true); - } - - return true; - } - catch - { - Brio.NotifyError("Invalid pose file loaded from IPC."); - } - } - } - - return false; - } - private unsafe string? GetPoseAsJson_Impl(IGameObject gameObject) - { - if(_gPoseService.IsGPosing == false) return null; - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var posingCapability)) - { - var pose = posingCapability.ExportPose(); - - return JsonSerializer.Serialize(pose); - } - } - return null; - } - - private unsafe bool ResetPose_Impl(IGameObject gameObject, bool clearRedoHistory) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(gameObject.Native(), out var entity)) - { - if(entity.TryGetCapability(out var posingCapability)) - { - posingCapability.Reset(false, false, clearRedoHistory); - - return true; - } - } - - return false; - } - - private unsafe bool ActorExists_Impl(IGameObject gameObject) - { - if(_gPoseService.IsGPosing == false) return false; - - return _entityManager.EntityExists(gameObject.Native()); - } - - private unsafe IGameObject[]? ActorGetAll_Impl() - { - if(_gPoseService.IsGPosing == false) return null; - - return _entityManager.TryGetAllActorsAsGameObject().ToArray(); - } - - private unsafe bool SetActorSpeed_Impl(IGameObject actor, float speed) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(actor.Native(), out var entity)) - { - if(entity.TryGetCapability(out var actionTimeline)) - { - actionTimeline.SetOverallSpeedOverride(speed); - return true; - } - } - - return false; - } - private unsafe float GetActorSpeed_Impl(IGameObject actor) - { - if(_gPoseService.IsGPosing == false) return 0; - - if(_entityManager.TryGetEntity(actor.Native(), out var entity)) - { - if(entity.TryGetCapability(out var actionTimeline)) - { - return actionTimeline.SpeedMultiplier; - } - } - - return 0; - } - - private unsafe bool FreezActor_Impl(IGameObject actor) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(actor.Native(), out var entity)) - { - if(entity.TryGetCapability(out var actionTimeline)) - { - actionTimeline.StopSpeedAndResetTimeline(); - return true; - } - } - - return false; - } - private unsafe bool UnFreezActor_Impl(IGameObject actor) - { - if(_gPoseService.IsGPosing == false) return false; - - if(_entityManager.TryGetEntity(actor.Native(), out var entity)) - { - if(entity.TryGetCapability(out var actionTimeline)) - { - actionTimeline.SetOverallSpeedOverride(1); - return true; - } - } - - return false; - } - - public bool FreezePhysics_Impl() - { - if(_gPoseService.IsGPosing == false) return false; - - return _physicsService.FreezeEnable(); - } - - public bool UnFreezePhysics_Impl() - { - if(_gPoseService.IsGPosing == false) return false; - - return _physicsService.FreezeRevert(); - } - - public void Dispose() - { - _configurationService.OnConfigurationChanged -= OnConfigurationChanged; - DisposeIPC(); - } -} diff --git a/Brio/Input/InputAction.cs b/Brio/Input/InputAction.cs index b8a4613c..49a47cfc 100644 --- a/Brio/Input/InputAction.cs +++ b/Brio/Input/InputAction.cs @@ -1,4 +1,5 @@ namespace Brio.Input; + public enum InputAction { // Interface diff --git a/Brio/Input/KeyConfig.cs b/Brio/Input/KeyConfig.cs index d2fafcbb..da57c2cd 100644 --- a/Brio/Input/KeyConfig.cs +++ b/Brio/Input/KeyConfig.cs @@ -1,6 +1,7 @@ using Dalamud.Game.ClientState.Keys; namespace Brio.Input; + public struct KeyConfig(VirtualKey key, bool requireShift = false, bool requireCtrl = false, bool requireAlt = false) { public VirtualKey Key = key; diff --git a/Brio/Library/Tags/Tag.cs b/Brio/Library/Tags/Tag.cs index 2fd39145..56143816 100644 --- a/Brio/Library/Tags/Tag.cs +++ b/Brio/Library/Tags/Tag.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; namespace Brio.Library.Tags; + public class Tag : IEquatable { private static readonly Dictionary TagCache = new(); diff --git a/Brio/MCDF/Game/Services/MCDFService.cs b/Brio/MCDF/Game/Services/MCDFService.cs index b95e7180..36ab67f6 100644 --- a/Brio/MCDF/Game/Services/MCDFService.cs +++ b/Brio/MCDF/Game/Services/MCDFService.cs @@ -583,10 +583,10 @@ private async Task CreateCharacterData(IGameObject player Task getGlamourerData = _glamourerService.GetCharacterCustomizationAsync(playerRelatedObject.Address); Task getCustomizeData = _customizePlusService.GetScaleAsync(playerRelatedObject); - + fragment.GlamourerString = await getGlamourerData.ConfigureAwait(false); Brio.Log.Verbose("Glamourer is now: {data}", fragment.GlamourerString); - + fragment.CustomizePlusScale = await getCustomizeData.ConfigureAwait(false) ?? string.Empty; Brio.Log.Verbose("Customize is now: {data}", fragment.CustomizePlusScale); diff --git a/Brio/Resources/Sheets/BrioActionTimeline.cs b/Brio/Resources/Sheets/BrioActionTimeline.cs index 502a814b..f7cca68e 100644 --- a/Brio/Resources/Sheets/BrioActionTimeline.cs +++ b/Brio/Resources/Sheets/BrioActionTimeline.cs @@ -37,6 +37,10 @@ readonly public struct BrioActionTimeline(ExcelPage page, uint offset, uint row) public readonly bool IsLoop => page.ReadPackedBool(offset + 19, 5); public readonly bool Unknown4 => page.ReadPackedBool(offset + 19, 6); + public ExcelPage ExcelPage => throw new System.NotImplementedException(); + + public uint RowOffset => throw new System.NotImplementedException(); + static BrioActionTimeline IExcelRow.Create(ExcelPage page, uint offset, uint row) => new(page, offset, row); } diff --git a/Brio/Resources/Sheets/BrioCharaMakeType.cs b/Brio/Resources/Sheets/BrioCharaMakeType.cs index d3be6fcb..326b6ff2 100644 --- a/Brio/Resources/Sheets/BrioCharaMakeType.cs +++ b/Brio/Resources/Sheets/BrioCharaMakeType.cs @@ -13,7 +13,7 @@ namespace Brio.Resources.Sheets; -[Sheet("CharaMakeType", 0x80D7DB6D)] +[Sheet("CharaMakeType", 0x50CDBEEF)] public unsafe struct BrioCharaMakeType(ExcelPage page, uint offset, uint row) : IExcelRow { public const int MenuCount = 28; @@ -23,34 +23,42 @@ public unsafe struct BrioCharaMakeType(ExcelPage page, uint offset, uint row) : public const int FaceCount = 8; public const int FaceFeatureCount = 7; + public readonly ExcelPage ExcelPage => page; + public readonly uint RowOffset => offset; public readonly uint RowId => row; public readonly Collection CharaMakeStruct => new(page, offset, offset, &CharaMakeStructCtor, 28); public readonly Collection VoiceStruct => new(page, offset, offset, &VoiceStructCtor, 12); public readonly Collection FacialFeatureOption => new(page, offset, offset, &FacialFeatureOptionCtor, 8); public readonly Collection Equipment => new(page, offset, offset, &EquipmentCtor, 3); - public readonly RowRef Race => new(page.Module, (uint)page.ReadInt32(offset + 12392), page.Language); - public readonly RowRef Tribe => new(page.Module, (uint)page.ReadInt32(offset + 12396), page.Language); - public readonly sbyte Gender => page.ReadInt8(offset + 12400); + public readonly RowRef Race => new(page.Module, (uint)page.ReadInt32(offset + 13064), page.Language); + public readonly RowRef Tribe => new(page.Module, (uint)page.ReadInt32(offset + 13068), page.Language); + public readonly sbyte Gender => page.ReadInt8(offset + 13072); - private static CharaMakeStructStruct CharaMakeStructCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + i * 428); - private static byte VoiceStructCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt8(offset + 11984 + i); - private static FacialFeatureOptionStruct FacialFeatureOptionCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + 11996 + i * 28); - private static EquipmentStruct EquipmentCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + 12224 + i * 56); + + private static CharaMakeStructStruct CharaMakeStructCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + i * 452); + private static byte VoiceStructCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt8(offset + 12656 + i); + private static FacialFeatureOptionStruct FacialFeatureOptionCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + 12668 + i * 28); + private static EquipmentStruct EquipmentCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page, parentOffset, offset + 12896 + i * 56); public readonly struct CharaMakeStructStruct(ExcelPage page, uint parentOffset, uint offset) { public readonly RowRef Menu => new(page.Module, page.ReadUInt32(offset), page.Language); public readonly uint SubMenuMask => page.ReadUInt32(offset + 4); public readonly uint Customize => page.ReadUInt32(offset + 8); + public readonly Collection SubMenuParam => new(page, parentOffset, offset, &SubMenuParamCtor, 100); - public readonly byte InitVal => page.ReadUInt8(offset + 412); - public readonly byte SubMenuType => page.ReadUInt8(offset + 413); - public readonly byte SubMenuNum => page.ReadUInt8(offset + 414); - public readonly byte LookAt => page.ReadUInt8(offset + 415); + public readonly Collection Unknown0 => new(page, parentOffset, offset, &Unknown0Ctor, 6); + + public readonly byte InitVal => page.ReadUInt8(offset + 436); + public readonly byte SubMenuType => page.ReadUInt8(offset + 437); + public readonly byte SubMenuNum => page.ReadUInt8(offset + 438); + public readonly byte LookAt => page.ReadUInt8(offset + 439); + public readonly Collection SubMenuGraphic => new(page, parentOffset, offset, &SubMenuGraphicCtor, 10); private static uint SubMenuParamCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt32(offset + 12 + i * 4); + private static uint Unknown0Ctor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt32(offset + 412 + i * 4); private static byte SubMenuGraphicCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt8(offset + 416 + i); } @@ -89,8 +97,7 @@ public static MenuCollection BuildMenus(ActorAppearance appearance) var menus = new List(); var CharaMakeTypes = GameDataProvider.Instance.DataManager.GetExcelSheet(name: "CharaMakeType"). - Where(x => x.Gender == (sbyte)appearance.Customize.Gender && x.Race.RowId == (uint)appearance.Customize.Race). - First(); + First(x => x.Gender == (sbyte)appearance.Customize.Gender && x.Race.RowId == (uint)appearance.Customize.Race); for(uint i = 0; i < CharaMakeTypes.CharaMakeStruct.Count; ++i) { diff --git a/Brio/Resources/Sheets/BrioHairMakeType.cs b/Brio/Resources/Sheets/BrioHairMakeType.cs index 76b368c2..7d31b6ce 100644 --- a/Brio/Resources/Sheets/BrioHairMakeType.cs +++ b/Brio/Resources/Sheets/BrioHairMakeType.cs @@ -7,32 +7,29 @@ namespace Brio.Resources.Sheets; [Sheet("HairMakeType")] -public struct BrioHairMakeType : IExcelRow +public struct BrioHairMakeType(ExcelPage page, uint offset, uint row) : IExcelRow { public const int EntryCount = 100; - public BrioHairMakeType() - { - } - - public uint RowId { get; private set; } + public readonly ExcelPage ExcelPage => page; + public readonly uint RowOffset => offset; + public readonly uint RowId => row; public RowRef Race { get; private set; } public RowRef Tribe { get; private set; } public Genders Gender { get; private set; } + public RowRef[] HairStyles = new RowRef[EntryCount]; public RowRef[] FacePaints = new RowRef[EntryCount]; public static BrioHairMakeType Create(ExcelPage page, uint offset, uint row) { - var brioHairMakeType = new BrioHairMakeType + var brioHairMakeType = new BrioHairMakeType(page, offset, row) { - RowId = row, - - Race = new RowRef(page.Module, (uint)page.ReadInt32(offset + 4076), page.Language), - Tribe = new RowRef(page.Module, (uint)page.ReadInt32(offset + 4080), page.Language), - Gender = (Genders)(uint)page.ReadInt8(offset + 4084) + Race = new RowRef(page.Module, (uint)page.ReadInt32(offset + 4292), page.Language), + Tribe = new RowRef(page.Module, (uint)page.ReadInt32(offset + 4296), page.Language), + Gender = (Genders)(uint)page.ReadInt8(offset + 4300) }; for(int i = 0; i < EntryCount; i++) diff --git a/Brio/UI/BrioStyle.cs b/Brio/UI/BrioStyle.cs index eb624b7c..247d57e9 100644 --- a/Brio/UI/BrioStyle.cs +++ b/Brio/UI/BrioStyle.cs @@ -3,6 +3,7 @@ using System.Numerics; namespace Brio.UI; + public static class BrioStyle { public static bool EnableStyle { get; set; } diff --git a/Brio/UI/Controls/Editors/BoneIKEditor.cs b/Brio/UI/Controls/Editors/BoneIKEditor.cs index fde045f0..9eb1464a 100644 --- a/Brio/UI/Controls/Editors/BoneIKEditor.cs +++ b/Brio/UI/Controls/Editors/BoneIKEditor.cs @@ -4,6 +4,7 @@ using Dalamud.Interface.Utility.Raii; namespace Brio.UI.Controls.Editors; + public class BoneIKEditor { public static void Draw(BonePoseInfo poseInfo, PosingCapability posing) diff --git a/Brio/UI/Controls/Editors/CustomizeEditor.cs b/Brio/UI/Controls/Editors/CustomizeEditor.cs index 8dcc085c..33efedde 100644 --- a/Brio/UI/Controls/Editors/CustomizeEditor.cs +++ b/Brio/UI/Controls/Editors/CustomizeEditor.cs @@ -42,9 +42,9 @@ public bool DrawCustomize(ref ActorAppearance currentAppearance, ActorAppearance ImBrio.VerticalPadding(2); ImGui.Separator(); ImBrio.VerticalPadding(2); - + didChange |= DrawRaceSelector(ref currentAppearance.Customize); - + ImBrio.VerticalPadding(2); ImGui.Separator(); ImBrio.VerticalPadding(2); @@ -687,7 +687,7 @@ private bool DrawGenericMenu(ref ActorCustomize customize, BrioCharaMakeType.Men var menuType = menu.Type; var customizeIndex = menu.CustomizeIndex; var title = menu.Title; - + return menuType switch { BrioCharaMakeType.MenuType.Numerical => DrawNumericalSelector(ref customize, customizeIndex, title), diff --git a/Brio/UI/Controls/Editors/GearEditor.cs b/Brio/UI/Controls/Editors/GearEditor.cs index 13ca481d..3cb97c5f 100644 --- a/Brio/UI/Controls/Editors/GearEditor.cs +++ b/Brio/UI/Controls/Editors/GearEditor.cs @@ -476,7 +476,7 @@ private bool DrawWeaponSlot(ref ActorAppearance appearance, ref WeaponModelId eq { equip = SpecialAppearances.EmperorsMainHand; } - else if (slot == ActorEquipSlot.OffHand) + else if(slot == ActorEquipSlot.OffHand) { equip = SpecialAppearances.EmperorsOffHand; diff --git a/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs b/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs index 8b78d225..a2758ff1 100644 --- a/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs +++ b/Brio/UI/Controls/Editors/LibrarySourcesEditor.cs @@ -9,6 +9,7 @@ using static Brio.Config.LibraryConfiguration; namespace Brio.UI.Controls.Editors; + 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 249bc7cc..4a5a4776 100644 --- a/Brio/UI/Controls/Editors/ModelShaderEditor.cs +++ b/Brio/UI/Controls/Editors/ModelShaderEditor.cs @@ -4,8 +4,6 @@ using Brio.UI.Controls.Stateless; using Dalamud.Bindings.ImGui; using Dalamud.Interface; -using System; -using System.Numerics; namespace Brio.UI.Controls.Editors; diff --git a/Brio/UI/Controls/Editors/PosingEditorCommon.cs b/Brio/UI/Controls/Editors/PosingEditorCommon.cs index 8d4b18d9..4ce0ad7f 100644 --- a/Brio/UI/Controls/Editors/PosingEditorCommon.cs +++ b/Brio/UI/Controls/Editors/PosingEditorCommon.cs @@ -148,7 +148,7 @@ public static void DrawBoneFilterEditor(BoneFilter filter, PosingService? posing { filter.EnableOnly(category); } - + if(category.Type is BoneCategories.BoneCategoryTypes.Category) { ImGui.Separator(); diff --git a/Brio/UI/Controls/Stateless/ImBrio.Companions.cs b/Brio/UI/Controls/Stateless/ImBrio.Companions.cs index 62adadfd..7a751874 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Companions.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Companions.cs @@ -3,6 +3,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; + 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 94cc0947..08153ae1 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Drag.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Drag.cs @@ -337,7 +337,7 @@ public static (bool anyActive, bool didChange) DragFloat(string label, ref float } changed = true; } - + AttachToolTip($"Increase {tooltip}"); if(hasLabel) diff --git a/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs b/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs index dec6f80a..59856eff 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Layouts.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; namespace Brio.UI.Controls.Stateless; + public static partial class ImBrio { [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] @@ -42,7 +43,7 @@ public static void CenterNextElementWithPadding(float padding) float windowWidth = ImGui.GetContentRegionAvail().X; float offset = MathF.Max(0, (windowWidth - elementWidth) * 0.5f); - + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + offset); ImGui.SetNextItemWidth(elementWidth); } diff --git a/Brio/UI/Controls/Stateless/ImBrio.Slider.cs b/Brio/UI/Controls/Stateless/ImBrio.Slider.cs index a889bca0..995aa487 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Slider.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Slider.cs @@ -5,6 +5,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; + 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) diff --git a/Brio/UI/Controls/Stateless/ImBrio.Text.cs b/Brio/UI/Controls/Stateless/ImBrio.Text.cs index 0e4dcd27..69928407 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Text.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Text.cs @@ -8,6 +8,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; + public static partial class ImBrio { diff --git a/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs b/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs index e5bd820d..6184d37a 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.ToggleButton.cs @@ -88,7 +88,7 @@ public static bool ToggleSelecterStrip(string id, Vector2 size, ref bool[] selec if(i > 0) ImGui.SameLine(); changed |= ToggleStripButton($"{options[i]}##{id}_{i}", new(buttonWidth, size.Y), ref selected[i], false); - + if(toolTip is not null) { var tooltip = selected[i] ? "Disable" : "Enable"; diff --git a/Brio/UI/Controls/Stateless/ImBrio.Weather.cs b/Brio/UI/Controls/Stateless/ImBrio.Weather.cs index da0dedd6..c8a8ded9 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.Weather.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.Weather.cs @@ -3,6 +3,7 @@ using System.Numerics; namespace Brio.UI.Controls.Stateless; + 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 b4cfa5bb..0fc8377b 100644 --- a/Brio/UI/Controls/Stateless/ImBrio.cs +++ b/Brio/UI/Controls/Stateless/ImBrio.cs @@ -89,7 +89,7 @@ public static bool FontIconButtonRight(string id, FontAwesomeIcon icon, float po if(enabled is false) ImGui.BeginDisabled(); - var pixelPos = ImGui.GetWindowSize().X - ((ImGui.CalcTextSize("XXII").X + (ImGui.GetStyle().FramePadding.X * 2)) * position ); + var pixelPos = ImGui.GetWindowSize().X - ((ImGui.CalcTextSize("XXII").X + (ImGui.GetStyle().FramePadding.X * 2)) * position); ImGui.SetCursorPosX(pixelPos); diff --git a/Brio/UI/UIManager.cs b/Brio/UI/UIManager.cs index 060a620b..e5075d00 100644 --- a/Brio/UI/UIManager.cs +++ b/Brio/UI/UIManager.cs @@ -11,7 +11,6 @@ using Dalamud.Interface.Windowing; using Dalamud.Plugin; using Dalamud.Plugin.Services; -using FFXIVClientStructs.FFXIV.Common.Lua; using System; using System.Collections.Generic; diff --git a/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs b/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs index 4f989821..1d771797 100644 --- a/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs +++ b/Brio/UI/Widgets/Actor/ActorAppearanceWidget.cs @@ -49,7 +49,7 @@ public override void DrawBody() else drawBody(); - void drawBody() + void drawBody() { AppearanceEditorCommon.DrawPenumbraCollectionSwitcher(Capability); AppearanceEditorCommon.DrawGlamourerDesignSwitcher(Capability); diff --git a/Brio/UI/Widgets/Camera/CameraContainerWidget.cs b/Brio/UI/Widgets/Camera/CameraContainerWidget.cs index c64b3b9d..33154b74 100644 --- a/Brio/UI/Widgets/Camera/CameraContainerWidget.cs +++ b/Brio/UI/Widgets/Camera/CameraContainerWidget.cs @@ -102,7 +102,7 @@ public override void DrawPopup() ImGui.EndMenu(); } - + if(ImGui.BeginMenu("Destroy All Cameras###containerwidgetpopup_destroyall")) { if(ImGui.MenuItem("Confirm Destruction###containerwidgetpopup_destroyall_confirm")) diff --git a/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs b/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs index bf2e7cac..bf2a9152 100644 --- a/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs +++ b/Brio/UI/Widgets/Camera/CameraLifetimeWidet.cs @@ -82,7 +82,7 @@ public override void DrawPopup() { Capability.VirtualCameraManager.DestroyCamera(Capability.CameraEntity.CameraID); } - + ImGui.EndMenu(); } diff --git a/Brio/UI/Widgets/Debug/DebugWidget.cs b/Brio/UI/Widgets/Debug/DebugWidget.cs index 911f732e..894cd397 100644 --- a/Brio/UI/Widgets/Debug/DebugWidget.cs +++ b/Brio/UI/Widgets/Debug/DebugWidget.cs @@ -3,7 +3,6 @@ using Brio.IPC; using Brio.UI.Controls.Stateless; using Brio.UI.Widgets.Core; -using Brio.UI.Widgets.World; using Dalamud.Bindings.ImGui; using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Services; diff --git a/Brio/UI/Widgets/World/Lights/LightRenderingWidget.cs b/Brio/UI/Widgets/World/Lights/LightRenderingWidget.cs index 9c906ce0..46fd697f 100644 --- a/Brio/UI/Widgets/World/Lights/LightRenderingWidget.cs +++ b/Brio/UI/Widgets/World/Lights/LightRenderingWidget.cs @@ -1,13 +1,8 @@ using Brio.Capabilities.World; -using Brio.Game.World; using Brio.UI.Controls.Editors; using Brio.UI.Controls.Stateless; using Brio.UI.Widgets.Core; using Dalamud.Bindings.ImGui; -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; -using System; -using System.Numerics; namespace Brio.UI.Widgets.World.Lights; @@ -27,7 +22,7 @@ public override void DrawPopup() } public unsafe override void DrawBody() - { + { LightEditor.DrawLightProperties(Capability); ImBrio.VerticalPadding(5); diff --git a/Brio/UI/Windows/AutoSaveWindow.cs b/Brio/UI/Windows/AutoSaveWindow.cs index ab42b2ba..da3e150f 100644 --- a/Brio/UI/Windows/AutoSaveWindow.cs +++ b/Brio/UI/Windows/AutoSaveWindow.cs @@ -5,6 +5,7 @@ using System; namespace Brio.UI.Windows; + public class AutoSaveWindow : Window, IDisposable { private readonly ConfigurationService _configurationService; diff --git a/Brio/UI/Windows/ProjectWindow.cs b/Brio/UI/Windows/ProjectWindow.cs index a8ebd61b..4157a316 100644 --- a/Brio/UI/Windows/ProjectWindow.cs +++ b/Brio/UI/Windows/ProjectWindow.cs @@ -47,7 +47,7 @@ public override void Draw() { using(ImRaii.PushColor(ImGuiCol.Text, UIConstants.GizmoMagenta)) ImGui.Text("Project System is in Beta."); - + using(ImRaii.PushColor(ImGuiCol.Text, UIConstants.GizmoMagenta)) ImGui.Text("ATTENTION: Projects made in this version will be incompatible with the next version of Brio!"); diff --git a/Brio/UI/Windows/SettingsWindow.cs b/Brio/UI/Windows/SettingsWindow.cs index c1267fc5..01de5aea 100644 --- a/Brio/UI/Windows/SettingsWindow.cs +++ b/Brio/UI/Windows/SettingsWindow.cs @@ -1,6 +1,7 @@ using Brio.Config; using Brio.Input; using Brio.IPC; +using Brio.IPC.API; using Brio.Resources; using Brio.UI.Controls.Core; using Brio.UI.Controls.Editors; @@ -22,7 +23,6 @@ public class SettingsWindow : Window private readonly PenumbraService _penumbraService; private readonly GlamourerService _glamourerService; private readonly WebService _webService; - private readonly BrioIPCService _brioIPCService; private readonly CustomizePlusService _customizePlusService; public SettingsWindow( @@ -30,8 +30,7 @@ public SettingsWindow( PenumbraService penumbraService, GlamourerService glamourerService, WebService webService, - CustomizePlusService customizePlusService, - BrioIPCService brioIPCService) : base($"{Brio.Name} SETTINGS###brio_settings_window", ImGuiWindowFlags.NoResize) + CustomizePlusService customizePlusService) : base($"{Brio.Name} SETTINGS###brio_settings_window", ImGuiWindowFlags.NoResize) { Namespace = "brio_settings_namespace"; @@ -39,7 +38,6 @@ public SettingsWindow( _penumbraService = penumbraService; _glamourerService = glamourerService; _webService = webService; - _brioIPCService = brioIPCService; _customizePlusService = customizePlusService; Size = new Vector2(500, 550); @@ -375,7 +373,7 @@ private void DrawBrioIPC() _configurationService.Configuration.IPC.EnableBrioIPC = enableBrioIpc; _configurationService.ApplyChange(); } - ImGui.Text($"Brio IPC Status: {(_brioIPCService.IsIPCEnabled ? "Active" : "Inactive")}"); + ImGui.Text($"Brio IPC Status: {(enableBrioIpc ? "Active" : "Inactive")}"); bool enableWebApi = _configurationService.Configuration.IPC.AllowWebAPI; if(ImGui.Checkbox("Enable Brio API", ref enableWebApi)) @@ -661,7 +659,7 @@ private void DrawOffsetSection() { _configurationService.Configuration.Interface.DefaultFreeCameraMouseSensitivity = defaultFreeCamMouseSensitivity; _configurationService.ApplyChange(); - } + } } bool resetSettings = false; diff --git a/Brio/UI/Windows/Specialized/CameraWindow.cs b/Brio/UI/Windows/Specialized/CameraWindow.cs index 9377f9d2..ddce6d67 100644 --- a/Brio/UI/Windows/Specialized/CameraWindow.cs +++ b/Brio/UI/Windows/Specialized/CameraWindow.cs @@ -2,14 +2,12 @@ using Brio.Config; using Brio.Entities; using Brio.Entities.Camera; -using Brio.Entities.Core; using Brio.Game.Camera; using Brio.Game.Cutscene; using Brio.Game.GPose; using Brio.UI.Controls.Editors; using Brio.UI.Controls.Stateless; using Dalamud.Bindings.ImGui; -using Dalamud.Interface.Colors; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using System; diff --git a/Brio/UI/Windows/Specialized/LightWindow.cs b/Brio/UI/Windows/Specialized/LightWindow.cs index 88ea1eef..7685aad7 100644 --- a/Brio/UI/Windows/Specialized/LightWindow.cs +++ b/Brio/UI/Windows/Specialized/LightWindow.cs @@ -77,7 +77,7 @@ public override void Draw() if(_lightingService.SelectedLightEntity is null || _lightingService.SelectedLightEntity.GameLight.IsValid == false) { - _lightingService.SelectedLightEntity = _lightingService.SpawnedLightEntitiesCount > 0 + _lightingService.SelectedLightEntity = _lightingService.SpawnedLightEntitiesCount > 0 ? _lightingService.SpawnedLightEntities.First() : null; } @@ -117,9 +117,9 @@ public override void Draw() if(ImBrio.FontIconButton("lifetimewidget_rename", FontAwesomeIcon.Signature, "Rename Light")) { RenameActorModal.Open(light!.Entity); - } + } } - + LightEditor.DrawSpawnMenu(_lightingService); if(_lightingService.SelectedLightEntity is null || _lightingService.SelectedLightEntity.GameLight.IsValid == false) diff --git a/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs b/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs index 08157ba0..92092bc1 100644 --- a/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingOverlayToolbarWindow.cs @@ -124,7 +124,7 @@ public override void Draw() else { ImGui.PushStyleColor(ImGuiCol.Button, UIConstants.Transparent); - + using(ImRaii.PushColor(ImGuiCol.Text, _overlayTransformWindow.IsOpen ? UIConstants.ToggleButtonActive : UIConstants.ToggleButtonInactive)) { using(ImRaii.PushFont(UiBuilder.IconFont)) @@ -155,7 +155,7 @@ public override void Draw() _overlayWindow.IsOpen = false; } ImBrio.AttachToolTip("Close Overlay"); - + ImGui.PopStyleColor(); ImGui.TextColored(ImGuiColors.DalamudRed, "Attention! No valid,"); @@ -362,7 +362,7 @@ private void DrawButtons(PosingCapability? posing, ActionTimelineCapability? tim _posingService.CoordinateMode = _posingService.CoordinateMode == PosingCoordinateMode.Local ? PosingCoordinateMode.World : PosingCoordinateMode.Local; } ImBrio.AttachToolTip(_posingService.CoordinateMode == PosingCoordinateMode.Local ? "Switch to World" : "Switch to Local"); - + ImGui.SameLine(); using(ImRaii.PushColor(ImGuiCol.Text, _overlayTransformWindow.IsOpen ? UIConstants.ToggleButtonActive : UIConstants.ToggleButtonInactive)) @@ -374,7 +374,7 @@ private void DrawButtons(PosingCapability? posing, ActionTimelineCapability? tim } } ImBrio.AttachToolTip("Toggle Transform Window"); - + ImGui.SameLine(); using(ImRaii.PushColor(ImGuiCol.Text, _lightWindow.IsOpen ? UIConstants.ToggleButtonActive : UIConstants.ToggleButtonInactive)) diff --git a/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs b/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs index 50ab355e..17476b85 100644 --- a/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs +++ b/Brio/UI/Windows/Specialized/PosingOverlayWindow.cs @@ -217,7 +217,7 @@ private unsafe void CalculateClickables(PosingCapability posing, OverlayUIState var modelTransform = new ClickableItem { Item = PosingSelectionType.ModelTransform, - ScreenPosition = ImGui.GetMainViewport().Pos + modelScreen, + ScreenPosition = ImGui.GetMainViewport().Pos + modelScreen, Size = config.BoneCircleSize, }; clickables.Add(modelTransform); diff --git a/Brio/Web/ActorWebController.cs b/Brio/Web/ActorWebController.cs index d9e18a89..a34ba6db 100644 --- a/Brio/Web/ActorWebController.cs +++ b/Brio/Web/ActorWebController.cs @@ -67,7 +67,8 @@ public async Task Spawn() public unsafe Task WaitForReadyToDraw(IGameObject go) { return _framework.RunUntilSatisfied( - () => { + () => + { if(go.IsValid()) return go.Native()->IsReadyToDraw(); return false; diff --git a/Brio/packages.lock.json b/Brio/packages.lock.json index 31454d49..7ac4adbc 100644 --- a/Brio/packages.lock.json +++ b/Brio/packages.lock.json @@ -1,7 +1,7 @@ { "version": 1, "dependencies": { - "net9.0-windows7.0": { + "net10.0-windows7.0": { "DalamudPackager": { "type": "Direct", "requested": "[13.1.0, )", @@ -107,18 +107,13 @@ "resolved": "17.11.4", "contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA==" }, - "System.ValueTuple": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" - }, "Unosquare.Swan.Lite": { "type": "Transitive", "resolved": "3.1.0", - "contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ==", - "dependencies": { - "System.ValueTuple": "4.5.0" - } + "contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ==" + }, + "brio.api": { + "type": "Project" } } } diff --git a/BrioTester.sln b/BrioTester.sln deleted file mode 100644 index 4b511f30..00000000 --- a/BrioTester.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.13.35507.96 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BrioTester", "BrioTester\BrioTester.csproj", "{E20A4046-E8C5-BDB1-282C-F2BC3231E687}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E20A4046-E8C5-BDB1-282C-F2BC3231E687}.Debug|x64.ActiveCfg = Debug|x64 - {E20A4046-E8C5-BDB1-282C-F2BC3231E687}.Debug|x64.Build.0 = Debug|x64 - {E20A4046-E8C5-BDB1-282C-F2BC3231E687}.Release|x64.ActiveCfg = Release|x64 - {E20A4046-E8C5-BDB1-282C-F2BC3231E687}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {6A991217-5AC2-4125-AB33-D78DDED973AE} - EndGlobalSection -EndGlobal diff --git a/BrioTester.slnx b/BrioTester.slnx new file mode 100644 index 00000000..7b25c3f2 --- /dev/null +++ b/BrioTester.slnx @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Libs/Brio API b/Libs/Brio API new file mode 160000 index 00000000..588f5291 --- /dev/null +++ b/Libs/Brio API @@ -0,0 +1 @@ +Subproject commit 588f52915cb1f462a6b32b84d121986ba6a9b6e5 diff --git a/Resources/Templates/repo.tmpl b/Resources/Templates/repo.tmpl index f42ff68a..40d34ce6 100644 --- a/Resources/Templates/repo.tmpl +++ b/Resources/Templates/repo.tmpl @@ -9,9 +9,9 @@ "TestingAssemblyVersion": "{version}", "RepoUrl": "https://github.com/Etheirys/Brio", "ApplicableVersion": "any", - "DownloadCount": 1539604, - "DalamudApiLevel": 13, - "TestingDalamudApiLevel": 13, + "DownloadCount": 1654215, + "DalamudApiLevel": 14, + "TestingDalamudApiLevel": 14, "DownloadLinkInstall": "https://github.com/Etheirys/Brio/releases/download/v{version}/Brio.zip", "DownloadLinkTesting": "https://github.com/Etheirys/Brio/releases/download/v{version}/Brio.zip", "DownloadLinkUpdate": "https://github.com/Etheirys/Brio/releases/download/v{version}/Brio.zip", diff --git a/Resources/Templates/repotesting.tmpl b/Resources/Templates/repotesting.tmpl index 1ac7f5f3..44b7768e 100644 --- a/Resources/Templates/repotesting.tmpl +++ b/Resources/Templates/repotesting.tmpl @@ -9,9 +9,9 @@ "TestingAssemblyVersion": "{version_testing}", "RepoUrl": "https://github.com/Etheirys/Brio", "ApplicableVersion": "any", - "DownloadCount": 1539604, - "DalamudApiLevel": 13, - "TestingDalamudApiLevel": 13, + "DownloadCount": 1654215, + "DalamudApiLevel": 14, + "TestingDalamudApiLevel": 14, "DownloadLinkInstall": "https://github.com/Etheirys/Brio/releases/download/v{version_live}/Brio.zip", "DownloadLinkTesting": "https://github.com/Etheirys/Brio/releases/download/v{version_testing}/Brio.zip", "DownloadLinkUpdate": "https://github.com/Etheirys/Brio/releases/download/v{version_live}/Brio.zip", diff --git a/brio.slnx b/brio.slnx new file mode 100644 index 00000000..9944efbc --- /dev/null +++ b/brio.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + +