Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: loading and saving characters with custom colors #132

Merged
merged 6 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -18,7 +18,7 @@

namespace Brio.Game.Scene;

public class SceneService(EntityManager _entityManager, VirtualCameraManager _virtualCameraManager, PosingService _posingService, ActorSpawnService _actorSpawnService, IClientState _clientState, IFramework _framework)

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_posingService' is unread.

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_actorSpawnService' is unread.

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_clientState' is unread.

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_posingService' is unread.

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_actorSpawnService' is unread.

Check warning on line 21 in Brio/Game/Scene/SceneService.cs

View workflow job for this annotation

GitHub Actions / build

Parameter '_clientState' is unread.
{
public bool IsLoading { get; private set; }

Expand Down Expand Up @@ -145,12 +145,14 @@
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 @@

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
Loading