From 5c6abd2f99c9bda099954ba78c3fdd2b9397b7b7 Mon Sep 17 00:00:00 2001 From: Bronya-Rand Date: Mon, 17 Feb 2025 18:37:45 +0000 Subject: [PATCH 1/5] fix: brio camera not being added to `_createdCameras` --- Brio/Game/Camera/VirtualCameraManager.cs | 33 +++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Brio/Game/Camera/VirtualCameraManager.cs b/Brio/Game/Camera/VirtualCameraManager.cs index e473ab29..9e3f157d 100644 --- a/Brio/Game/Camera/VirtualCameraManager.cs +++ b/Brio/Game/Camera/VirtualCameraManager.cs @@ -55,16 +55,29 @@ public VirtualCameraManager(IServiceProvider serviceProvider, GPoseService gPose if(virtualCamera is null) { - if(cameraType == CameraType.Free) + switch(cameraType) { - camEnt.VirtualCamera.FreeCamValues.MovementSpeed = DefaultMovementSpeed; - camEnt.VirtualCamera.FreeCamValues.MouseSensitivity = DefaultMouseSensitivity; - camEnt.VirtualCamera.IsFreeCamera = true; - camEnt.VirtualCamera.ActivateCamera(); - camEnt.VirtualCamera.ToFreeCam(); - camEnt.VirtualCamera.DeactivateCamera(); - - _createdCameras.Add(_cameraId, camEnt); + case CameraType.Free: + camEnt.VirtualCamera.FreeCamValues.MovementSpeed = DefaultMovementSpeed; + camEnt.VirtualCamera.FreeCamValues.MouseSensitivity = DefaultMouseSensitivity; + camEnt.VirtualCamera.IsFreeCamera = true; + camEnt.VirtualCamera.ActivateCamera(); + camEnt.VirtualCamera.ToFreeCam(); + camEnt.VirtualCamera.DeactivateCamera(); + _createdCameras.Add(_cameraId, camEnt); + break; + case CameraType.Brio: + camEnt.VirtualCamera.IsFreeCamera = false; + camEnt.VirtualCamera.ActivateCamera(); + camEnt.VirtualCamera.DeactivateCamera(); + _createdCameras.Add(_cameraId, camEnt); + break; + //case CameraType.Cutscene: + // unimplemented + // break; + default: + Brio.Log.Error($"Unknown camera type: {cameraType}"); + break; } } else @@ -95,7 +108,7 @@ public bool DestroyCamera(int cameraID) if(cameraID == 0) return false; - Brio.Log.Verbose("Destroying Brio camera " + _cameraId); + Brio.Log.Info("Destroying Brio camera " + _cameraId); if(_entityManager.TryGetEntity("cameras", out var ent)) { From a4f26e327c39310d4e58ed29140bc7e5a2008694 Mon Sep 17 00:00:00 2001 From: Kenneth M Date: Mon, 17 Feb 2025 16:16:46 -0600 Subject: [PATCH 2/5] Update VirtualCameraManager.cs --- Brio/Game/Camera/VirtualCameraManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Brio/Game/Camera/VirtualCameraManager.cs b/Brio/Game/Camera/VirtualCameraManager.cs index 9e3f157d..dc499e2c 100644 --- a/Brio/Game/Camera/VirtualCameraManager.cs +++ b/Brio/Game/Camera/VirtualCameraManager.cs @@ -108,7 +108,7 @@ public bool DestroyCamera(int cameraID) if(cameraID == 0) return false; - Brio.Log.Info("Destroying Brio camera " + _cameraId); + Brio.Log.Verbose("Destroying Brio camera " + _cameraId); if(_entityManager.TryGetEntity("cameras", out var ent)) { From 6822bbab59fae7b0b2a8a256626b88d0e24a8af7 Mon Sep 17 00:00:00 2001 From: Bronya-Rand Date: Tue, 18 Feb 2025 07:33:17 +0000 Subject: [PATCH 3/5] feat: save and load custom colors --- .../Actor/ActorAppearanceCapability.cs | 15 ++++++- Brio/Files/ActorFile.cs | 3 +- Brio/Files/AnamnesisCharaFile.cs | 39 ++++++++++++++++++- Brio/Game/Actor/Appearance/ActorAppearance.cs | 7 ++++ Brio/UI/Controls/Stateless/FileUIHelpers.cs | 25 ++++++++++++ .../Specialized/ActorAppearanceWindow.cs | 9 +++++ 6 files changed, 93 insertions(+), 5 deletions(-) diff --git a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs index cb3d8cde..16cb5ade 100644 --- a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs +++ b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs @@ -4,6 +4,7 @@ using Brio.Game.Actor; using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; +using Brio.Game.Actor.Interop; using Brio.Game.GPose; using Brio.Game.Types; using Brio.IPC; @@ -206,9 +207,18 @@ public void ImportAppearance(string file, AppearanceImportOptions options) _ = SetAppearance(doc, options); } - public void ExportAppearance(string file) + public unsafe void ExportAppearance(string file) { - AnamnesisCharaFile appearance = CurrentAppearance; + var currentAppearance = CurrentAppearance; + BrioHuman.ShaderParams* shaders = Character.GetShaderParams(); + + ActorAppearanceExtended actor = new() + { + Appearance = currentAppearance, + ShaderParams = *shaders + }; + + AnamnesisCharaFile appearance = actor; ResourceProvider.Instance.SaveFileDocument(file, appearance); } @@ -318,6 +328,7 @@ public WeaponModelId GetProp() private unsafe void ApplyShaderOverride() { var shaders = Character.GetShaderParams(); + var test = *shaders; if(shaders != null) { _modelShaderOverride.Apply(ref *shaders); diff --git a/Brio/Files/ActorFile.cs b/Brio/Files/ActorFile.cs index 33626f99..c75846f3 100644 --- a/Brio/Files/ActorFile.cs +++ b/Brio/Files/ActorFile.cs @@ -2,6 +2,7 @@ using Brio.Capabilities.Posing; using Brio.Core; using Brio.Entities.Actor; +using Brio.Game.Actor.Appearance; using Brio.Game.Actor.Extensions; using Brio.Game.Types; using MessagePack; @@ -41,7 +42,7 @@ public static implicit operator ActorFile(ActorEntity actorEntity) var actorFile = new ActorFile { Name = actorEntity.RawName, - AnamnesisCharaFile = appearanceCapability.CurrentAppearance, + AnamnesisCharaFile = new ActorAppearanceExtended { Appearance = appearanceCapability.CurrentAppearance }, PoseFile = posingCapability.GeneratePoseFile(), IsProp = actorEntity.IsProp, PropData = new PropData diff --git a/Brio/Files/AnamnesisCharaFile.cs b/Brio/Files/AnamnesisCharaFile.cs index 650f3f1d..6e1fd98f 100644 --- a/Brio/Files/AnamnesisCharaFile.cs +++ b/Brio/Files/AnamnesisCharaFile.cs @@ -2,6 +2,7 @@ using Brio.Entities; using Brio.Entities.Actor; using Brio.Game.Actor.Appearance; +using Brio.Game.Actor.Interop; using Brio.Library.Tags; using Brio.Resources; using Dalamud.Interface.Textures.TextureWraps; @@ -164,8 +165,31 @@ public static implicit operator ActorAppearance(AnamnesisCharaFile chara) return appearance; } - public static implicit operator AnamnesisCharaFile(ActorAppearance appearance) + public static implicit operator BrioHuman.ShaderParams(AnamnesisCharaFile chara) { + // More Extended Appearance (Shaders) + var shaders = new BrioHuman.ShaderParams + { + SkinColor = chara.SkinColor ?? Vector3.One, + SkinGloss = chara.SkinGloss ?? Vector3.One, + LeftEyeColor = chara.LeftEyeColor ?? Vector3.One, + RightEyeColor = chara.RightEyeColor ?? Vector3.One, + HairColor = chara.HairColor ?? Vector3.One, + HairGloss = chara.HairGloss ?? Vector3.One, + HairHighlight = chara.HairHighlight ?? Vector3.One, + MouthColor = chara.MouthColor ?? Vector4.One, + MuscleTone = chara.MuscleTone, + FeatureColor = chara.LimbalRingColor ?? Vector3.One, + }; + + return shaders; + } + + public static implicit operator AnamnesisCharaFile(ActorAppearanceExtended appearanceExt) + { + var appearance = appearanceExt.Appearance; + var shaders = appearanceExt.ShaderParams; + var charaFile = new AnamnesisCharaFile { // Model @@ -220,7 +244,18 @@ public static implicit operator AnamnesisCharaFile(ActorAppearance appearance) // Extended Appearance Transparency = appearance.ExtendedAppearance.Transparency, - HeightMultiplier = appearance.ExtendedAppearance.HeightMultiplier + HeightMultiplier = appearance.ExtendedAppearance.HeightMultiplier, + + SkinColor = shaders.SkinColor, + SkinGloss = shaders.SkinGloss, + LeftEyeColor = shaders.LeftEyeColor, + RightEyeColor = shaders.RightEyeColor, + HairColor = shaders.HairColor, + HairGloss = shaders.HairGloss, + HairHighlight = shaders.HairHighlight, + MouthColor = shaders.MouthColor, + MuscleTone = shaders.MuscleTone, + LimbalRingColor = shaders.FeatureColor, }; return charaFile; diff --git a/Brio/Game/Actor/Appearance/ActorAppearance.cs b/Brio/Game/Actor/Appearance/ActorAppearance.cs index 6c5eaa16..ec94c084 100644 --- a/Brio/Game/Actor/Appearance/ActorAppearance.cs +++ b/Brio/Game/Actor/Appearance/ActorAppearance.cs @@ -1,4 +1,5 @@ using Brio.Game.Actor.Extensions; +using Brio.Game.Actor.Interop; using FFXIVClientStructs.FFXIV.Client.Game.Character; using Lumina.Excel.Sheets; using DalamudCharacter = Dalamud.Game.ClientState.Objects.Types.ICharacter; @@ -332,3 +333,9 @@ private static (WeaponModelId, WeaponModelId, ActorEquipment) FromNpcEquip(NpcEq return (mainHand, offHand, equipment); } } + +public struct ActorAppearanceExtended +{ + public ActorAppearance Appearance; + public BrioHuman.ShaderParams ShaderParams; +} diff --git a/Brio/UI/Controls/Stateless/FileUIHelpers.cs b/Brio/UI/Controls/Stateless/FileUIHelpers.cs index 9239fc7c..6676b3e6 100644 --- a/Brio/UI/Controls/Stateless/FileUIHelpers.cs +++ b/Brio/UI/Controls/Stateless/FileUIHelpers.cs @@ -5,6 +5,7 @@ using Brio.Entities; using Brio.Files; using Brio.Game.Actor.Appearance; +using Brio.Game.Actor.Interop; using Brio.Game.Core; using Brio.Game.Posing; using Brio.Game.Scene; @@ -273,6 +274,20 @@ public static void ShowExportPoseModal(PosingCapability capability) }, ConfigurationService.Instance.Configuration.LastExportPath, true); } + public static void ImportShadersFromFile(ref ModelShaderOverride modelShaderOverride, BrioHuman.ShaderParams shaderParams) + { + modelShaderOverride.SkinColor = shaderParams.SkinColor; + modelShaderOverride.SkinGloss = shaderParams.SkinGloss; + modelShaderOverride.MuscleTone = shaderParams.MuscleTone; + modelShaderOverride.MouthColor = shaderParams.MouthColor; + modelShaderOverride.HairColor = shaderParams.HairColor; + modelShaderOverride.HairGloss = shaderParams.HairGloss; + modelShaderOverride.HairHighlight = shaderParams.HairHighlight; + modelShaderOverride.LeftEyeColor = shaderParams.LeftEyeColor; + modelShaderOverride.RightEyeColor = shaderParams.RightEyeColor; + modelShaderOverride.FeatureColor = shaderParams.FeatureColor; + } + public static void ShowImportCharacterModal(ActorAppearanceCapability capability, AppearanceImportOptions options) { List types = [typeof(ActorAppearanceUnion), typeof(AnamnesisCharaFile)]; @@ -292,6 +307,11 @@ public static void ShowImportCharacterModal(ActorAppearanceCapability capability } else if(r is AnamnesisCharaFile appearanceFile) { + if (options.HasFlag(AppearanceImportOptions.Shaders)) + { + BrioHuman.ShaderParams shaderParams = appearanceFile; + ImportShadersFromFile(ref capability._modelShaderOverride, shaderParams); + } _ = capability.SetAppearance(appearanceFile, options); } else if(r is MareCharacterDataFile mareFile) @@ -311,6 +331,11 @@ public static void ShowImportCharacterModal(ActorAppearanceCapability capability } else if(r is AnamnesisCharaFile appearanceFile) { + if(options.HasFlag(AppearanceImportOptions.Shaders)) + { + BrioHuman.ShaderParams shaderParams = appearanceFile; + ImportShadersFromFile(ref capability._modelShaderOverride, shaderParams); + } _ = capability.SetAppearance(appearanceFile, options); } else if(r is MareCharacterDataFile mareFile) diff --git a/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs b/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs index 531987e1..967c0141 100644 --- a/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs +++ b/Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs @@ -240,6 +240,15 @@ private void DrawImportOptions() else _importOptions &= ~AppearanceImportOptions.ExtendedAppearance; } + + bool shaders = _importOptions.HasFlag(AppearanceImportOptions.Shaders); + if(ImGui.Checkbox("Shaders", ref shaders)) + { + if(shaders) + _importOptions |= AppearanceImportOptions.Shaders; + else + _importOptions &= ~AppearanceImportOptions.Shaders; + } } } } From 2dc79d42ffac02e61b1195db1181207cc6ea50d5 Mon Sep 17 00:00:00 2001 From: Bronya-Rand Date: Tue, 18 Feb 2025 07:48:17 +0000 Subject: [PATCH 4/5] chore: cleanup --- Brio/Capabilities/Actor/ActorAppearanceCapability.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs index 16cb5ade..a55dd109 100644 --- a/Brio/Capabilities/Actor/ActorAppearanceCapability.cs +++ b/Brio/Capabilities/Actor/ActorAppearanceCapability.cs @@ -328,7 +328,6 @@ public WeaponModelId GetProp() private unsafe void ApplyShaderOverride() { var shaders = Character.GetShaderParams(); - var test = *shaders; if(shaders != null) { _modelShaderOverride.Apply(ref *shaders); From 82ceb305f4f24bd5def1a8605ea1ee98a5e9e10f Mon Sep 17 00:00:00 2001 From: Kenneth M Date: Wed, 19 Feb 2025 18:17:02 -0600 Subject: [PATCH 5/5] make adjustments --- Brio/Files/ActorFile.cs | 4 ++-- Brio/Game/Scene/SceneService.cs | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Brio/Files/ActorFile.cs b/Brio/Files/ActorFile.cs index c75846f3..b403f189 100644 --- a/Brio/Files/ActorFile.cs +++ b/Brio/Files/ActorFile.cs @@ -33,7 +33,7 @@ public class ActorFile public bool IsProp { get; set; } - public static implicit operator ActorFile(ActorEntity actorEntity) + public static unsafe implicit operator ActorFile(ActorEntity actorEntity) { var appearanceCapability = actorEntity.GetCapability(); var posingCapability = actorEntity.GetCapability(); @@ -42,7 +42,7 @@ public static implicit operator ActorFile(ActorEntity actorEntity) var actorFile = new ActorFile { Name = actorEntity.RawName, - AnamnesisCharaFile = new ActorAppearanceExtended { Appearance = appearanceCapability.CurrentAppearance }, + AnamnesisCharaFile = new ActorAppearanceExtended { Appearance = appearanceCapability.CurrentAppearance, ShaderParams = *appearanceCapability.Character.GetShaderParams() }, PoseFile = posingCapability.GeneratePoseFile(), IsProp = actorEntity.IsProp, PropData = new PropData diff --git a/Brio/Game/Scene/SceneService.cs b/Brio/Game/Scene/SceneService.cs index 3240a441..e69c9eef 100644 --- a/Brio/Game/Scene/SceneService.cs +++ b/Brio/Game/Scene/SceneService.cs @@ -145,12 +145,14 @@ await _framework.RunOnTick(async () => if(actorFile.PropData is not null) modelCapability.Transform += actorFile.PropData.PropTransformDifference; - await appearanceCapability.SetAppearance(actorFile.AnamnesisCharaFile, AppearanceImportOptions.Weapon); - - await _framework.RunOnTick(() => + await _framework.RunOnTick(async () => { - appearanceCapability.AttachWeapon(); - }, delayTicks: 10); + await appearanceCapability.SetAppearance(actorFile.AnamnesisCharaFile, AppearanceImportOptions.Weapon); + await _framework.RunOnTick(() => + { + appearanceCapability.AttachWeapon(); + }, delayTicks: 10); + }, delayTicks: 10); }, delayTicks: 2); } @@ -167,7 +169,7 @@ private async Task ApplyDataToActor(EntityId actorId, ActorFile actorFile) await _framework.RunOnTick(async () => { - await appearanceCapability.SetAppearance(actorFile.AnamnesisCharaFile, AppearanceImportOptions.Default); + await appearanceCapability.SetAppearance(actorFile.AnamnesisCharaFile, AppearanceImportOptions.All); await _framework.RunOnTick(async () => {