Skip to content

Commit 83bc32f

Browse files
Merge pull request #40 from PassiveModding/feature/2025-07-update
Feature/2025 07 update
2 parents eebedd5 + a3cc009 commit 83bc32f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1130
-781
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System.Text.Json.Serialization;
2+
using Dalamud.Configuration;
3+
using Dalamud.IoC;
4+
using Dalamud.Plugin;
5+
using Meddle.Plugin.Models;
6+
using Meddle.Plugin.UI.Layout;
7+
using Meddle.Plugin.UI.Windows;
8+
using Meddle.Plugin.Utils;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace Meddle.Plugin;
12+
13+
public partial class Configuration : IPluginConfiguration
14+
{
15+
public const ExportType DefaultExportType = ExportType.GLTF;
16+
17+
[PluginService]
18+
[JsonIgnore]
19+
private IDalamudPluginInterface PluginInterface { get; set; } = null!;
20+
21+
public int Version { get; set; } = 4;
22+
23+
public bool OpenDebugMenuOnLoad { get; set; }
24+
public LogLevel MinimumNotificationLogLevel { get; set; } = LogLevel.Warning;
25+
public bool OpenOnLoad { get; set; }
26+
public bool DisableUserUiHide { get; set; }
27+
public bool DisableAutomaticUiHide { get; set; }
28+
public bool DisableCutsceneUiHide { get; set; } = true;
29+
public bool DisableGposeUiHide { get; set; } = true;
30+
public string ExportDirectory { get; set; } = Plugin.DefaultExportDirectory;
31+
32+
/// <summary>
33+
/// Used to hide names in the UI
34+
/// </summary>
35+
public string PlayerNameOverride { get; set; } = string.Empty;
36+
37+
public LayoutWindow.LayoutConfig LayoutConfig { get; set; } = new();
38+
public ExportConfiguration ExportConfig { get; set; } = new();
39+
public UpdateWindow.UpdateConfig UpdateConfig { get; set; } = new();
40+
41+
public class ExportConfiguration
42+
{
43+
public CacheFileType CacheFileTypes { get; set; }
44+
public ExportType ExportType { get; set; } = DefaultExportType;
45+
46+
[Obsolete("TextureMode is only ever Raw as baking is no longer supported", true)]
47+
public TextureMode TextureMode { get; set; } = TextureMode.Raw;
48+
public SkeletonUtils.PoseMode PoseMode { get; set; } = SkeletonUtils.PoseMode.Local;
49+
50+
[Obsolete("Use PoseMode instead", true)]
51+
public bool ExportPose { get; set; } = true;
52+
public bool RemoveAttributeDisabledSubmeshes { get; set; } = true;
53+
public bool SkipHiddenBgParts { get; set; }
54+
public bool UseDeformer { get; set; } = true;
55+
56+
public bool LimitTerrainExportRange { get; set; }
57+
public float TerrainExportDistance { get; set; } = 500f;
58+
59+
// public enum ExportRootAttachHandling
60+
// {
61+
// PlayerAsAttachChild,
62+
// Exclude,
63+
// }
64+
65+
// public ExportRootAttachHandling RootAttachHandling { get; set; } = ExportRootAttachHandling.Exclude;
66+
67+
public ExportConfiguration Clone()
68+
{
69+
return new ExportConfiguration
70+
{
71+
CacheFileTypes = CacheFileTypes,
72+
ExportType = ExportType,
73+
// ExportPose = ExportPose,
74+
// TextureMode = TextureMode,
75+
PoseMode = PoseMode,
76+
RemoveAttributeDisabledSubmeshes = RemoveAttributeDisabledSubmeshes,
77+
SkipHiddenBgParts = SkipHiddenBgParts,
78+
// RootAttachHandling = RootAttachHandling
79+
UseDeformer = UseDeformer,
80+
LimitTerrainExportRange = LimitTerrainExportRange,
81+
TerrainExportDistance = TerrainExportDistance
82+
};
83+
}
84+
85+
public void SetDefaultCloneOptions()
86+
{
87+
RemoveAttributeDisabledSubmeshes = true;
88+
SkipHiddenBgParts = true;
89+
UseDeformer = true;
90+
}
91+
92+
public void Apply(ExportConfiguration other)
93+
{
94+
CacheFileTypes = other.CacheFileTypes;
95+
ExportType = other.ExportType;
96+
// ExportPose = other.ExportPose;
97+
// TextureMode = other.TextureMode;
98+
PoseMode = other.PoseMode;
99+
RemoveAttributeDisabledSubmeshes = other.RemoveAttributeDisabledSubmeshes;
100+
SkipHiddenBgParts = other.SkipHiddenBgParts;
101+
// RootAttachHandling = other.RootAttachHandling;
102+
UseDeformer = other.UseDeformer;
103+
LimitTerrainExportRange = other.LimitTerrainExportRange;
104+
TerrainExportDistance = other.TerrainExportDistance;
105+
}
106+
}
107+
108+
public event Action? OnConfigurationSaved;
109+
110+
public void Save()
111+
{
112+
PluginInterface.SavePluginConfig(this);
113+
OnConfigurationSaved?.Invoke();
114+
}
115+
}

