Skip to content

Commit

Permalink
feat: loading and saving characters with custom colors (#132)
Browse files Browse the repository at this point in the history
* fix: brio camera not being added to `_createdCameras`

* Update VirtualCameraManager.cs

* feat: save and load custom colors

* chore: cleanup

* make adjustments

---------

Co-authored-by: Kenneth M <KennethMizell@outlook.com>
  • Loading branch information
Bronya-Rand and Minmoose authored Feb 20, 2025
1 parent bcb0492 commit 415b94c
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 12 deletions.
14 changes: 12 additions & 2 deletions Brio/Capabilities/Actor/ActorAppearanceCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
5 changes: 3 additions & 2 deletions Brio/Files/ActorFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -32,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<ActorAppearanceCapability>();
var posingCapability = actorEntity.GetCapability<PosingCapability>();
Expand All @@ -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, ShaderParams = *appearanceCapability.Character.GetShaderParams() },
PoseFile = posingCapability.GeneratePoseFile(),
IsProp = actorEntity.IsProp,
PropData = new PropData
Expand Down
39 changes: 37 additions & 2 deletions Brio/Files/AnamnesisCharaFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions Brio/Game/Actor/Appearance/ActorAppearance.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
}
14 changes: 8 additions & 6 deletions Brio/Game/Scene/SceneService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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 () =>
{
Expand Down
25 changes: 25 additions & 0 deletions Brio/UI/Controls/Stateless/FileUIHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Type> types = [typeof(ActorAppearanceUnion), typeof(AnamnesisCharaFile)];
Expand All @@ -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)
Expand All @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions Brio/UI/Windows/Specialized/ActorAppearanceWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down

0 comments on commit 415b94c

Please sign in to comment.