Meddle/Meddle.Plugin/Models/Composer/ArrayTextureUtil.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using Meddle.Utils.Files.SqPack;
44
using Meddle.Utils.Helpers;
55

6-
namespace Meddle.Plugin.Models.Composer.Textures;
6+
namespace Meddle.Plugin.Models.Composer;
77

88
public static class ArrayTextureUtil
99
{

Meddle/Meddle.Plugin/Models/Composer/CharacterComposer.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Meddle.Utils.Constants;
99
using Meddle.Utils.Export;
1010
using Meddle.Utils.Files.SqPack;
11-
using Meddle.Utils.Helpers;
1211
using Microsoft.Extensions.Logging;
1312
using SharpGLTF.Materials;
1413
using SharpGLTF.Scenes;
@@ -18,31 +17,22 @@ public class CharacterComposer
1817
{
1918
public record SkinningContext(List<BoneNodeBuilder> Bones, BoneNodeBuilder? RootBone, Matrix4x4 Transform);
2019

21-
private readonly Configuration config;
22-
private readonly SqPack pack;
2320
private readonly ComposerCache composerCache;
2421
private readonly Configuration.ExportConfiguration exportConfig;
25-
private readonly CancellationToken cancellationToken;
2622

27-
public CharacterComposer(Configuration config, SqPack pack, ComposerCache composerCache, Configuration.ExportConfiguration exportConfig, CancellationToken cancellationToken = default)
23+
public CharacterComposer(ComposerCache composerCache, Configuration.ExportConfiguration exportConfig)
2824
{
29-
this.config = config;
30-
this.pack = pack;
3125
this.composerCache = composerCache;
3226
this.exportConfig = exportConfig;
33-
this.cancellationToken = cancellationToken;
3427
}
3528

36-
public CharacterComposer(Configuration config, SqPack pack, Configuration.ExportConfiguration exportConfig, string outDir, CancellationToken cancellationToken = default)
29+
public CharacterComposer(SqPack pack, Configuration.ExportConfiguration exportConfig, string outDir)
3730
{
38-
this.config = config;
39-
this.pack = pack;
4031
this.exportConfig = exportConfig;
4132
Directory.CreateDirectory(outDir);
4233
var cacheDir = Path.Combine(outDir, "cache");
4334
Directory.CreateDirectory(cacheDir);
4435
composerCache = new ComposerCache(pack, cacheDir, exportConfig);
45-
this.cancellationToken = cancellationToken;
4636
}
4737

4838
private void HandleModel(ParsedCharacterInfo characterInfo, ParsedModelInfo m, SceneBuilder scene, SkinningContext skinningContext)

Meddle/Meddle.Plugin/Models/Composer/ComposerCache.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System.Collections.Concurrent;
2-
using Meddle.Plugin.Models.Composer.Materials;
3-
using Meddle.Plugin.Models.Composer.Textures;
42
using Meddle.Plugin.Models.Layout;
53
using Meddle.Plugin.Utils;
64
using Meddle.Utils.Export;
@@ -201,7 +199,7 @@ private string CacheFile(string fullPath)
201199
return cachePath;
202200
}
203201

204-
private string CacheTexture(string fullPath)
202+
public string CacheTexture(string fullPath)
205203
{
206204
var cachePath = GetCacheFilePath(fullPath);
207205
var pngCachePath = cachePath + ".png";
@@ -291,6 +289,21 @@ public MaterialBuilder ComposeMaterial(string mtrlPath,
291289
// remove full path prefix, get only dir below cache dir.
292290
material.SetProperty($"{texture.Key}_PngCachePath", Path.GetRelativePath(cacheDir, cachePath));
293291
}
292+
293+
if (characterInfo != null)
294+
{
295+
if (characterInfo.CustomizeData.DecalPath != null)
296+
{
297+
var decalCachePath = CacheTexture(characterInfo.CustomizeData.DecalPath);
298+
material.SetProperty("Decal_PngCachePath", Path.GetRelativePath(cacheDir, decalCachePath));
299+
}
300+
301+
if (characterInfo.CustomizeData.LegacyBodyDecalPath != null)
302+
{
303+
var legacyDecalCachePath = CacheTexture(characterInfo.CustomizeData.LegacyBodyDecalPath);
304+
material.SetProperty("LegacyBodyDecal_PngCachePath", Path.GetRelativePath(cacheDir, legacyDecalCachePath));
305+
}
306+
}
294307

295308
materialBuilder.Extras = material.ExtrasNode;
296309
return materialBuilder;

Meddle/Meddle.Plugin/Models/Composer/InstanceComposer.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Numerics;
22
using System.Text.Json;
33
using System.Text.Json.Nodes;
4-
using Meddle.Plugin.Models.Composer.Textures;
54
using Meddle.Plugin.Models.Layout;
65
using Meddle.Plugin.Models.Structs;
76
using Meddle.Plugin.Utils;
@@ -13,9 +12,6 @@
1312
using Microsoft.Extensions.Logging;
1413
using SharpGLTF.Materials;
1514
using SharpGLTF.Scenes;
16-
using SharpGLTF.Schema2;
17-
using SharpGLTF.Transforms;
18-
using SharpGLTF.Validation;
1915

2016
namespace Meddle.Plugin.Models.Composer;
2117

@@ -37,7 +33,6 @@ public ExportProgress(int total, string? name)
3733

3834
public class InstanceComposer
3935
{
40-
private readonly Configuration config;
4136
private readonly SqPack pack;
4237
private readonly Configuration.ExportConfiguration exportConfig;
4338
private readonly string outDir;
@@ -46,13 +41,11 @@ public class InstanceComposer
4641
private readonly ComposerCache composerCache;
4742

4843
public InstanceComposer(
49-
Configuration config,
5044
SqPack pack,
5145
Configuration.ExportConfiguration exportConfig,
5246
string outDir,
5347
CancellationToken cancellationToken)
5448
{
55-
this.config = config;
5649
this.pack = pack;
5750
this.exportConfig = exportConfig;
5851
this.outDir = outDir;
@@ -214,13 +207,40 @@ public void Compose(ParsedInstance[] instances, ExportProgress progress)
214207

215208
if (parsedInstance is ParsedCameraInstance parsedCameraInstance)
216209
{
217-
return ComposeCameraInstance(parsedCameraInstance, scene, rootProgress);
210+
return ComposeCameraInstance(parsedCameraInstance, scene);
211+
}
212+
213+
if (parsedInstance is ParsedWorldDecalInstance parsedDecalInstance)
214+
{
215+
return ComposeDecalInstance(parsedDecalInstance, scene);
218216
}
219217

220218
return null;
221219
}
222-
223-
private NodeBuilder? ComposeCameraInstance(ParsedCameraInstance parsedCameraInstance, SceneBuilder scene, ExportProgress rootProgress)
220+
private NodeBuilder? ComposeDecalInstance(ParsedWorldDecalInstance parsedWorldDecalInstance, SceneBuilder scene)
221+
{
222+
var root = new NodeBuilder($"{parsedWorldDecalInstance.Type}_{parsedWorldDecalInstance.Id}");
223+
var cachedDiffuse = Path.GetRelativePath(cacheDir, composerCache.CacheTexture(parsedWorldDecalInstance.Diffuse.FullPath));
224+
var cachedNormal = Path.GetRelativePath(cacheDir, composerCache.CacheTexture(parsedWorldDecalInstance.Normal.FullPath));
225+
var cachedSpecular = Path.GetRelativePath(cacheDir, composerCache.CacheTexture(parsedWorldDecalInstance.Specular.FullPath));
226+
var decalData = new
227+
{
228+
DiffusePath = parsedWorldDecalInstance.Diffuse.FullPath,
229+
DiffuseCachePath = cachedDiffuse,
230+
NormalPath = parsedWorldDecalInstance.Normal.FullPath,
231+
NormalCachePath = cachedNormal,
232+
SpecularPath = parsedWorldDecalInstance.Specular.FullPath,
233+
SpecularCachePath = cachedSpecular,
234+
};
235+
236+
root.Extras = JsonNode.Parse(JsonSerializer.Serialize(decalData, MaterialComposer.JsonOptions));
237+
root.SetLocalTransform(parsedWorldDecalInstance.Transform.AffineTransform, true);
238+
scene.AddNode(root);
239+
240+
return root;
241+
}
242+
243+
private NodeBuilder ComposeCameraInstance(ParsedCameraInstance parsedCameraInstance, SceneBuilder scene)
224244
{
225245
var perspective = new CameraBuilder.Perspective(aspectRatio: parsedCameraInstance.AspectRatio, fovy: parsedCameraInstance.FoV, znear: 0.01f, zfar: 1000f);
226246
var root = new NodeBuilder($"{parsedCameraInstance.Type}_{parsedCameraInstance.Id}")
@@ -245,7 +265,7 @@ public void Compose(ParsedInstance[] instances, ExportProgress progress)
245265
Plugin.Logger?.LogWarning("Character instance {InstanceId} has no character info", instance.Id);
246266
return null;
247267
}
248-
var characterComposer = new CharacterComposer(config, pack, composerCache, exportConfig, cancellationToken);
268+
var characterComposer = new CharacterComposer(composerCache, exportConfig);
249269
var root = new NodeBuilder($"{instance.Type}_{instance.Name}_{instance.Id}");
250270

251271
var characterProgress = new ExportProgress(instance.CharacterInfo.Models.Length, "Character Meshes");

Meddle/Meddle.Plugin/Models/Composer/MaterialComposer.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
using System.Text.Json;
33
using System.Text.Json.Nodes;
44
using System.Text.Json.Serialization;
5-
using ImGuiNET;
6-
using Meddle.Plugin.Models.Composer.Materials;
75
using Meddle.Plugin.Models.Layout;
8-
using Meddle.Plugin.Services;
96
using Meddle.Plugin.Utils;
107
using Meddle.Utils.Constants;
118
using Meddle.Utils.Export;
@@ -20,8 +17,6 @@ namespace Meddle.Plugin.Models.Composer;
2017
public class MaterialComposer
2118
{
2219
private readonly MtrlFile mtrlFile;
23-
private readonly string mtrlPath;
24-
private readonly ShaderPackage shaderPackage;
2520
private readonly Dictionary<uint, float[]> mtrlConstants = new();
2621
private readonly Dictionary<ShaderCategory, uint> shaderKeyDict = new();
2722
private readonly Dictionary<string, object> additionalProperties = new();
@@ -37,6 +32,9 @@ public void SetPropertiesFromCharacterInfo(ParsedCharacterInfo characterInfo)
3732

3833
SetProperty("Highlights", customizeData.Highlights);
3934
SetProperty("LipStick", customizeData.LipStick);
35+
SetProperty("FacePaintReversed", customizeData.FacePaintReversed);
36+
SetProperty("LegacyBodyDecalPath", customizeData.LegacyBodyDecalPath ?? "");
37+
SetProperty("DecalPath", customizeData.DecalPath ?? "");
4038
SetProperty("CustomizeData", JsonNode.Parse(JsonSerializer.Serialize(customizeData, JsonOptions))!);
4139

4240
SetProperty("LeftIrisColor", customizeParameter.LeftColor.AsFloatArray());
@@ -45,10 +43,11 @@ public void SetPropertiesFromCharacterInfo(ParsedCharacterInfo characterInfo)
4543
SetProperty("SkinColor", customizeParameter.SkinColor.AsFloatArray());
4644
SetProperty("MeshColor", customizeParameter.MeshColor.AsFloatArray());
4745
SetProperty("LipColor", customizeParameter.LipColor.AsFloatArray());
48-
SetProperty("FacePaintUVOffset", customizeParameter.FacePaintUVOffset);
49-
SetProperty("FacePaintUVMultiplier", customizeParameter.FacePaintUVMultiplier);
46+
SetProperty("FacePaintUVOffset", customizeParameter.FacePaintUvOffset);
47+
SetProperty("FacePaintUVMultiplier", customizeParameter.FacePaintUvMultiplier);
5048
SetProperty("MuscleTone", customizeParameter.MuscleTone);
5149
SetProperty("OptionColor", customizeParameter.OptionColor.AsFloatArray());
50+
SetProperty("DecalColor", customizeParameter.DecalColor.AsFloatArray());
5251
SetProperty("CustomizeParameters", JsonNode.Parse(JsonSerializer.Serialize(customizeParameter, JsonOptions))!);
5352
}
5453

@@ -78,8 +77,6 @@ public void SetPropertiesFromColorTable(IColorTableSet colorTableSet)
7877
public MaterialComposer(MtrlFile mtrlFile, string mtrlPath, ShaderPackage shaderPackage)
7978
{
8079
this.mtrlFile = mtrlFile;
81-
this.mtrlPath = mtrlPath;
82-
this.shaderPackage = shaderPackage;
8380
SetShaderKeys();
8481
SetConstants();
8582
SetSamplers();

Meddle/Meddle.Plugin/Models/Composer/RawMaterialBuilder.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
using Meddle.Plugin.Models.Composer.Textures;
2-
using Meddle.Utils.Helpers;
3-
using Meddle.Utils.Materials;
1+
using Meddle.Utils.Materials;
42
using SharpGLTF.Materials;
53

6-
namespace Meddle.Plugin.Models.Composer.Materials;
4+
namespace Meddle.Plugin.Models.Composer;
75

86
public class RawMaterialBuilder : MaterialBuilder, IVertexPaintMaterialBuilder
97
{

Meddle/Meddle.Plugin/Models/Composer/TransformSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static float GetSingleNamed(this ref Utf8JsonReader reader)
9393
}
9494
else
9595
{
96-
value = float.Parse(str);
96+
value = float.Parse(str!);
9797
}
9898
}
9999
else

0 commit comments

Comments
 (0)